Files
authentik/packages/ak-guardian/guardian/models.py
Simonyi Gergő 1b9653901c rbac: clean up roles and permissions (#19588)
* clean up roles and permissions

This was purposefully not included in `2025.12` to split the changes up.

The main content of this patch is in the migrations. Everything else
follows more or less automatically.

* add breaking change warning to release notes

* add `ak_groups` --> `groups` deprecated proxy

* fixup! add `ak_groups` --> `groups` deprecated proxy

* fixup! add `ak_groups` --> `groups` deprecated proxy

* fixup! add `ak_groups` --> `groups` deprecated proxy

* add configuration warning to default notifications blueprint

* add rudimentary tests for User.ak_groups

* remove no longer used permissions

* clarify deprecation

Co-authored-by: Jens L. <jens@goauthentik.io>
Signed-off-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>

* remove integration changes

These will be included in a separate PR once this is released.

---------

Signed-off-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
Co-authored-by: Jens L. <jens@goauthentik.io>
2026-01-29 19:12:38 +01:00

53 lines
2.2 KiB
Python

from django.contrib.auth.models import Permission
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import gettext_lazy as _
from guardian.conf import settings as guardian_settings
from guardian.utils import get_content_type
class RoleObjectPermission(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
permission = models.ForeignKey(Permission, on_delete=models.CASCADE)
role = models.ForeignKey(guardian_settings.role_model_label, on_delete=models.CASCADE)
object_pk = models.CharField(_("object ID"), max_length=255)
content_object = GenericForeignKey(fk_field="object_pk")
class Meta:
unique_together = ["role", "permission", "object_pk"]
indexes = [
models.Index(fields=["permission", "role", "content_type", "object_pk"]),
models.Index(fields=["role", "content_type", "object_pk"]),
]
def __str__(self) -> str:
return f"{str(self.content_object)} | {str(self.role)} | {str(self.permission.codename)}"
def save(self, *args, **kwargs) -> None:
content_type = get_content_type(self.content_object)
if content_type != self.permission.content_type:
raise ValidationError(
"Cannot persist permission not designed for this class (permission's type is "
f"{self.permission.content_type} and object's type is {content_type})"
)
return super().save(*args, **kwargs)
class RoleModelPermission(models.Model):
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
permission = models.ForeignKey(Permission, on_delete=models.CASCADE)
role = models.ForeignKey(guardian_settings.role_model_label, on_delete=models.CASCADE)
class Meta:
unique_together = ["role", "permission"]
indexes = [
models.Index(fields=["permission", "role", "content_type"]),
models.Index(fields=["role", "content_type"]),
]
def __str__(self) -> str:
return f"RoleModelPermission with role {self.role_id} and permission {self.permission_id}"