Permissions

TODO

Write about:

  • API permission check

  • The filter backend

Model Permissions

Lego’s permission strings form a hierarchy, where each step is described with a forward slash. A user with the permission /sudo/admin/events/ will also implicitly have access to everything that requires the permission /sudo/admin/events/create/, while he or she won’t have access to anything that requires i.e. /sudo/admin/users/.

Example:

Needed permission: /sudo/admin/events/create/

  • Permission - Passed?

  • /sudo/admin/users/create/ - Yes

  • /sudo/admin/users/update/ - No

  • /sudo/admin/ - Yes

The permission strings can only contain letters and forward slashes, and need to start and end with a forward slash.

Permissions are stored per group, connected to the model :class:lego.users.models.AbakusGroup. The current permission strings are: /sudo/ - for Webkom /sudo/admin/ for Hovedstyret

Object Permissions

Object permissions are handled explicitly by each app themself. This is done by inheriting the abstract model ObjectPermissionsModel, which adds the fields can_view_groups, can_edit_groups and can_edit_users. These are then used by mixins like lego.permissions.ObjectPermissions to decide if a user has permission to access an event/article or similar.

Modules

Filters

Models

class lego.apps.permissions.models.ObjectPermissionsModel(*args, **kwargs)

Bases: Model

Abstract model that provides fields that can be used for object permissions.

Permission Classes

class lego.apps.permissions.permissions.PermissionHandler

Bases: Generic[T]

The permission handler defines how permissions should be handled on a model

Required functions and things we need to answer

  • Different actions a user can perform on a queryset (action_grant)

  • Different actions a user can perform on a object (action_grant)

  • Filter querysets based on permissions

  • Check permissions on a per object level

  • Support custom permission actions

Usage: class Test(models.Model):

class Meta:

permissions = PermissionHandler()

filter_queryset(user: User, queryset: QuerySet[T], **kwargs) QuerySet[T]

Filter queryset based on object-level permissions. We currently only supports queryset filtering on ObjectPermissionsModels. Don’t use this function if you know that the user has list permissions.

has_object_level_permissions(user: User, perm: str, obj: T | None = None, queryset: QuerySet[T] | None = None) bool

Check whether the queryset or object requires a permission check at object level. This function should only be used by the api permission backend.

has_perm(user: User, perm: str, obj: T | None = None, queryset: QuerySet[T] | None = None, check_keyword_permissions=True, **kwargs) bool

Check permission on a object.

keyword_permission(model: Type[BasisModel], perm: str) str

Create default permission string based on the model class, action and default_permission format. This is used when no permission is provided for a action in the permission_map.

permissions_grant(permissions: Sequence[str], user: User, obj: T | None = None, queryset: QuerySet[T] | None = None) list[str]

Lookup possible permissions the user has access to.

required_keyword_permissions(model: Type[BasisModel], perm: str) list[str]

Get required keyword permissions based on the action and model class. Override the permission_map to create custom permissions, the default_keyword_permission function is used otherwise.