#!/usr/bin/python3

"""
    workspace++

    ws_find

    python version of ws_find command, no privileges necessary

    print workspace path for a given workspace name

    differences to old workspace version
    - usage if 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, 2026
    (c) Christoph Niethammer 2024

    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
from optparse import OptionParser


# 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()
gid = os.getgid()
user = pwd.getpwuid(uid)[0]
group = grp.getgrgid(gid)[0]
# groups = [grp.getgrgid(gid_tmp)[0] for gid_tmp in os.getgroups()]
groups = []
for gid_tmp in os.getgroups():
    try:
        groups.append(grp.getgrgid(gid_tmp)[0])
    except KeyError:
        print(f"group <{gid_tmp}> could not be resolved - ignoring", file=sys.stderr)


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


usage = "Usage: ws_find [options] [workspacename]"

# option configuration
parser = OptionParser(usage=usage, version="workspace version 1.6.0")
parser.add_option("-F", "--filesystem", dest="filesystem", help="filesystem to search workspace in")
parser.add_option("-l", "--list", action="store_true", dest="list", default=False, help="list valid filesystem names")
(options, args) = parser.parse_args()


# all filesystems or a selected one?
if options.filesystem:
    if options.filesystem in config["workspaces"]:
        filesystems = [options.filesystem]
    else:
        print("Error: no such filesystem.")
        sys.exit(-1)
else:
    filesystems = config["workspaces"].keys()

# reduce list to allowed filesystems
legal = []
for f in filesystems:
    userok = True
    if "user_acl" in config["workspaces"][f] or "group_acl" in config["workspaces"][f]:
        userok = False
    if "group_acl" in config["workspaces"][f]:
        for g in groups:
            if g in config["workspaces"][f]["group_acl"]:
                userok = True
                break
            if group in config["workspaces"][f]["group_acl"]:
                userok = True
    if "user_acl" in config["workspaces"][f]:
        if user in config["workspaces"][f]["user_acl"]:
            userok = True
    # admin can see workspaces from anywhere, but can also restrict
    if userok:
        legal.append(f)

# list workspaces (only allowed ones), exit after done
if options.list:
    print("available filesystems:")
    for i in legal:
        print(i)
    sys.exit(0)

if len(args) == 0:
    print(usage, file=sys.stderr)
    sys.exit(-1)

wsname = args[0]

# main loop
found = False
for fs in legal:
    dbfilename = "%s/%s-%s" % (config["workspaces"][fs]["database"], user, wsname)
    try:
        f = yaml.safe_load(open(dbfilename))
    except IOError:
        continue
    try:
        wsdir = f["workspace"]
    except TypeError:
        # fallback to old db format
        try:
            f = open(dbfilename)
            extensions = int(f.readline())
            wsdir = f.readline()[:-1]
            f.close()
        except IOError:
            continue
    print(wsdir)
    found = True
    # break
if not found:
    print("Error: no such workspace", file=sys.stderr)
    sys.exit(-1)
