netbox/netbox/users/models/permissions.py
Jeremy Stretch b610cf37cf
Closes #19924: Record model features on ObjectType (#19939)
* Convert ObjectType to a concrete child model of ContentType

* Add public flag to ObjectType

* Catch post_migrate signal to update ObjectTypes

* Reference ObjectType records instead of registry for feature support

* Automatically create ObjectTypes

* Introduce has_feature() utility function

* ObjectTypeManager should not inherit from ContentTypeManager

* Misc cleanup

* Don't populate ObjectTypes during migration

* Don't automatically create ObjectTypes when a ContentType is created

* Fix test

* Extend has_feature() to accept a model or OT/CT

* Misc cleanup

* Deprecate get_for_id() on ObjectTypeManager

* Rename contenttypes.py to object_types.py

* Add index to features ArrayField

* Keep FK & M2M fields pointing to ContentType

* Add get_for_models() to ObjectTypeManager

* Add tests for manager methods & utility functions

* Fix migrations for M2M relations to ObjectType

* model_is_public() should return False for non-core & non-plugin models

* Order ObjectType by app_label & model name

* Resolve migrations conflict
2025-07-30 13:05:34 -04:00

82 lines
2.1 KiB
Python

from django.contrib.postgres.fields import ArrayField
from django.db import models
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from utilities.querysets import RestrictedQuerySet
__all__ = (
'ObjectPermission',
)
class ObjectPermission(models.Model):
"""
A mapping of view, add, change, and/or delete permission for users and/or groups to an arbitrary set of objects
identified by ORM query parameters.
"""
name = models.CharField(
verbose_name=_('name'),
max_length=100
)
description = models.CharField(
verbose_name=_('description'),
max_length=200,
blank=True
)
enabled = models.BooleanField(
verbose_name=_('enabled'),
default=True
)
object_types = models.ManyToManyField(
to='contenttypes.ContentType',
related_name='object_permissions'
)
actions = ArrayField(
base_field=models.CharField(max_length=30),
help_text=_("The list of actions granted by this permission")
)
constraints = models.JSONField(
blank=True,
null=True,
verbose_name=_('constraints'),
help_text=_("Queryset filter matching the applicable objects of the selected type(s)")
)
objects = RestrictedQuerySet.as_manager()
class Meta:
ordering = ['name']
verbose_name = _('permission')
verbose_name_plural = _('permissions')
def __str__(self):
return self.name
@property
def can_view(self):
return 'view' in self.actions
@property
def can_add(self):
return 'add' in self.actions
@property
def can_change(self):
return 'change' in self.actions
@property
def can_delete(self):
return 'delete' in self.actions
def list_constraints(self):
"""
Return all constraint sets as a list (even if only a single set is defined).
"""
if type(self.constraints) is not list:
return [self.constraints]
return self.constraints
def get_absolute_url(self):
return reverse('users:objectpermission', args=[self.pk])