You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2020/07/29 20:27:23 UTC

[allura] 01/01: [#8372] misc site admin improvements:

This is an automated email from the ASF dual-hosted git repository.

brondsem pushed a commit to branch db/8372
in repository https://gitbox.apache.org/repos/asf/allura.git

commit 9facc398ddb839b7d3db22f464061c2ba65a77be
Author: Dave Brondsema <da...@brondsema.net>
AuthorDate: Wed Jul 29 16:24:25 2020 -0400

    [#8372] misc site admin improvements:
    
    * admin search by usernames & project shortnames should handle uppercase
    * on user-profile page, show site admin link
    * allow site admins to view disabled user-profile pages
    * more notes on user admin details pages
---
 Allura/allura/controllers/rest.py                       |  7 +++++--
 Allura/allura/controllers/site_admin.py                 |  3 +++
 .../allura/ext/user_profile/templates/user_index.html   | 14 ++++++++++++++
 Allura/allura/lib/helpers.py                            |  2 +-
 Allura/allura/lib/plugin.py                             | 17 +++++++++++------
 Allura/allura/lib/security.py                           |  7 +++++++
 Allura/allura/model/project.py                          | 12 ++++++++++--
 Allura/allura/templates/site_admin.html                 |  2 +-
 Allura/allura/templates/site_admin_new_projects.html    |  1 +
 Allura/allura/templates/site_admin_user_details.html    | 16 +++++++++++++++-
 .../override/allura/templates/site_admin.html           |  2 +-
 Allura/allura/tests/functional/test_neighborhood.py     |  4 +++-
 .../forgeactivity/tests/functional/test_root.py         |  5 ++---
 13 files changed, 74 insertions(+), 18 deletions(-)

diff --git a/Allura/allura/controllers/rest.py b/Allura/allura/controllers/rest.py
index 6072c6f..2686a54 100644
--- a/Allura/allura/controllers/rest.py
+++ b/Allura/allura/controllers/rest.py
@@ -331,8 +331,11 @@ def nbhd_lookup_first_path(nbhd, name, current_user, remainder, api=False):
         return project, (pname,) + remainder  # include pname in new remainder, it is actually the nbhd tool path
     if project and prefix == 'u/':
         # make sure user-projects are associated with an enabled user
-        user = project.user_project_of
-        if not user or user.disabled or user.pending:
+        is_site_admin = h.is_site_admin(c.user)
+        user = project.get_userproject_user(include_disabled=is_site_admin)
+        if not user or user.pending:
+            raise exc.HTTPNotFound
+        if user.disabled and not is_site_admin:
             raise exc.HTTPNotFound
         if not api and user.url() != '/{}{}/'.format(prefix, pname):
             # might be different URL than the URL requested
diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index 7def94e..d70e7c6 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -272,6 +272,9 @@ class SiteAdminController(object):
         objects = []
         limit, page, start = g.handle_paging(limit, page, default=25)
         if q:
+            if f in ('username', 'shortname'):
+                # these are always lowercase, so search by lowercase
+                q = q.lower()
             match = search.site_admin_search(model, q, f, rows=limit, start=start)
             if match:
                 count = match.hits
diff --git a/Allura/allura/ext/user_profile/templates/user_index.html b/Allura/allura/ext/user_profile/templates/user_index.html
index 9d448c7..17db505 100644
--- a/Allura/allura/ext/user_profile/templates/user_index.html
+++ b/Allura/allura/ext/user_profile/templates/user_index.html
@@ -47,6 +47,20 @@
 {% block top_nav %}{# disabled #}{% endblock %}
 
 {% block content_base %}
+  {% if h.is_site_admin(c.user) %}
+    {# maybe could be a regular user profile "section" but would need a way to make it conditionally display #}
+    <div class="profile-section tools">
+        <h3 style="background: darkorange">Site Admin</h3>
+        <div class="section-body">
+            <ul>
+                <li><a href="/nf/admin/user/{{ user.username }}">Admin details page for {{ user.username }}</a></li>
+                {% if user.disabled %}
+                    <li>User is <strong>DISABLED</strong>. <span style="color:darkorange">This page is only visible because you are a site admin.  Everyone else gets a 404 error page.</span></li>
+                {% endif %}
+            </ul>
+        </div>
+    </div>
+  {% endif %}
   {% for section in sections %}
     {{ section.display() }}
   {% endfor %}
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index b664dcf..6b29822 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -72,7 +72,7 @@ from allura.lib import exceptions as exc
 from allura.lib import utils
 
 # import to make available to templates, don't delete:
-from .security import has_access, is_allowed_by_role
+from .security import has_access, is_allowed_by_role, is_site_admin
 
 
 log = logging.getLogger(__name__)
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index bcf6527..2a804f0 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -363,7 +363,7 @@ class AuthenticationProvider(object):
         # default implementation for any providers that haven't implemented this newer method yet
         return '/{}/'.format(self.user_project_shortname(user))
 
-    def user_by_project_shortname(self, shortname):
+    def user_by_project_shortname(self, shortname, include_disabled=False):
         '''
         :param str: shortname
         :rtype: user: a :class:`User <allura.model.auth.User>`
@@ -592,12 +592,17 @@ class LocalAuthenticationProvider(AuthenticationProvider):
         # (nbhd_lookup_first_path will figure it out)
         return '/u/{}/'.format(user.username)
 
-    def user_by_project_shortname(self, shortname):
+    def user_by_project_shortname(self, shortname, include_disabled=False):
         from allura import model as M
-        user = M.User.query.get(username=shortname, disabled=False, pending=False)
+        filters = {
+            'pending': False,
+        }
+        if not include_disabled:
+            filters['disabled'] = False
+        user = M.User.query.get(username=shortname, **filters)
         if not user and '-' in shortname:
             # try alternate version in case username & user-project shortname differ - see user_project_shortname()
-            user = M.User.query.get(username=shortname.replace('-', '_'), disabled=False, pending=False)
+            user = M.User.query.get(username=shortname.replace('-', '_'), **filters)
         return user
 
     def update_notifications(self, user):
@@ -797,8 +802,8 @@ class LdapAuthenticationProvider(AuthenticationProvider):
     def user_project_shortname(self, user):
         return LocalAuthenticationProvider(None).user_project_shortname(user)
 
-    def user_by_project_shortname(self, shortname):
-        return LocalAuthenticationProvider(None).user_by_project_shortname(shortname)
+    def user_by_project_shortname(self, shortname, **kwargs):
+        return LocalAuthenticationProvider(None).user_by_project_shortname(shortname, **kwargs)
 
     def user_registration_date(self, user):
         # could read this from an LDAP field?
diff --git a/Allura/allura/lib/security.py b/Allura/allura/lib/security.py
index 3969ea8..4ff62f7 100644
--- a/Allura/allura/lib/security.py
+++ b/Allura/allura/lib/security.py
@@ -498,8 +498,15 @@ def require_authenticated():
 
 
 def is_site_admin(user):
+    '''
+    :param allura.model.User user:
+    :rtype: bool
+    '''
     from allura.lib import helpers as h
 
+    if user.is_anonymous():
+        return False
+
     with h.push_context(tg.config.get('site_admin_project', 'allura'),
                         neighborhood=tg.config.get('site_admin_project_nbhd', 'Projects')):
         return has_access(c.project, 'admin', user=user)
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index 5c8ca1b..c073186 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -464,10 +464,18 @@ class Project(SearchIndexable, MappedClass, ActivityNode, ActivityObject):
         '''
         If this is a user-project, return the User, else None
         '''
+        return self.get_userproject_user()
+
+    def get_userproject_user(self, include_disabled=False):
+        '''
+        If this is a user-project, return the User, else None
+        '''
         user = None
         if self.is_user_project:
-            user = plugin.AuthenticationProvider.get(
-                request).user_by_project_shortname(self.shortname[2:])
+            user = plugin.AuthenticationProvider.get(request).user_by_project_shortname(
+                self.shortname[2:],  # strip leading u/ prefix
+                include_disabled=include_disabled,
+            )
         return user
 
     @LazyProperty
diff --git a/Allura/allura/templates/site_admin.html b/Allura/allura/templates/site_admin.html
index 3670285..1a4dbb5 100644
--- a/Allura/allura/templates/site_admin.html
+++ b/Allura/allura/templates/site_admin.html
@@ -25,7 +25,7 @@
 {% block header %}Forge Site Admin{% endblock %}
 
 {% block nav_menu %}
-  <h1 class="project_title">Site Admin</h1>
+  <h1 class="project_title"><a href="/nf/admin/">Site Admin</a></h1>
 {% endblock %}
 
 {% block sidebar_menu %}
diff --git a/Allura/allura/templates/site_admin_new_projects.html b/Allura/allura/templates/site_admin_new_projects.html
index aa366fa..eb2d931 100644
--- a/Allura/allura/templates/site_admin_new_projects.html
+++ b/Allura/allura/templates/site_admin_new_projects.html
@@ -22,6 +22,7 @@
 {% extends 'allura:templates/site_admin.html' %}
 
 {% block title %}New Projects{% endblock %}
+{% block header %}New Projects{% endblock %}
 
 {% macro _paging() %}
 <div class="paging">
diff --git a/Allura/allura/templates/site_admin_user_details.html b/Allura/allura/templates/site_admin_user_details.html
index d491307..0f4d34a 100644
--- a/Allura/allura/templates/site_admin_user_details.html
+++ b/Allura/allura/templates/site_admin_user_details.html
@@ -44,7 +44,14 @@
         <form action='/nf/admin/user/set_status' method="POST">
           Account Status:<br>
             <label><input type="radio" name="status" value="enable"{% if status == 'enabled' %} checked="checked"{% endif %}>Enabled</label><br>
-            <label><input type="radio" name="status" value="disable"{% if status == 'disabled' %} checked="checked"{% endif %}>Disabled</label><br>
+            <label><input type="radio" name="status" value="disable"{% if status == 'disabled' %} checked="checked"{% endif %}>
+                {%- if status == 'disabled' -%}
+                    <strong>Disabled</strong>
+                    (see Audit Log below)
+                {%- else -%}
+                    Disabled
+                {%- endif -%}
+            </label><br>
             <label><input type="radio" name="status" value="pending"{% if status == 'pending' %} checked="checked"{% endif %}>Pending</label>
           <input type='hidden' name='username' value='{{ user.username }}'>
           {{lib.csrf_token()}}
@@ -152,6 +159,13 @@
             <li><a href="{{ p.url() }}">{{p.name}}</a>
                 <span class="spacer">&ndash;</span>
                 <a href="{{ p.url() }}admin/">Admin</a>
+                {% if not p.is_root %}
+                    (subproject)
+                {% elif p.is_user_project %}
+                    (user profile project)
+                {% elif p.is_nbhd_project %}
+                    (neighborhood)
+                {% endif %}
             </li>
           {% endfor %}
         </ul>
diff --git a/Allura/allura/templates_responsive/override/allura/templates/site_admin.html b/Allura/allura/templates_responsive/override/allura/templates/site_admin.html
index 3d13608..926e7f3 100644
--- a/Allura/allura/templates_responsive/override/allura/templates/site_admin.html
+++ b/Allura/allura/templates_responsive/override/allura/templates/site_admin.html
@@ -30,7 +30,7 @@
 {% block header %}Forge Site Admin{% endblock %}
 
 {% block nav_menu %}
-  <h1 class="project_title">Site Admin</h1>
+  <h1 class="project_title"><a href="/nf/admin/">Site Admin</a></h1>
 {% endblock %}
 
 {% block sidebar_menu %}
diff --git a/Allura/allura/tests/functional/test_neighborhood.py b/Allura/allura/tests/functional/test_neighborhood.py
index 1f7034c..a302ec1 100644
--- a/Allura/allura/tests/functional/test_neighborhood.py
+++ b/Allura/allura/tests/functional/test_neighborhood.py
@@ -951,7 +951,9 @@ class TestNeighborhood(TestController):
         self.app.get('/u/donald-duck/')  # assert it's there
         M.User.query.update(dict(username='donald-duck'),
                             {'$set': {'disabled': True}})
-        self.app.get('/u/donald-duck/', status=404)
+        self.app.get('/u/donald-duck/', status=404, extra_environ={'username': str('*anonymous')})
+        self.app.get('/u/donald-duck/', status=404, extra_environ={'username': str('test-user')})
+        self.app.get('/u/donald-duck/', status=302, extra_environ={'username': str('test-admin')})  # site admin user
 
     def test_more_projects_link(self):
         r = self.app.get('/adobe/adobe-1/admin/')
diff --git a/ForgeActivity/forgeactivity/tests/functional/test_root.py b/ForgeActivity/forgeactivity/tests/functional/test_root.py
index 7567004..1213ca7 100644
--- a/ForgeActivity/forgeactivity/tests/functional/test_root.py
+++ b/ForgeActivity/forgeactivity/tests/functional/test_root.py
@@ -58,9 +58,8 @@ class TestActivityController(TestController):
     def test_anon_read(self):
         r = self.app.get('/u/test-user-1',
                 extra_environ={'username': str('*anonymous')}).follow().follow()
-        assert r.html.find('div', 'profile-section tools').find('a',
-                dict(href='/u/test-user-1/activity/')), \
-                        'No Activity tool in top nav'
+        assert r.html.select('div.profile-section.tools a[href="/u/test-user-1/activity/"]'),\
+            'No Activity tool in top nav'
 
     @td.with_tool('test', 'activity')
     @patch('forgeactivity.main.g.director')