Fixes #21051: Fix ObjectPermission object type selector to exclude internal/third-party models #556

Closed
opened 2026-04-05 16:43:23 +02:00 by MrUnknownDE · 0 comments
Owner

Originally created by @pheus on 1/15/2026

Fixes: #21051

Summary

Thank you for reviewing/triaging this issue and for the earlier guidance on treating this as a short-term bugfix.

This PR tightens the object type selector for Object Permissions to avoid listing internal-only and third-party/dev tooling models. Instead of maintaining a growing denylist of app labels, it leans on NetBox’s existing ObjectType.public flag and adds a small set of explicit exceptions for private-but-permission-relevant models.

Changes

  • Replace the current OBJECTPERMISSION_OBJECT_TYPES denylist-style filter with:

    OBJECTPERMISSION_OBJECT_TYPES = (
        (Q(public=True) & ~Q(app_label='core', model='objecttype'))
        | Q(app_label='core', model__in=['managedfile'])
        | Q(app_label='extras', model__in=['scriptmodule', 'taggeditem'])
    )
    
  • Explicitly exclude Core > Object Type (core.objecttype) from being selectable.

  • Explicitly include the private models that are expected to remain permissionable:

    • Core > Managed File
    • Extras > Script Module
    • Extras > Tagged Item

Resulting behavior (high level)

This removes several non-user-facing/internal or third-party object types which were previously shown in the selector, including:

  • Core > Auto Sync Record
  • Core > Object Type
  • DCIM > Cable Path *
  • DCIM > Port Mapping *
  • DCIM > Port Template Mapping *
  • Django_Rq > Queue
  • Extras > Cached Value
  • Python Social Auth > *
  • Thumbnail > Kv Store

* These models don’t use RestrictedQuerySet today and therefore don’t participate in object-permission filtering.

It also adds:

  • Users > Owner Group

Rationale

  • The prior approach was effectively “include everything except a small denylist”, which allowed unrelated installed apps (e.g. background worker tooling, debug/thumbnail/social-auth dependencies) to appear as selectable ObjectPermission targets.
  • Using public=True makes the selector align with NetBox’s concept of “user-facing” models and avoids continually expanding a denylist.
  • A few private models still need to remain selectable for real workflows (e.g. scripts), so they are explicitly included.

Alternative considered

As a short-term fix, an alternative would have been to expand the existing denylist and re-allow a small set of models:

OBJECTPERMISSION_OBJECT_TYPES = Q(
    ~Q(app_label__in=[
        'account', 'admin', 'auth', 'contenttypes', 'core', 'django_rq', 'extras', 'migrations', 'sessions', 'taggit',
        'thumbnail', 'users',
    ]) |
    Q(app_label='core', model__in=['configrevision', 'datafile', 'datasource', 'job', 'managedfile', 'objectchange']) |
    Q(app_label='users', model__in=['objectpermission', 'token', 'group', 'user', 'owner', 'ownergroup']) |
    (Q(app_label='extras') & ~Q(model='cachedvalue'))
)

I opted for the public=True approach (with explicit exceptions) to reduce the likelihood of new unrelated installed apps/models showing up in the selector over time.

Testing

Quick manual check in nbshell:

from core.models import ObjectType
from users.constants import OBJECTPERMISSION_OBJECT_TYPES

for ot in ObjectType.objects.filter(OBJECTPERMISSION_OBJECT_TYPES).order_by('app_label', 'model'):
    print(ot.app_labeled_name)

Follow-up

Per maintainer guidance, this PR focuses on the short-term bugfix. I plan to open a separate housekeeping issue to track the longer-term solution (i.e., defining a more explicit and/or feature-based mechanism for “permissionable object types”).

*Originally created by @pheus on 1/15/2026* ### Fixes: #21051 #### Summary Thank you for reviewing/triaging this issue and for the earlier guidance on treating this as a short-term bugfix. This PR tightens the object type selector for **Object Permissions** to avoid listing internal-only and third-party/dev tooling models. Instead of maintaining a growing denylist of app labels, it leans on NetBox’s existing `ObjectType.public` flag and adds a small set of explicit exceptions for private-but-permission-relevant models. #### Changes - Replace the current `OBJECTPERMISSION_OBJECT_TYPES` denylist-style filter with: ```python OBJECTPERMISSION_OBJECT_TYPES = ( (Q(public=True) & ~Q(app_label='core', model='objecttype')) | Q(app_label='core', model__in=['managedfile']) | Q(app_label='extras', model__in=['scriptmodule', 'taggeditem']) ) ``` - Explicitly exclude **`Core > Object Type`** (`core.objecttype`) from being selectable. - Explicitly include the private models that are expected to remain permissionable: - **Core > Managed File** - **Extras > Script Module** - **Extras > Tagged Item** #### Resulting behavior (high level) This removes several non-user-facing/internal or third-party object types which were previously shown in the selector, including: - `Core > Auto Sync Record` - `Core > Object Type` - `DCIM > Cable Path` * - `DCIM > Port Mapping` * - `DCIM > Port Template Mapping` * - `Django_Rq > Queue` - `Extras > Cached Value` - `Python Social Auth > *` - `Thumbnail > Kv Store` \* These models don’t use `RestrictedQuerySet` today and therefore don’t participate in object-permission filtering. It also adds: - `Users > Owner Group` #### Rationale - The prior approach was effectively “include everything except a small denylist”, which allowed unrelated installed apps (e.g. background worker tooling, debug/thumbnail/social-auth dependencies) to appear as selectable ObjectPermission targets. - Using `public=True` makes the selector align with NetBox’s concept of “user-facing” models and avoids continually expanding a denylist. - A few private models still need to remain selectable for real workflows (e.g. scripts), so they are explicitly included. #### Alternative considered As a short-term fix, an alternative would have been to expand the existing denylist and re-allow a small set of models: ```python OBJECTPERMISSION_OBJECT_TYPES = Q( ~Q(app_label__in=[ 'account', 'admin', 'auth', 'contenttypes', 'core', 'django_rq', 'extras', 'migrations', 'sessions', 'taggit', 'thumbnail', 'users', ]) | Q(app_label='core', model__in=['configrevision', 'datafile', 'datasource', 'job', 'managedfile', 'objectchange']) | Q(app_label='users', model__in=['objectpermission', 'token', 'group', 'user', 'owner', 'ownergroup']) | (Q(app_label='extras') & ~Q(model='cachedvalue')) ) ``` I opted for the `public=True` approach (with explicit exceptions) to reduce the likelihood of new unrelated installed apps/models showing up in the selector over time. #### Testing Quick manual check in `nbshell`: ```python from core.models import ObjectType from users.constants import OBJECTPERMISSION_OBJECT_TYPES for ot in ObjectType.objects.filter(OBJECTPERMISSION_OBJECT_TYPES).order_by('app_label', 'model'): print(ot.app_labeled_name) ``` #### Follow-up Per maintainer guidance, this PR focuses on the short-term bugfix. I plan to open a separate housekeeping issue to track the longer-term solution (i.e., defining a more explicit and/or feature-based mechanism for “permissionable object types”).
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github/netbox#556