From c7348891956ff7bcf8b77be720aab9e90a2bce3b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Sun, 30 Jul 2023 11:18:03 -0400 Subject: [PATCH] Introduce the DEFAULT_PERMISSIONS config parameter --- docs/administration/permissions.md | 7 ++++++- docs/configuration/security.md | 18 ++++++++++++++++++ netbox/netbox/authentication.py | 13 ++++++++++++- netbox/netbox/settings.py | 1 + 4 files changed, 37 insertions(+), 2 deletions(-) diff --git a/docs/administration/permissions.md b/docs/administration/permissions.md index 48abd5443..95f0f0c05 100644 --- a/docs/administration/permissions.md +++ b/docs/administration/permissions.md @@ -68,8 +68,13 @@ When defining a permission constraint, administrators may use the special token The `$user` token can be used only as a constraint value, or as an item within a list of values. It cannot be modified or extended to reference specific user attributes. +### Default Permissions -#### Example Constraint Definitions +!!! info "This feature was introduced in NetBox v3.6." + +While permissions are typically assigned to specific groups and/or users, it is also possible to define a set of default permissions that are applied to _all_ authenticated users. This is done using the [`DEFAULT_PERMISSIONS`](../configuration/security.md#default_permissions) configuration parameter. Note that statically configuring permissions for specific users or groups is **not** supported. + +### Example Constraint Definitions | Constraints | Description | | ----------- | ----------- | diff --git a/docs/configuration/security.md b/docs/configuration/security.md index 596de1461..716e75043 100644 --- a/docs/configuration/security.md +++ b/docs/configuration/security.md @@ -90,6 +90,24 @@ CSRF_TRUSTED_ORIGINS = ( --- +## DEFAULT_PERMISSIONS + +!!! info "This parameter was introduced in NetBox v3.6." + +Default: None + +This parameter defines object permissions that are applied automatically to _any_ authenticated user, regardless of what permissions have been defined in the database. For example, to allow all users to create a device role beginning with the word "temp," you could configure the following: + +```python +DEFAULT_PERMISSIONS = { + 'dcim.add_devicerole': ( + {'name__startswith': 'temp'}, + ) +} +``` + +--- + ## EXEMPT_VIEW_PERMISSIONS Default: Empty list diff --git a/netbox/netbox/authentication.py b/netbox/netbox/authentication.py index 61dfe2fdb..659dd67e7 100644 --- a/netbox/netbox/authentication.py +++ b/netbox/netbox/authentication.py @@ -76,6 +76,18 @@ class ObjectPermissionMixin: """ Return all permissions granted to the user by an ObjectPermission. """ + # Initialize a dictionary mapping permission names to sets of constraints + perms = defaultdict(list) + + # Collect any configured default permissions + for perm_name, constraints in settings.DEFAULT_PERMISSIONS.items(): + constraints = constraints or tuple() + if type(constraints) not in (list, tuple): + raise ImproperlyConfigured( + f"Constraints for default permission {perm_name} must be defined as a list or tuple." + ) + perms[perm_name].extend(constraints) + # Retrieve all assigned and enabled ObjectPermissions object_permissions = ObjectPermission.objects.filter( self.get_permission_filter(user_obj), @@ -83,7 +95,6 @@ class ObjectPermissionMixin: ).order_by('id').distinct('id').prefetch_related('object_types') # Create a dictionary mapping permissions to their constraints - perms = defaultdict(list) for obj_perm in object_permissions: for object_type in obj_perm.object_types.all(): for action in obj_perm.actions: diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index 13b2bae7d..7dee3de16 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -99,6 +99,7 @@ DATE_FORMAT = getattr(configuration, 'DATE_FORMAT', 'N j, Y') DATETIME_FORMAT = getattr(configuration, 'DATETIME_FORMAT', 'N j, Y g:i a') DEBUG = getattr(configuration, 'DEBUG', False) DEFAULT_DASHBOARD = getattr(configuration, 'DEFAULT_DASHBOARD', None) +DEFAULT_PERMISSIONS = getattr(configuration, 'DEFAULT_PERMISSIONS', {}) DEVELOPER = getattr(configuration, 'DEVELOPER', False) DOCS_ROOT = getattr(configuration, 'DOCS_ROOT', os.path.join(os.path.dirname(BASE_DIR), 'docs')) EMAIL = getattr(configuration, 'EMAIL', {})