Skip to content
Snippets Groups Projects
permissions.py 2.7 KiB
Newer Older
"""
This file contains models used for permissions
"""

import logging
logger = logging.getLogger(__name__)

from .common import NamedCommonPK, AbstractChoice
from django.db.models import ManyToManyField
from enum import Enum

from rest_framework.permissions import DjangoModelPermissions
from django.contrib.auth.models import AbstractUser
from django.contrib.postgres.fields import JSONField

class TMSSUser(AbstractUser):
    """
    A custom user model that allows for additional information on the user like project roles.
    """
    # todo: The project roles field feels very free-form at the moment.
    #  Maybe this can be modeled better somehow, with references to the ProjectRole table?
    #  Otherwise, we should probably come up with a schema to makes sure things are consistent.
    #  Also, I'd suggest to simply map project name to a list of roles instead of the structure that is used here.
    project_roles = JSONField(null=True, blank=True, help_text='A list of structures that contain a project name and project role')  # e.g. [{'project': 'high', 'role': 'PI'}, {'project': 'high', 'role': 'Friend of Project'}]
#
# Project Permissions
#

class ProjectRole(AbstractChoice):
    """Defines the model and predefined list of possible project roles a user can have.
    The items in the Choices class below are automagically populated into the database via a data migration."""
    class Choices(Enum):
        PI = "pi"
        CO_I = "co_i"
        CONTACT_AUTHOR = "contact"
        SHARED_SUPPORT = 'shared_support'
        SHARED_SUPPORT_PRIMARY = 'shared_support_primary'
        FRIEND_OF_PROJECT = 'friend_of_project'
        FRIEND_OF_PROJECT_PRIMARY = 'friend_of_project_primary'


class ProjectPermission(NamedCommonPK):
     GET = ManyToManyField('ProjectRole', related_name='can_GET', blank=True)
     PUT = ManyToManyField('ProjectRole', related_name='can_PUT', blank=True)
     POST = ManyToManyField('ProjectRole', related_name='can_POST', blank=True)
     PATCH = ManyToManyField('ProjectRole', related_name='can_PATCH', blank=True)
     DELETE = ManyToManyField('ProjectRole', related_name='can_DELETE', blank=True)


# todo: move to viewsets / merge with TMSSDjangoModelPermissions class
class TMSSBasePermissions(DjangoModelPermissions):
    # This enforces permissions as "deny any" by default.
    view_permissions = ['%(app_label)s.view_%(model_name)s']

    perms_map = {
        'GET': view_permissions,
        'OPTIONS': view_permissions,
        'HEAD': view_permissions,
        'POST': DjangoModelPermissions.perms_map['POST'],
        'PUT': DjangoModelPermissions.perms_map['PUT'],
        'PATCH': DjangoModelPermissions.perms_map['PATCH'],
        'DELETE': DjangoModelPermissions.perms_map['DELETE'],
    }