Newer
Older
Jörn Künsemöller
committed
"""
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
Jörn Künsemöller
committed
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'}]
Jörn Künsemöller
committed
#
# 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'
Jörn Künsemöller
committed
SHARED_SUPPORT_PRIMARY = 'shared_support_primary'
Jörn Künsemöller
committed
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'],
}