import web
from decorators import i18n
from model import User, Action
import types

def has_permissions(actions=None):
    '''
    Checks whether the current user (which may well be the anonymous user) has been granted
    permission to execute a task related to a given list of actions. The argument can be either
    a string with a single action name or a list of strings of action identifiers.

    To check these permissions, we retrieve all the roles to which the current user belongs,
    and then check if the roles grant the user permissions for the given actions.

    Note that if any of the given action names is not defined in the database, an exception will
    be raised, because it's a bug that the develop should fix: actions are managed by the plugin
    developer and the usage of this decorator.
    '''
    if actions == None:
        actions = []
    elif type(actions) is types.UnicodeType:
        actions = [actions]
    elif type(actions) is not types.ListType:
        raise TypeError(_("actions argument must be a string or a list of strings"))

    def decorator(actions, f):
        def df(*args, **kwargs):
            roles = set(User.current().roles)
            has_perms = True
            for action_name in actions:
                action_obj = web.ctx.orm.query(Action).filter_by(name = action_name).first()
                action_roles = set(action_obj.roles)
                if not action_roles.intersection(roles):
                    has_perms = False
                    break
            if has_perms:
                return f(*args, **kwargs)
            else:
                raise web.seeother('/user/login')
        return df
    return lambda f: decorator(actions, f)


def authenticated(function):
    '''
    If the user is authenticated it allows access to the resource, else ir redirect to login page
    '''
    def decorated(*args, **kwargs):
        if web.ctx.session.has_key('loggedin'):
            return function(*args, **kwargs)
        else:
            raise web.seeother('/user/login?next=%s' % web.ctx.path)
    return decorated


def admin(function):
    def decorated(*args, **kwargs):
        from user.views import get_user
        user = get_user()
        if user.super_user:
            return function(*args, **kwargs)
        else:
            raise web.seeother('/user/login?next=%s' % web.ctx.path)
    return decorated
