Repository: cisagov/manage.get.gov

Issue:
Django Admin: Allow Staff level users to see "User domain roles"
### Issue description

Usability testing revealed that analysts will need access to the “User Domain Roles” section, which is currently available only to "full-access" users, so that they may look up relationships between managers and domains:

1. all managers for a particular domain and 
2. all domains managed by a particular manager



![Image](https://github.com/cisagov/manage.get.gov/assets/62573986/b9f54a2e-de9a-4657-bc1a-2b5cb96c943e)



### Acceptance criteria

- [ ] "cisa-analyst" users can see and use the "User domain roles" model.
- [ ] "cisa-analyst" users can "delete" a user domain role.

### Additional context

[Miro Research board](https://miro.com/app/board/uXjVNZhbw-s=/?openComment=3458764569104364449)

### Links to other issues

Related to #1292 #1298 (Do together)


Discussion:
@h-m-f-t Should analysts also be able to "Delete" a domain role? For example, in the use case described in this [slack thread](https://cisa-corp.slack.com/archives/C066ZBWFLRW/p1701463482798209), Alex would need to be able to view this section of the admin and have the ability to delete an entry. 

A little background: Currently there's only one role - Manager - to select, and the admin forces you to select a role in order to "Save" the entry. The only option for removing the role is to delete the entry altogether. 

cc: @neilmb and @abroddrick since you were part of that slack thread.

Resolving patch:
diff --git a/src/registrar/admin.py b/src/registrar/admin.py
--- a/src/registrar/admin.py
+++ b/src/registrar/admin.py
@@ -1,6 +1,7 @@
 import logging
 from django import forms
 from django.http import HttpResponse
+from django.shortcuts import redirect
 from django_fsm import get_available_FIELD_transitions
 from django.contrib import admin, messages
 from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
@@ -360,6 +361,17 @@ class Meta:
 
     autocomplete_fields = ["user", "domain"]
 
+    # Fixes a bug where non-superusers are redirected to the main page
+    def delete_view(self, request, object_id, extra_context=None):
+        """Custom delete_view implementation that specifies redirect behaviour"""
+        response = super().delete_view(request, object_id, extra_context)
+
+        if isinstance(response, HttpResponseRedirect) and not request.user.has_perm("registrar.full_access_permission"):
+            url = reverse("admin:registrar_userdomainrole_changelist")
+            return redirect(url)
+        else:
+            return response
+
 
 class DomainInvitationAdmin(ListHeaderAdmin):
     """Custom domain invitation admin class."""
diff --git a/src/registrar/migrations/0053_create_groups_v05.py b/src/registrar/migrations/0053_create_groups_v05.py
new file mode 100644
--- /dev/null
+++ b/src/registrar/migrations/0053_create_groups_v05.py
@@ -0,0 +1,37 @@
+# This migration creates the create_full_access_group and create_cisa_analyst_group groups
+# It is dependent on 0035 (which populates ContentType and Permissions)
+# If permissions on the groups need changing, edit CISA_ANALYST_GROUP_PERMISSIONS
+# in the user_group model then:
+# [NOT RECOMMENDED]
+# step 1: docker-compose exec app ./manage.py migrate --fake registrar 0035_contenttypes_permissions
+# step 2: docker-compose exec app ./manage.py migrate registrar 0036_create_groups
+# step 3: fake run the latest migration in the migrations list
+# [RECOMMENDED]
+# Alternatively:
+# step 1: duplicate the migration that loads data
+# step 2: docker-compose exec app ./manage.py migrate
+
+from django.db import migrations
+from registrar.models import UserGroup
+from typing import Any
+
+
+# For linting: RunPython expects a function reference,
+# so let's give it one
+def create_groups(apps, schema_editor) -> Any:
+    UserGroup.create_cisa_analyst_group(apps, schema_editor)
+    UserGroup.create_full_access_group(apps, schema_editor)
+
+
+class Migration(migrations.Migration):
+    dependencies = [
+        ("registrar", "0052_alter_domainapplication_anything_else_and_more"),
+    ]
+
+    operations = [
+        migrations.RunPython(
+            create_groups,
+            reverse_code=migrations.RunPython.noop,
+            atomic=True,
+        ),
+    ]
diff --git a/src/registrar/models/user_group.py b/src/registrar/models/user_group.py
--- a/src/registrar/models/user_group.py
+++ b/src/registrar/models/user_group.py
@@ -61,6 +61,11 @@ def create_cisa_analyst_group(apps, schema_editor):
                 "model": "website",
                 "permissions": ["change_website"],
             },
+            {
+                "app_label": "registrar",
+                "model": "userdomainrole",
+                "permissions": ["view_userdomainrole", "delete_userdomainrole"],
+            },
         ]
 
         # Avoid error: You can't execute queries until the end


Test patch:
diff --git a/src/registrar/tests/test_migrations.py b/src/registrar/tests/test_migrations.py
--- a/src/registrar/tests/test_migrations.py
+++ b/src/registrar/tests/test_migrations.py
@@ -41,6 +41,8 @@ def test_groups_created(self):
             "change_draftdomain",
             "analyst_access_permission",
             "change_user",
+            "delete_userdomainrole",
+            "view_userdomainrole",
             "change_website",
         ]