Commit a11f570f authored by Thomas Souvignet's avatar Thomas Souvignet Committed by Sébastien Luttringer
Browse files

rework rights commands to handle new system

parent 99d0a3cc
Loading
Loading
Loading
Loading
+72 −77
Original line number Diff line number Diff line
@@ -5,101 +5,96 @@
CloudControl right releated commands
'''

import tempfile
import subprocess
import os
import re
import pprint

from cccli.exception import *
from sjrpc.core.exceptions import *
from cccli.printer import Printer, color
from cccli.command import Command, TqlCommand
from cccli.command import Command, RemoteCommand

class Command_rights(TqlCommand):
class Command_rights(RemoteCommand):
    '''List account rights'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
        self.set_usage("%prog [options] [tql]")
        self.tql_filter += "&a&r=cli"
        self.remove_option("--direct")
        self.remove_option("--quiet")
        self.remove_option("--index")
        RemoteCommand.__init__(self, cli, argv0)
        self.set_usage("%prog [options]")

    def __call__(self, argv):
        # Parse argline
        self.parse_args(argv)
        # append current login if nothing asked
        if len(self.args) == 0:
            tql = "a=%s"%self.cli.settings["login"]
        else:
            tql = "".join(self.args)
        # ask server
        al = self.rpccall("rights", tql, _direct=True, _status=False)
        al = self.rpc.call("loadrights")
        # display answer
        for (a, rl) in al.items():
            self.printer.out("%sa:%s%s%s"%(self.tdtc("a"), self.tdc("a"), a, color["reset"]))
            for i,r in enumerate(rl):
                tags = " ".join([ "%s%s:%s%s"%(self.tdtc(t), t, self.tdc(t), v) for (t,v) in r.items() ])
                self.printer.out("[%s] %s%s"%(i,tags, color["reset"]))

    def remote_functions(self):
        return set(('rights',))


class Command_addright(TqlCommand):
    '''Add or edit account right'''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
        self.tql_filter += "&a&r=cli"
        self.set_usage('''%prog [options] <account tql> <right tql> <method> <target> [index]

<method> is the name of the rpc command to allow
<target> can be allow or deny''')

    def __call__(self, argv):
        # argv check
        self.parse_args(argv)
        if len(self.args) == 4:
            self.args.append(None)
        elif len(self.args) == 5:
            self.args[4] = int(self.args[4])
        else:
            raise cmdBadArgument()
        # rpc call
        self.rpccall("addright",
                    self.args[0],
                    self.args[1],
                    self.args[2],
                    self.args[3],
                    self.args[4])
        for r in al:
            self.printer.out("%(match)s\t%(method)s\t%(tql)s\t%(action)s" % r)

    def remote_functions(self):
        return set(('addright',))
        return set(('loadrights',))


class Command_delright(TqlCommand):
    '''Delete account right'''
class Command_editrights(RemoteCommand):
    ''' Edit rights '''

    def __init__(self, cli, argv0):
        TqlCommand.__init__(self, cli, argv0)
        self.tql_filter += "&a&r=cli"
        self.set_usage("%prog [options] <tql> <index> ...\n<index> * means all")
        RemoteCommand.__init__(self, cli, argv0)
        self.set_usage("%prog [options]")

    def indent(self, rights, space):
        indents = {}
        fields = ('match', 'method', 'tql', 'action')
        for f in fields:
            cur = 0
            for r in rights:
                cur = max(cur, len(r[f]))
            indents[f] = cur + space
        return indents

    def edit(self, out):
        editor = os.environ.get('EDITOR', '/bin/nano')
        subprocess.call([editor, out.name])
        out.seek(0)
        new_rights = []
        nb = 1
        for line in out:
            line = line.lstrip().rstrip()
            if len(line) == 0 or line.startswith('#'):
                continue
            items = line.split()
            if len(items) < 4 or (len(items) > 4 and not items[5].startswith('#')):
                while True:
                    s = raw_input("Error: bad file format at line %d, do you want to reedit ? [yes/no] " % nb)
                    answer = s.lstrip().rstrip()
                    if answer == 'yes':
                        return self.edit(out)
                    elif answer == 'no':
                        raise cmdError('Bad file format at line %d' % nb)
                    else:
                        self.printer.out("Please answer by yes or no")
            new_rights.append({'match': items[0], 'method': items[1], 'tql': items[2], 'action': items[3]})
            nb += 1
        return new_rights

    def __call__(self, argv):
        # argv check
        self.parse_args(argv)
        if len(self.args) < 2:
            raise cmdBadArgument("No enough argument")
        # building list of index
        try:
            l = [ int(x) for x in self.args[1:] if x != "*" ]
            # we sort list in reverse order to avoid removing error
            l.sort()
            l.reverse()
        except ValueError as e:
            raise cmdBadArgument("Indexes must be numbers")
        # if all is detected
        if "*" in self.args[1:]:
            self.rpccall("delright", self.args[0], None)
        else:
            self.rpccall("delright", self.args[0], _arg_list=l)
        with tempfile.NamedTemporaryFile(dir='/tmp') as temp:
            al = self.rpc.call("loadrights")
            indents = self.indent(al, 2)
            temp.write("# match%smethod%stql%saction\n" % (' '*(indents['match'] - len('match') - 2),
                                                             ' '*(indents['method'] - len('method')),
                                                             ' '*(indents['tql'] - len('tql'))))
            for r in al:
                temp.write("%s%s%s%s%s%s%s\n" % (r['match'],
                                                   ' '*(indents['match'] - len(r['match'])),
                                                   r['method'],
                                                   ' '*(indents['method'] - len(r['method'])),
                                                   r['tql'],
                                                   ' '*(indents['tql'] - len(r['tql'])),
                                                   r['action']))
            temp.flush()
            new_rights = self.edit(temp)
            temp.close()
            self.rpc.call('saverights', new_rights)

    def remote_functions(self):
        return set(('delright',))
        return set(('saverights',))