#!/usr/bin/python3

"""
    workspace++

    ws_register

    python version of ws_register command, no privileges necessary

    create links for all workspaces in a selected directory, delete
    links to no longer valid workspaces.
    Reads new YAML configuration files and new YAML workspace database.

    differences to old workspace version
    - usage of YAML file format
    - more options for administrator (configured and root)
            + list expired/moved workspaces

    (c) Holger Berger 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020
    (c) Bernd Krisckok 2017
    (c) Christoph Niethammer 2021-2022

    workspace++ is based on workspace by Holger Berger, Thomas Beisel and Martin Hecht

    workspace++ is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    workspace++ is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with workspace++.  If not, see <http://www.gnu.org/licenses/>.

"""

from __future__ import print_function

import os, os.path, pwd, grp, sys
import glob
import argparse
import pathlib

# read a single line from ws.conf of the form: pythonpath: /path/to/python
def read_python_conf():
    for l in open("/etc/ws.conf","r"):
        if 'pythonpath' in l:
            key = l.split(":")[0].strip()
            value = l.split(":")[1].strip()
            if key == 'pythonpath':
                if os.path.isdir(value):
                    sys.path.insert(0,value)
                    break
                else:
                    print("Warning: Invalid pythonpath in ws.conf", file=sys.stderr)

read_python_conf()

import yaml


# who are we?
uid = os.getuid()
username = pwd.getpwuid(uid).pw_name


# load config file
config = yaml.safe_load(open('/etc/ws.conf'))

parser = argparse.ArgumentParser(description='Creates/updates symbolic links to workspaces in a directory')
parser.add_argument('directory', metavar='directory', type=pathlib.Path, help='directory in which links shall be created/updated')
parser.add_argument('-F', '--filesystem', help='filesystem to search workspaces in')
options = parser.parse_args()


dirname = str(options.directory)


# all filesystems or a selected one?
if options.filesystem:
    if options.filesystem in config['workspaces']:
        filesystems = [options.filesystem]
    else:
        print("Error: Invalid filesystem specified", file=sys.stderr)
        sys.exit(-1)
else:
    filesystems = config['workspaces'].keys()

# reduce list to allowed filesystems
legal_filesystems = []
for fs in filesystems:
    userok = True
    if 'user_acl' in config['workspaces'][fs] or 'group_acl' in config['workspaces'][fs]:
        userok = False
    if 'group_acl' in config['workspaces'][fs]:
        groups = os.getgrouplist(username, os.getgid())
        for gid in groups:
            groupname = grp.getgrgid(gid).gr_name
            if groupname in config['workspaces'][fs]['group_acl']:
                userok = True
                break
    if 'user_acl' in config['workspaces'][fs]:
            if username in config['workspaces'][fs]['user_acl']:
                userok = True
    # admin can see workspaces from anywhere, but can also restrict
    if userok:
        legal_filesystems.append(fs)


# main loop


if not os.path.isdir(dirname):
    os.makedirs(dirname)

for fs in legal_filesystems:
    if not os.path.isdir(dirname+"/"+fs):
        os.mkdir(dirname+"/"+fs)
    keeplist = []
    dbfilename = '%s/%s-*' % (config["workspaces"][fs]['database'], username)
    wsdirs = []
    for fname in glob.glob(dbfilename):
        f = yaml.safe_load(open(fname))
        try:
            wsname = f['workspace']
        except TypeError:
            f = open(fname).readlines()
            wsname = f[1][:-1]
        linkpath = dirname + "/" + fs + "/" + os.path.basename(wsname)
        keeplist.append(linkpath)
        if not os.path.exists(linkpath) and not os.path.islink(linkpath):
            os.symlink(wsname, linkpath)
    # delete links not beeing workspaces anymore
    for f in glob.glob(dirname + "/" + fs + "/*"):
        if os.path.islink(f):
            if not f in keeplist:
                print("removing link ", f)
                os.unlink(f)
            else:
                print("keeping link ", f)

