########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Server/Client/Commands/Set/Acl.py,v 1.14 2004/09/23 20:53:32 mbrown Exp $
"""
Implementation of '4ss set acl' command
(functions defined here are used by the Ft.Lib.CommandLine framework)

Copyright 2004 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""

__doc__ = """This command sets access control info for a resource in a \
4Suite repository. It will prompts for specific permissions to add or \
modify. Requires write access on the resource. If necessary, you will \
be prompted first for credentials and access info to connect to the \
repository."""

from Ft.Server.Client.Commands import CommandUtil
from Ft.Server.Common import AclConstants


def Run(options,args):
    commit = False
    repo = CommandUtil.GetRepository(options, '4ss.set.acl')
    if repo is not None:
        try:
            res = repo.fetchResource(args['path'])
            done = False
            while not done:
                #Display the current ACL
                print "Current ACL Settings for: %s" % res.getAbsolutePath()
                acl = res.getAcl()
                for name, key in (('Read', AclConstants.READ_ACCESS),
                                 ('Write', AclConstants.WRITE_ACCESS),
                                 ('Write user model', AclConstants.WRITE_USER_MODEL_ACCESS),
                                 ('Execute', AclConstants.EXECUTE_ACCESS),
                                 ('Delete', AclConstants.DELETE_ACCESS),
                                 ('Change Permissions', AclConstants.CHANGE_PERMISSIONS_ACCESS),
                                 ('Change Owner', AclConstants.CHANGE_OWNER_ACCESS),
                                 ):

                    if acl.has_key(key):
                        print "%s ACL" % name
                    else:
                        print "%s ACL (inherited)" % name
                    for ident,allowed in res.getAcl(key).items():
                        if ident[0] == ':': ident = ident[1:]
                        print "  %s --> %s" % (ident, allowed == AclConstants.ALLOWED and 'allowed' or 'denied')


                print "Please enter an action to perform on %s:" % res.getAbsolutePath()
                print "(s)et - reset an access level, then add a new identifier at that level"
                print "(a)dd - add a new id to an access level without otherwise affecting the level"
                print "(r)emove - remove an id from an access level without otherwise affecting the level"
                print "(q)uit and save"
                print "(e)xit without save"

                while 1:
                    cmd = raw_input(">> ")
                    if not cmd or cmd.lower() not in ['s', 'a', 'r', 'q', 'e']:
                        print "Invalid command"
                    else:
                        cmd = cmd.lower()
                        break

                if cmd == 'e':
                    done = True
                elif cmd == 'q':
                    commit = True
                    done = True
                else:
                    phrase = 'set'
                    if cmd == 'a': phrase = 'add'
                    if cmd == 'r':
                        print 'Warning: you cannot override permissions inherited from the parent using "remove".  In order to override inherited permissions, use "set" to add a "denied" access entry, instead.'
                        phrase = 'remove'
                    print
                    print "Please enter the type of access: read | write | write user model | execute | delete | change owner | change permissions"
                    print
                    aclKey = raw_input("Please enter the type of access: ")
                    if not aclKey:
                        print "Invalid Access type"
                        continue

                    aclIdent = raw_input("Please enter the identifier (i.e. username/groupname) to %s: " % phrase)
                    if not aclIdent:
                        print "Invalid Acl identifier"
                        continue

                    if cmd != 'r':
                        allowed = raw_input("Should %s be allowed %s on %s (yes/no): " % (aclIdent, aclKey, res.getPath()))
                        if not allowed:
                            print "Invalid Response"
                            continue
                        allowed = allowed.lower()
                        if allowed in ['y', 'yes']:
                            allowed = AclConstants.ALLOWED
                        elif allowed in ['n', 'no']:
                            allowed = AclConstants.DENIED
                        else:
                            print "Invalid Response: %s" % allowed
                            continue

                    if cmd == 's':
                        res.setAcl(aclKey, aclIdent, allowed)
                    elif cmd == 'r':
                        res.removeAcl(aclKey, aclIdent)
                    elif cmd == 'a':
                        res.addAcl(aclKey, aclIdent, allowed)

        finally:
            try:
                if commit:
                    repo.txCommit()
                else:
                    repo.txRollback()
            except:
                pass

    return


def Register():
    from Ft.Lib.CommandLine import Options, Command, Arguments
    cmd = Command.Command('acl',
                          'Set access control info for a resource in a repository',
                          '/path/to/doc.xml',
                          __doc__,
                          function = Run,
                          arguments = [Arguments.RequiredArgument('path',
                                                                  "the path of the resource",
                                                                  str),
                                       ],

                          fileName = __file__,
                          )
    return cmd
