1
0
mirror of https://github.com/taigaio/taiga-back synced 2025-10-06 00:02:52 +02:00
Files
taiga-back/taiga/base/api/permissions.py
David Barragán Merino e7fad0b5cc chore: migrate to django 3.2
2023-02-24 13:05:37 +01:00

199 lines
5.4 KiB
Python

# -*- coding: utf-8 -*-
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# Copyright (c) 2021-present Kaleidos Ventures SL
import abc
import inspect
from functools import reduce
from taiga.permissions.services import user_has_perm, is_project_admin
from django.utils.translation import gettext as _
######################################################################
# Base permissiones definition
######################################################################
class ResourcePermission(object):
"""
Base class for define resource permissions.
"""
enough_perms = None
global_perms = None
retrieve_perms = None
create_perms = None
update_perms = None
destroy_perms = None
list_perms = None
def __init__(self, request, view):
self.request = request
self.view = view
def check_permissions(self, action:str, obj:object=None):
permset = getattr(self, "{}_perms".format(action))
if isinstance(permset, (list, tuple)):
permset = reduce(lambda acc, v: acc & v, permset)
elif permset is None:
# Use empty operator that always return true with
# empty components.
permset = And()
elif isinstance(permset, PermissionComponent):
# Do nothing
pass
elif inspect.isclass(permset) and issubclass(permset, PermissionComponent):
permset = permset()
else:
raise RuntimeError(_("Invalid permission definition."))
if self.global_perms:
permset = (self.global_perms & permset)
if self.enough_perms:
permset = (self.enough_perms | permset)
return permset.check_permissions(request=self.request,
view=self.view,
obj=obj)
class PermissionComponent(object, metaclass=abc.ABCMeta):
@abc.abstractmethod
def check_permissions(self, request, view, obj=None):
pass
def __invert__(self):
return Not(self)
def __and__(self, component):
return And(self, component)
def __or__(self, component):
return Or(self, component)
class PermissionOperator(PermissionComponent):
"""
Base class for all logical operators for compose
components.
"""
def __init__(self, *components):
self.components = tuple(components)
class Not(PermissionOperator):
"""
Negation operator as permission composable component.
"""
# Overwrites the default constructor for fix
# to one parameter instead of variable list of them.
def __init__(self, component):
super().__init__(component)
def check_permissions(self, *args, **kwargs):
component = self.components[0]
return (not component.check_permissions(*args, **kwargs))
class Or(PermissionOperator):
"""
Or logical operator as permission component.
"""
def check_permissions(self, *args, **kwargs):
valid = False
for component in self.components:
if component.check_permissions(*args, **kwargs):
valid = True
break
return valid
class And(PermissionOperator):
"""
And logical operator as permission component.
"""
def check_permissions(self, *args, **kwargs):
valid = True
for component in self.components:
if not component.check_permissions(*args, **kwargs):
valid = False
break
return valid
######################################################################
# Generic components.
######################################################################
class AllowAny(PermissionComponent):
def check_permissions(self, request, view, obj=None):
return True
class DenyAll(PermissionComponent):
def check_permissions(self, request, view, obj=None):
return False
class IsAuthenticated(PermissionComponent):
def check_permissions(self, request, view, obj=None):
return request.user and request.user.is_authenticated
class IsSuperUser(PermissionComponent):
def check_permissions(self, request, view, obj=None):
return request.user and request.user.is_authenticated and request.user.is_superuser
class HasProjectPerm(PermissionComponent):
def __init__(self, perm, *components):
self.project_perm = perm
super().__init__(*components)
def check_permissions(self, request, view, obj=None):
return user_has_perm(request.user, self.project_perm, obj)
class IsProjectAdmin(PermissionComponent):
def check_permissions(self, request, view, obj=None):
return is_project_admin(request.user, obj)
class IsObjectOwner(PermissionComponent):
def check_permissions(self, request, view, obj=None):
if obj.owner is None:
return False
return obj.owner == request.user
######################################################################
# Generic permissions.
######################################################################
class AllowAnyPermission(ResourcePermission):
enough_perms = AllowAny()
class IsAuthenticatedPermission(ResourcePermission):
enough_perms = IsAuthenticated()
class TaigaResourcePermission(ResourcePermission):
enough_perms = IsSuperUser()