Repository: netbox-community/netbox
Pull request: Added optional user and group on custom field
<!--
    Thank you for your interest in contributing to NetBox! Please note that
    our contribution policy requires that a feature request or bug report be
    approved and assigned prior to opening a pull request. This helps avoid
    waste time and effort on a proposed change that we might not be able to
    accept.

    IF YOUR PULL REQUEST DOES NOT REFERENCE AN ISSUE WHICH HAS BEEN ASSIGNED
    TO YOU, IT WILL BE CLOSED AUTOMATICALLY.

    Please specify your assigned issue number on the line below.
-->
### Fixes: #10600

<!--
    Please include a summary of the proposed changes below.
-->


Problem statement:
Allow custom object fields to reference a user or group
### NetBox version

v3.3.5

### Feature type

Data model extension

### Proposed functionality

Being able to create object type custom fields with Netbox users.


### Use case

Being able to point a specific user which is responsible for a given object, like a device or VM.

### Database changes

_No response_

### External dependencies

_No response_

Hints from issue discussion:
That's why _Contacts_ are for: give a specific role to a specific contact for a given object, and for free you get a many-to-many relationship. In case an object does not have a _Contacts_ field, a custom field of that type will do. It also allows for _Contacts_ to exist while not being _Users_ with credentials on Netbox itself (covers different tenancy models).

Arguably, we may question the use case where a _Contact_ is optionally associated with a Netbox _User_ at creation time (e.g. autofill name and associated info). This could be helpful as a "garbage collection" strategy to detect obsolete contact info (via scripting for example if user no longer valid in ldap).
I think it's reasonable to allow referencing a NetBox user (or group) as well; we do this today with rack reservations.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. **Do not** attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our [contributing guide](https://github.com/netbox-community/netbox/blob/develop/CONTRIBUTING.md).
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. NetBox is governed by a small group of core maintainers which means not all opened issues may receive direct feedback. **Do not** attempt to circumvent this process by "bumping" the issue; doing so will result in its immediate closure and you may be barred from participating in any future discussions. Please see our [contributing guide](https://github.com/netbox-community/netbox/blob/develop/CONTRIBUTING.md).
Can I take a shot at this?
Assigned to you @abhi1693, thanks!
For the assigned user/group, should the custom field be hidden from the UI that were not assigned on it?
@abhi1693, sorry, I'm not clear on what you're asking. Could you give me an example?
Lets say I created a custom field and assigned to `bob`. Should the field only be visible to `bob` whether its view or edit on the UI? If so, should this also be tackled on the API side?
No, I don't think so. I believe the intent here is merely to be able to associate an arbitrary object with a particular user or group, like we do currently for rack reservations.

Commit message: added group and user model to object_type

Patch to review:
diff --git a/netbox/extras/forms/model_forms.py b/netbox/extras/forms/model_forms.py
index 040882d2700..d176df5e983 100644
--- a/netbox/extras/forms/model_forms.py
+++ b/netbox/extras/forms/model_forms.py
@@ -1,6 +1,7 @@
 import json
 
 from django import forms
+from django.db.models import Q
 from django.contrib.contenttypes.models import ContentType
 from django.utils.translation import gettext as _
 
@@ -37,7 +38,7 @@ class CustomFieldForm(BootstrapMixin, forms.ModelForm):
     object_type = ContentTypeChoiceField(
         queryset=ContentType.objects.all(),
         # TODO: Come up with a canonical way to register suitable models
-        limit_choices_to=FeatureQuery('webhooks'),
+        limit_choices_to=FeatureQuery('webhooks').get_query() | Q(app_label='auth', model__in=['user', 'group']),
         required=False,
         help_text=_("Type of the related object (for object/multi-object fields only)")
     )
diff --git a/netbox/utilities/utils.py b/netbox/utilities/utils.py
index aec0d896c6e..33c208f9e8d 100644
--- a/netbox/utilities/utils.py
+++ b/netbox/utilities/utils.py
@@ -48,6 +48,10 @@ def get_viewname(model, action=None, rest_api=False):
         if is_plugin:
             viewname = f'plugins-api:{app_label}-api:{model_name}'
         else:
+            # Alter the app_label for group and user model_name to point to users app
+            if model_name in ['group', 'user']:
+                app_label = 'users'
+
             viewname = f'{app_label}-api:{model_name}'
         # Append the action, if any
         if action:


Code review comments:
diff_hunk: @@ -48,6 +48,10 @@ def get_viewname(model, action=None, rest_api=False):
         if is_plugin:
             viewname = f'plugins-api:{app_label}-api:{model_name}'
         else:
+            # Alter the app_label for group and user model_name to point to users app
+            if model_name in ['group', 'user']:
path: netbox/utilities/utils.py
text: @user1:
This needs to check `app_label` as well, because future apps could theoretically introduce their own "group" or "user" models.

```suggestion
            if app_label == 'auth' and model_name in ['group', 'user']:
```