Permissions made easy
Project description
Easy permissions
Define user permissions and resource access simply and efficiently.
Installation
pip install ezperm
Usage & examples
General case
Assume we are in charge of a superhero team. We have a list of heroes, and we want to define permissions for them. Our hero model might look like this:
import dataclasses
@dataclasses.dataclass
class Hero:
name: str
age: int
permissions: list['Permissions']
After a while of working with our heroes, we realize that some of them are terrible cooks. We want to define a permission that will allow only some of them to cook or bake.
This can be done by extending the PermissionEnum
class and defining a _has_perm
method that will check if the hero has the permission.
Permission enums
import ezperm
class Permissions(ezperm.PermissionEnum):
CAN_COOK = 'CAN_COOK'
CAN_BAKE = 'CAN_BAKE'
def _has_perm(self, hero: Hero) -> bool:
return self.value in hero.permissions
Now lets use our permissions in the code:
# Define some heroes
ironman = Hero('Ironman', 45, [Permissions.CAN_COOK, Permissions.CAN_BAKE])
deadpool = Hero('Deadpool', 30, [Permissions.CAN_BAKE])
hulk = Hero('Hulk', 55, [])
# Check if the hero has a permission
Permissions.CAN_COOK(ironman) # ➞ True
Permissions.CAN_COOK(deadpool) # ➞ False
Permissions.CAN_COOK(hulk) # ➞ False
It is possible to use &
(logical and), |
(logical or) or ~
(negation) operators to combine permissions:
(Permissions.CAN_COOK & Permissions.CAN_BAKE)(ironman) # ➞ True
(Permissions.CAN_COOK & Permissions.CAN_BAKE)(deadpool) # ➞ False
(Permissions.CAN_COOK | Permissions.CAN_BAKE)(hulk) # ➞ False
~(Permissions.CAN_COOK | Permissions.CAN_BAKE)(hulk) # ➞ True
(~Permissions.CAN_COOK & Permissions.CAN_BAKE)(deadpool) # ➞ True
Dynamic permissions
Using the @permission
decorator, we can also define dynamic permissions that will check if the hero has a permission based on some other condition, or define a permission as a combination of other permissions.
class Permissions(ezperm.PermissionEnum):
CAN_COOK = 'CAN_COOK'
CAN_BAKE = 'CAN_BAKE'
def _has_perm(self, hero: Hero) -> bool:
return self.value in hero.permissions
### ↓ NEW ↓ ###
@ezperm.permission
def is_worthy(hero: Hero) -> bool:
return hero.name == 'Thor'
@ezperm.permission
def is_old(hero: Hero) -> bool:
return hero.age > 50
@ezperm.permission
def can_use_oven(hero: Hero) -> bool:
return (Permissions.CAN_COOK | Permissions.CAN_BAKE)(hero)
These permissions can be used in the same way as the static ones:
Permissions.is_worthy(ironman) # ➞ False
(Permissions.CAN_COOK | PERMISSIONS.is_worthy)(ironman) # ➞ True
Django integration
ezperm comes with a couple of tools to help with Django integration. Its use is entirely optional, and you can use ezperm and Django without it.
First, lets update our Permissions
and Hero
classes in our example:
import ezperm.django
from django.db import models
from django.contrib.postgres.fields import ArrayField
class Permissions(ezperm.PermissionEnum, models.TextChoices):
... # same as before
class Hero(ezperm.django.PermissionsMixin, models.Model):
name = models.CharField(max_length=100)
age = models.IntegerField()
permissions = ArrayField(
base_field=models.CharField(
max_length=255,
choices=Permissions.choices,
),
default=list,
)
Note, that we've inherited the Permissions
from Django's TextChoices
in order to use it as a choices
argument for the permissions
field.
Moreover, we've added the PermissionsMixin
to our Hero
model, which overrides the has_perms
and has_perm
method.
Now lets define a view which will allow access only to worthy or old heroes:
from django.views.generic import View
from ezperm.django.views import PermissionRequiredMixin
class CookView(PermissionRequiredMixin, View):
permission_required = Permissions.is_worthy | Permissions.is_old
def get(self, request):
return HttpResponse('You can cook!')
Contributing
Pull requests for any improvements are welcome.
Poetry is used to manage dependencies. To get started follow these steps:
git clone https://github.com/VojtechPetru/ezperm.git
cd ezperm
poetry install
poetry run pytest
Links
- Repository: https://github.com/VojtechPetru/ezperm
- Issue tracker: https://github.com/VojtechPetru/ezperm/issues. In case of sensitive bugs (e.g. security vulnerabilities) please contact me at petru.vojtech@gmail.com directly.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file ezperm-0.1.2.tar.gz
.
File metadata
- Download URL: ezperm-0.1.2.tar.gz
- Upload date:
- Size: 5.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.3 CPython/3.11.9 Linux/6.5.0-1025-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | e69524b91f11c32a949110b2c9b1abc01ff1f265e91e5aa625c0a62b1b5947bc |
|
MD5 | 9eea6d6d5c521cc85ac9561e86c42802 |
|
BLAKE2b-256 | ee489b04e5a51fd672cf27f455db1076550bbb3365a78d74bfa0c7b19cb1edb4 |
File details
Details for the file ezperm-0.1.2-py3-none-any.whl
.
File metadata
- Download URL: ezperm-0.1.2-py3-none-any.whl
- Upload date:
- Size: 6.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.3 CPython/3.11.9 Linux/6.5.0-1025-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 26581466195891d830519b9c6a719c3d295c53618a3eef68d7277a0a6e50edab |
|
MD5 | dd09aa07eeaa81449a79afe582e67d2b |
|
BLAKE2b-256 | 57a4ea7a58a5e5c3e33460ba5eea48225fefa2324eae70dc3da23234d5e7bd5c |