#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Univention Management Console
#  Create UMC ACLs for local user
#
# Like what you see? Join us!
# https://www.univention.com/about-us/careers/vacancies/
#
# Copyright 2006-2023 Univention GmbH
#
# https://www.univention.de/
#
# All rights reserved.
#
# The source code of this program is made available
# under the terms of the GNU Affero General Public License version 3
# (GNU AGPL V3) as published by the Free Software Foundation.
#
# Binary versions of this program provided by Univention to you as
# well as other copyrighted, protected or trademarked materials like
# Logos, graphics, fonts, specific documentations and configurations,
# cryptographic keys etc. are subject to a license agreement between
# you and Univention and not subject to the GNU AGPL V3.
#
# In the case you use this program under the terms of the GNU AGPL V3,
# the program is provided 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 Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <https://www.gnu.org/licenses/>.

from __future__ import print_function

import json
import os
import pickle
import sys
from argparse import ArgumentParser

import six

import univention.config_registry as ucr
from univention.management.console.acl import Rule


_cache_dir = '/var/cache/univention-management-console/acls'

configRegistry = ucr.ConfigRegistry()
configRegistry.load()

parser = ArgumentParser()
parser.add_argument('-u', '--user', action='store', dest='user', default='root', help='define the user who should get access [default: %(default)s]')
parser.add_argument('-c', '--command', action='append', dest='commands', default=[], help='defines a list of UMC commands (or patterns)')
parser.add_argument('-f', '--flavor', action='store', dest='flavor', default='*', help='defines the flavor')
parser.add_argument('-H', '--host', action='store', dest='host', default=configRegistry['hostname'], help='on which host the commands are allowed [default: %(default)s]')
parser.add_argument('operation', choices=('show', 'reset', 'allow', 'remove', 'upgrade-to-json'))

options = parser.parse_args()

operation = options.operation
filename = os.path.join(_cache_dir, options.user.replace('/', ''))

acls = []
if os.path.isfile(filename) and operation in ('show', 'allow', 'remove', 'upgrade-to-json'):
    try:
        with open(filename) as fd:
            acls = json.load(fd)
        print('loaded json file', filename)
    except Exception:
        if six.PY2:
            try:
                with open(filename) as fd:
                    acls = pickle.load(fd)  # noqa: S301
                print('loaded pickle file', filename)
            except Exception:
                acls = []

# convert old format
new_acls = []
if isinstance(acls, dict):
    for rule in acls['allow']:
        rule = Rule(rule)
        if rule not in new_acls:
            new_acls.append(rule)
else:  # check for duplicates
    for rule in acls:
        rule = Rule(rule)
        if rule not in new_acls:
            new_acls.append(rule)
acls = new_acls

if operation == 'show':
    print('Username: %s' % options.user)
    for acl in acls:
        print('     Host: %-10s Command: %-15s Flavor: %-14s Options: %s' % (acl.host, acl.command, acl.flavor, str(acl.options)))
    sys.exit(0)
elif operation == 'allow':
    for command in options.commands:
        rule = Rule({'fromUser': False, 'host': options.host, 'command': command, 'flavor': options.flavor})
        if rule not in acls:
            acls.append(rule)
            print('info: rule %s appended' % command)
        else:
            print('warning: rule %s already exists' % command)
elif operation == 'remove':
    acls = [item for item in acls if item.command not in options.commands]
elif operation == 'reset':
    pass  # nothing todo as the acls dict is already "reset" and will be written in the next step

with open(filename, 'w') as fd:
    fd.write(json.dumps(acls))
