275 lines
6.8 KiB
Python
275 lines
6.8 KiB
Python
import django
|
|
|
|
from django.db import models
|
|
|
|
from access.models.tenant import Tenant as Organization
|
|
|
|
User = django.contrib.auth.get_user_model()
|
|
|
|
|
|
|
|
class OrganizationMixin:
|
|
"""Organization Tenancy Mixin
|
|
|
|
This class is intended to be included in **ALL** View / Viewset classes as
|
|
it contains the functions/methods required to conduct the permission
|
|
checking.
|
|
"""
|
|
|
|
|
|
_obj_organization: int = None
|
|
"""Cached Object Organization"""
|
|
|
|
def get_obj_organization(self, obj = None, request = None) -> Organization:
|
|
"""Fetch the objects Organization
|
|
|
|
Args:
|
|
obj (Model): Model of object
|
|
|
|
Raises:
|
|
ValueError: When `obj` and `request` are both missing
|
|
|
|
Returns:
|
|
Organization: Organization the object is from
|
|
None: No Organization was found
|
|
"""
|
|
|
|
if obj is None and request is None:
|
|
|
|
raise ValueError('Missing Parameter. obj or request must be supplied')
|
|
|
|
|
|
if self._obj_organization:
|
|
|
|
return self._obj_organization
|
|
|
|
|
|
if obj:
|
|
|
|
self._obj_organization = getattr(obj, 'organization', None)
|
|
|
|
|
|
if not self._obj_organization:
|
|
|
|
self._obj_organization = getattr(obj, 'get_organization', lambda: None)()
|
|
|
|
elif (
|
|
request
|
|
and not self.kwargs.get('pk', None)
|
|
):
|
|
|
|
if getattr(request.stream, 'method', '') != 'DELETE':
|
|
|
|
data = getattr(request, 'data', None)
|
|
|
|
if data:
|
|
|
|
data_organization = self.kwargs.get('organization_id', None)
|
|
|
|
if not data_organization:
|
|
|
|
data_organization = request.data.get('organization_id', None)
|
|
|
|
|
|
if not data_organization:
|
|
|
|
data_organization = request.data.get('organization', None)
|
|
|
|
|
|
if data_organization:
|
|
|
|
self._obj_organization = Organization.objects.get(
|
|
pk = int( data_organization )
|
|
)
|
|
|
|
elif self.kwargs.get('pk', None):
|
|
|
|
|
|
obj = self.model.objects.get( pk = self.kwargs.get('pk', None) )
|
|
|
|
if getattr(obj, 'organization', None):
|
|
|
|
self._obj_organization = obj.organization
|
|
|
|
elif str(self.model._meta.verbose_name).lower() == 'tenant':
|
|
|
|
self._obj_organization = obj
|
|
|
|
|
|
if self.get_parent_model(): # if defined is to overwrite object organization
|
|
|
|
parent_obj = self.get_parent_obj()
|
|
|
|
self._obj_organization = parent_obj.get_organization()
|
|
|
|
|
|
return self._obj_organization
|
|
|
|
|
|
|
|
def get_parent_model(self):
|
|
"""Get the Parent Model
|
|
|
|
This function exists so that dynamic parent models can be defined.
|
|
They are defined by overriding this method.
|
|
|
|
Returns:
|
|
Model: Parent Model
|
|
"""
|
|
|
|
return self.parent_model
|
|
|
|
|
|
|
|
def get_parent_obj(self):
|
|
""" Get the Parent Model Object
|
|
|
|
Use in views where the the model has no organization and the organization should be fetched from the parent model.
|
|
|
|
Requires attribute `parent_model` within the view with the value of the parent's model class
|
|
|
|
Returns:
|
|
parent_model (Model): with PK from kwargs['pk']
|
|
"""
|
|
|
|
return self.get_parent_model().objects.get(pk=self.kwargs[self.parent_model_pk_kwarg])
|
|
|
|
|
|
|
|
def get_permission_organizations(self, permission: str ) -> list([ int ]):
|
|
"""Return Organization(s) the permission belongs to
|
|
|
|
Searches the users organizations for the required permission, if found
|
|
the organization is added to the list to return.
|
|
|
|
Args:
|
|
permission (str): Permission to search users organizations for
|
|
|
|
Returns:
|
|
Organizations (list): All Organizations where the permission was found.
|
|
"""
|
|
|
|
_permission_organizations: list = []
|
|
|
|
for team in self.request.tenancy._user_teams:
|
|
|
|
for team_permission in team.permissions.all():
|
|
|
|
permission_value = str( team_permission.content_type.app_label + '.' + team_permission.codename )
|
|
|
|
if permission_value == permission:
|
|
|
|
_permission_organizations += [ team.organization.id ]
|
|
|
|
|
|
return _permission_organizations
|
|
|
|
|
|
_permission_required: str = None
|
|
"""Cached Permissions required"""
|
|
|
|
|
|
def get_permission_required(self) -> str:
|
|
""" Get / Generate Permission Required
|
|
|
|
If there is a requirement that there be custom/dynamic permissions,
|
|
this function can be safely overridden.
|
|
|
|
Raises:
|
|
ValueError: Unable to determin the view action
|
|
|
|
Returns:
|
|
str: Permission in format `<app_name>.<action>_<model_name>`
|
|
"""
|
|
|
|
if self._permission_required:
|
|
|
|
return self._permission_required
|
|
|
|
|
|
if hasattr(self, 'get_dynamic_permissions'):
|
|
|
|
self._permission_required = self.get_dynamic_permissions()
|
|
|
|
if type(self._permission_required) is list:
|
|
|
|
self._permission_required = self._permission_required[0]
|
|
|
|
return self._permission_required
|
|
|
|
|
|
view_action: str = None
|
|
|
|
if(
|
|
self.action == 'create'
|
|
or getattr(self.request._stream, 'method', '') == 'POST'
|
|
):
|
|
|
|
view_action = 'add'
|
|
|
|
elif (
|
|
self.action == 'partial_update'
|
|
or self.action == 'update'
|
|
or getattr(self.request._stream, 'method', '') == 'PATCH'
|
|
or getattr(self.request._stream, 'method', '') == 'PUT'
|
|
):
|
|
|
|
view_action = 'change'
|
|
|
|
elif(
|
|
self.action == 'destroy'
|
|
or getattr(self.request._stream, 'method', '') == 'DELETE'
|
|
):
|
|
|
|
view_action = 'delete'
|
|
|
|
elif (
|
|
self.action == 'list'
|
|
):
|
|
|
|
view_action = 'view'
|
|
|
|
elif self.action == 'retrieve':
|
|
|
|
view_action = 'view'
|
|
|
|
elif self.action == 'metadata':
|
|
|
|
view_action = 'view'
|
|
|
|
elif self.action is None:
|
|
|
|
return False
|
|
|
|
|
|
|
|
if view_action is None:
|
|
|
|
raise ValueError('view_action could not be defined.')
|
|
|
|
|
|
permission = self.model._meta.app_label + '.' + view_action + '_' + self.model._meta.model_name
|
|
|
|
permission_required = permission
|
|
|
|
|
|
self._permission_required = permission_required
|
|
|
|
return self._permission_required
|
|
|
|
|
|
|
|
parent_model: models.Model = None
|
|
""" Parent Model
|
|
|
|
This attribute defines the parent model for the model in question. The parent model when defined
|
|
will be used as the object to obtain the permissions from.
|
|
"""
|
|
|
|
|
|
parent_model_pk_kwarg: str = 'pk'
|
|
"""Parent Model kwarg
|
|
|
|
This value is used to define the kwarg that is used as the parent objects primary key (pk).
|
|
"""
|