#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Univention Management Console
#  Create UMC ACLs for local user
#
# Copyright 2006-2022 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 pickle
import os
from argparse import ArgumentParser
import sys
import json

import six

from univention.management.console.acl import Rule

import univention.config_registry as ucr

_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)
				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))
