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:22 UTC

[allura] branch db/8372 created (now 9facc39)

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

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


      at 9facc39  [#8372] misc site admin improvements:

This branch includes the following new commits:

     new 9facc39  [#8372] misc site admin improvements:

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



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

Posted by br...@apache.org.
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')