Repository: nautobot/nautobot

Issue:
Installed Plugins NavMenuItem not adhering to `is_staff` permission
<!--
    NOTE: IF YOUR ISSUE DOES NOT FOLLOW THIS TEMPLATE, IT WILL BE CLOSED.

    This form is only for reporting reproducible bugs. If you need assistance
    with Nautobot installation, or if you have a general question, please start a
    discussion instead: https://github.com/nautobot/nautobot/discussions

    Please describe the environment in which you are running Nautobot. Be sure
    that you are running an unmodified instance of the latest stable release
    before submitting a bug report, and that any plugins have been disabled.
-->
### Environment
* Python version: 3.8
* Nautobot version: 1.3.9

<!--
    Describe in detail the exact steps that someone else can take to reproduce
    this bug using the current stable release of Nautobot. Begin with the
    creation of any necessary database objects and call out every operation
    being performed explicitly. If reporting a bug in the REST API, be sure to
    reconstruct the raw HTTP request(s) being made: Don't rely on a client
    library such as pynautobot.
-->
Caused by #1844 

### Steps to Reproduce
1. Set user permissions to `is_active` and `is_staff` to true BUT with `is_superuser` to false
2. Attempt to browse to installed plugins from nav menu
3.

<!-- What did you expect to happen? -->
### Expected Behavior
`is_staff` provide visibility to menu item without requiring `is_superuser`

<!-- What happened instead? -->
### Observed Behavior
NavMenuItem is only present if user has `is_superuser`


Discussion:

Resolving patch:
diff --git a/nautobot/core/authentication.py b/nautobot/core/authentication.py
--- a/nautobot/core/authentication.py
+++ b/nautobot/core/authentication.py
@@ -48,7 +48,7 @@ def get_object_permissions(self, user_obj):
 
     def has_perm(self, user_obj, perm, obj=None):
         if perm == "is_staff":
-            return user_obj.is_active and (user_obj.obj.is_staff or user_obj.is_superuser)
+            return user_obj.is_active and (user_obj.is_staff or user_obj.is_superuser)
 
         app_label, action, model_name = resolve_permission(perm)
 


Test patch:
diff --git a/nautobot/core/tests/test_views.py b/nautobot/core/tests/test_views.py
--- a/nautobot/core/tests/test_views.py
+++ b/nautobot/core/tests/test_views.py
@@ -105,46 +105,73 @@ def test_subdirectory_routes(self):
 
 
 class NavRestrictedUI(TestCase):
+    def setUp(self):
+        super().setUp()
+
+        self.url = reverse("plugins:plugins_list")
+        self.item_weight = 100  # TODO: not easy to introspect from the nav menu struct, so hard-code it here for now
+
     def make_request(self):
         response = self.client.get(reverse("home"))
-        response_body = response.content.decode(response.charset).replace("\n", "")
-        return re.compile(r'<nav.*<li class="dropdown-header".*General</li>.*Installed Plugins.*</nav>').search(
-            response_body
-        )
+        return response.content.decode(response.charset)
 
     @override_settings(HIDE_RESTRICTED_UI=True)
-    def test_installed_plugins_visible_to_admin_with_hide_restricted_ui_True(self):
+    def test_installed_plugins_visible_to_staff_with_hide_restricted_ui_true(self):
+        """The "Installed Plugins" menu item should be available to is_staff user regardless of HIDE_RESTRICTED_UI."""
         # Make user admin
         self.user.is_staff = True
-        self.user.is_superuser = True
         self.user.save()
 
-        search_result = self.make_request()
-
-        self.assertIsNotNone(search_result)
+        response_content = self.make_request()
+        self.assertInHTML(
+            f"""
+            <li>
+              <div class="buttons pull-right"></div>
+              <a href="{self.url}" data-item-weight="{self.item_weight}">Installed Plugins</a>
+            </li>
+            """,
+            response_content,
+        )
 
     @override_settings(HIDE_RESTRICTED_UI=False)
-    def test_installed_plugins_visible_to_admin_with_hide_restricted_ui_False(self):
+    def test_installed_plugins_visible_to_staff_with_hide_restricted_ui_false(self):
+        """The "Installed Plugins" menu item should be available to is_staff user regardless of HIDE_RESTRICTED_UI."""
         # Make user admin
         self.user.is_staff = True
-        self.user.is_superuser = True
         self.user.save()
 
-        search_result = self.make_request()
-
-        self.assertIsNotNone(search_result)
+        response_content = self.make_request()
+        self.assertInHTML(
+            f"""
+            <li>
+              <div class="buttons pull-right"></div>
+              <a href="{self.url}" data-item-weight="{self.item_weight}">Installed Plugins</a>
+            </li>
+            """,
+            response_content,
+        )
 
     @override_settings(HIDE_RESTRICTED_UI=True)
-    def test_installed_plugins_not_visible_to_user_with_hide_restricted_ui_True(self):
-        search_result = self.make_request()
+    def test_installed_plugins_not_visible_to_non_staff_user_with_hide_restricted_ui_true(self):
+        """The "Installed Plugins" menu item should be hidden from a non-staff user when HIDE_RESTRICTED_UI=True."""
+        response_content = self.make_request()
 
-        self.assertIsNone(search_result)
+        self.assertNotRegex(response_content, r"Installed\s+Plugins")
 
     @override_settings(HIDE_RESTRICTED_UI=False)
-    def test_installed_plugins_not_visible_to_user_with_hide_restricted_ui_False(self):
-        search_result = self.make_request()
-
-        self.assertIsNone(search_result)
+    def test_installed_plugins_disabled_to_non_staff_user_with_hide_restricted_ui_false(self):
+        """The "Installed Plugins" menu item should be disabled for a non-staff user when HIDE_RESTRICTED_UI=False."""
+        response_content = self.make_request()
+
+        self.assertInHTML(
+            f"""
+            <li class="disabled">
+              <div class="buttons pull-right"></div>
+              <a href="{self.url}" data-item-weight="{self.item_weight}">Installed Plugins</a>
+            </li>
+            """,
+            response_content,
+        )
 
 
 class LoginUI(TestCase):