scitran/core

View on GitHub
api/dao/consistencychecker.py

Summary

Maintainability
A
30 mins
Test Coverage
"""Scope of this module is to define consistency checkers that will
do some verification against the database before allowing the operation"""

from .. import config
from ..web.errors import APIConsistencyException

def noop(*args, **kwargs): # pylint: disable=unused-argument
    pass

def get_list_storage_checker(action, list_name):
    """Build the checker for the list storage"""
    if list_name == ['permissions', 'permissions'] and action == 'POST':
        return user_on_permission
    return noop

def get_container_storage_checker(action, cont_name):
    """Build the checker for the container storage"""
    if cont_name == 'projects' and action in ['PUT', 'POST']:
        return field_on_container('session', 'sessions')
    elif cont_name == 'sessions' and action in ['PUT', 'POST']:
        return field_on_container('project', 'projects')
    elif cont_name == 'acquisitions' and action in ['PUT', 'POST']:
        return field_on_container('acquisition', 'acquisitions')
    elif cont_name == 'groups' and action == 'DELETE':
        return check_children('group', 'projects')
    return noop

def user_on_permission(data_op, **kwargs): # pylint: disable=unused-argument
    """Check that for a permission the user already exists.

    Used before PUT operations.
    """
    if not config.db.users.find_one({'_id': data_op['_id']}):
        raise APIConsistencyException('user does not exist')

def field_on_container(parent_field, parent_container_name):
    """Checks that if we are moving or creating a container,
    the new parent container already exists.

    Used before POST/PUT operations.
    """
    def f(data_op, **kwargs): # pylint: disable=unused-argument
        if data_op.get(parent_field) and not config.db[parent_container_name].find_one({'_id': data_op[parent_field]}):
            raise APIConsistencyException('{} {} does not exist'.format(parent_field, data_op[parent_field]))
    return f

def check_children(foreign_key_field, container_name):
    """Check that a container has no children.

    Used before DELETE operations.

    Args:
        foreign_key_field (str): key field name in container_name collection
        container_name (str): db collection to search

    Returns:
        None:

    Raises:
        APIConsistencyException: Child document found
    """
    def f(data_op, **kwargs): # pylint: disable=unused-argument
        if config.db[container_name].find_one({foreign_key_field: data_op['_id'], 'deleted' :{'$exists': False}}):
            raise APIConsistencyException(
                'DELETE not allowed. Children {} found for {}'.format(container_name, data_op['_id'])
            )
    return f