class Authorisation:
    """
    Authorisation class is responsible for managing resource usage rules.
    """
    def __init__(self):
        self.basedb = BaseDB()
        self.accounting = Accounting()

    def verify(self, username, resource_name, resource_category):
        """
        Returns True if username is allowed to access resource.
        """
        resources = list(
            self.basedb.get(AUTHORISATION_COLLECTION, AUTHORISATION_KEY,
                            username))
        for item in resources:
            for elem in item['resource_rule']:
                LOG.info('elem: %s' % elem)
                if elem['resource_name'] == resource_name and\
                    elem['resource_category'] == resource_category:
                    return True
        return False

    def update_resource_item(self, username, resource_name, resource_category):
        """
        Add 1 to used field.
        """
        resources = self.basedb.get(AUTHORISATION_COLLECTION,
                                    AUTHORISATION_KEY, username)
        for item in resources:
            for elem in item['resource_rule']:
                LOG.info('elem: %s' % elem)
                if elem['resource_name'] == resource_name and\
                        elem['resource_category'] == resource_category:
                    old_item = copy.deepcopy(item)
                    elem['used'] = elem['used'] + 1
                    res = self.basedb.update(AUTHORISATION_COLLECTION,
                                             AUTHORISATION_KEY, username,
                                             AUTHORISATION_ITEM, old_item,
                                             item)
        return res

    def use_resource(self, username, resource_name, resource_category):
        """
        This method is called in order to user a determined resource. Thus, it
        is responsible for triggering the accounting mechanism and updating the
        database to increment the number of times that resource was used. 
        """
        if self.verify(username, resource_name, resource_category):
            # add 1 to used field
            self.update_resource_item(username, resource_name,
                                      resource_category)
            # account it
            msg = "Resource " + resource_name + " used by: " + username + "."
            LOG.info('msg: %s' % msg)
            category = INFO
            self.accounting.register(username, msg, category)
            return {'msg': msg}
        return None

    def validate_rule(self, rule):
        """
        Validates authorisation object.
        """

        SCHEMA = {
            'type': 'object',
            'properties': {
                'resource_name': {
                    'type': 'string',
                    'minLength': 1,
                    'maxLength': 50
                },
                'resource_category': {
                    'type': 'string',
                    'minLength': 1,
                    'maxLength': 50
                },
                'max_used': {
                    'type': 'number'
                },
                'used': {
                    'type': 'number'
                },
            },
            'required': ['resource_category', 'resource_name', 'max_used']
        }
        try:
            validate(rule, SCHEMA)
        except ValidationError as err:
            LOG.error('Invalid rule')
            raise Exception('Invalid rule') from err
        return True

    def create(self, username, resource_category, resource_name, max_used):
        """
        Create an authorisation rule on database. 

        Args:
            username (str): username;
            resource_name (str): name that identifies the resource being used;
            rule (dict): rule object.

        Returns:
            database response
        """
        rule = {
            'resource_category': resource_category,
            'resource_name': resource_name,
            'max_used': int(max_used),
            'used': 0
        }
        if self.validate_rule(rule):
            result = self.basedb.insert(AUTHORISATION_COLLECTION,
                                        AUTHORISATION_KEY, username,
                                        AUTHORISATION_ITEM, rule)
            if result is not None:
                LOG.info('Rule: ' + json.dumps(rule) +
                         'successfully created for user: '******'.')
                return result
        return None

    def read(self, username, resource_name, resource_category):
        """
        Read rule information from user.
        """
        resources = self.basedb.get(AUTHORISATION_COLLECTION,
                                    AUTHORISATION_KEY, username)
        for item in resources:
            for elem in item[AUTHORISATION_ITEM]:
                if elem['resource_name'] == resource_name and\
                        elem['resource_category'] == resource_category:
                    return elem
        return None

    def update(self, username, resource_name, resource_category, max_allowed):
        """
        Update rule information. 
        """
        resources = self.basedb.get(AUTHORISATION_COLLECTION,
                                    AUTHORISATION_KEY, username)
        for item in resources:
            for elem in item[AUTHORISATION_ITEM]:
                if elem['resource_name'] == resource_name and\
                        elem['resource_category'] == resource_category:
                    new_elem = copy.deepcopy(elem)
                    new_elem['max_allowed'] = max_allowed
                    result = self.basedb.update(AUTHORISATION_COLLECTION,
                                                AUTHORISATION_KEY, username,
                                                AUTHORISATION_ITEM, elem,
                                                new_elem)
                    return result
        return None

    def delete(self, username, resource_name, resource_category):
        """
        Delete rule information. 
        """
        resources = self.basedb.get(AUTHORISATION_COLLECTION,
                                    AUTHORISATION_KEY, username)
        for item in resources:
            for elem in item[AUTHORISATION_ITEM]:
                if elem['resource_name'] == resource_name and\
                        elem['resource_category'] == resource_category:
                    result = self.basedb.remove_list_item(
                        AUTHORISATION_COLLECTION, AUTHORISATION_KEY, username,
                        AUTHORISATION_ITEM, elem)
                    return result
        return None
Example #2
0
def step_impl(context):
    with patch.object(BaseDB, 'insert', return_value=True) as mck_insert:
        accounting = Accounting()
        accounting.register(context.username, context.msg, context.category)
        assert mck_insert.called