mirror of
				https://github.com/ae-utbm/sith.git
				synced 2025-11-03 18:43:04 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			95 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from typing import Iterable
 | 
						|
 | 
						|
from django.contrib.auth.models import Permission
 | 
						|
from django.db import models
 | 
						|
from django.utils.translation import gettext_lazy as _
 | 
						|
from django.utils.translation import pgettext_lazy
 | 
						|
 | 
						|
from core.models import Group, User
 | 
						|
 | 
						|
 | 
						|
class ApiClient(models.Model):
 | 
						|
    name = models.CharField(_("name"), max_length=64)
 | 
						|
    owner = models.ForeignKey(
 | 
						|
        User,
 | 
						|
        verbose_name=_("owner"),
 | 
						|
        related_name="api_clients",
 | 
						|
        on_delete=models.CASCADE,
 | 
						|
    )
 | 
						|
    groups = models.ManyToManyField(
 | 
						|
        Group, verbose_name=_("groups"), related_name="api_clients", blank=True
 | 
						|
    )
 | 
						|
    client_permissions = models.ManyToManyField(
 | 
						|
        Permission,
 | 
						|
        verbose_name=_("client permissions"),
 | 
						|
        blank=True,
 | 
						|
        help_text=_("Specific permissions for this api client."),
 | 
						|
        related_name="clients",
 | 
						|
    )
 | 
						|
    created_at = models.DateTimeField(auto_now_add=True)
 | 
						|
    updated_at = models.DateTimeField(auto_now=True)
 | 
						|
 | 
						|
    _perm_cache: set[str] | None = None
 | 
						|
 | 
						|
    class Meta:
 | 
						|
        verbose_name = _("api client")
 | 
						|
        verbose_name_plural = _("api clients")
 | 
						|
 | 
						|
    def __str__(self):
 | 
						|
        return self.name
 | 
						|
 | 
						|
    def has_perm(self, perm: str):
 | 
						|
        """Return True if the client has the specified permission."""
 | 
						|
 | 
						|
        if self._perm_cache is None:
 | 
						|
            group_permissions = (
 | 
						|
                Permission.objects.filter(group__group__in=self.groups.all())
 | 
						|
                .values_list("content_type__app_label", "codename")
 | 
						|
                .order_by()
 | 
						|
            )
 | 
						|
            client_permissions = self.client_permissions.values_list(
 | 
						|
                "content_type__app_label", "codename"
 | 
						|
            ).order_by()
 | 
						|
            self._perm_cache = {
 | 
						|
                f"{content_type}.{name}"
 | 
						|
                for content_type, name in (*group_permissions, *client_permissions)
 | 
						|
            }
 | 
						|
        return perm in self._perm_cache
 | 
						|
 | 
						|
    def has_perms(self, perm_list):
 | 
						|
        """
 | 
						|
        Return True if the client has each of the specified permissions. If
 | 
						|
        object is passed, check if the client has all required perms for it.
 | 
						|
        """
 | 
						|
        if not isinstance(perm_list, Iterable) or isinstance(perm_list, str):
 | 
						|
            raise ValueError("perm_list must be an iterable of permissions.")
 | 
						|
        return all(self.has_perm(perm) for perm in perm_list)
 | 
						|
 | 
						|
 | 
						|
class ApiKey(models.Model):
 | 
						|
    PREFIX_LENGTH = 5
 | 
						|
    KEY_LENGTH = 72
 | 
						|
    HASHED_KEY_LENGTH = 136
 | 
						|
 | 
						|
    name = models.CharField(_("name"), blank=True, default="")
 | 
						|
    prefix = models.CharField(_("prefix"), max_length=PREFIX_LENGTH, editable=False)
 | 
						|
    hashed_key = models.CharField(
 | 
						|
        _("hashed key"), max_length=HASHED_KEY_LENGTH, db_index=True, editable=False
 | 
						|
    )
 | 
						|
    client = models.ForeignKey(
 | 
						|
        ApiClient,
 | 
						|
        verbose_name=_("api client"),
 | 
						|
        related_name="api_keys",
 | 
						|
        on_delete=models.CASCADE,
 | 
						|
    )
 | 
						|
    revoked = models.BooleanField(pgettext_lazy("api key", "revoked"), default=False)
 | 
						|
    created_at = models.DateTimeField(auto_now_add=True)
 | 
						|
 | 
						|
    class Meta:
 | 
						|
        verbose_name = _("api key")
 | 
						|
        verbose_name_plural = _("api keys")
 | 
						|
        permissions = [("revoke_apikey", "Revoke API keys")]
 | 
						|
 | 
						|
    def __str__(self):
 | 
						|
        return f"{self.name} ({self.prefix}***)"
 |