allura-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From brond...@apache.org
Subject [allura] 02/02: [#8318] site admin button to generate password reset URL and show it
Date Thu, 18 Jul 2019 21:27:35 GMT
This is an automated email from the ASF dual-hosted git repository.

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

commit f13685ac2064202f3b53988c7509e547d3f9bead
Author: Dave Brondsema <dave@brondsema.net>
AuthorDate: Thu Jul 18 15:39:54 2019 -0400

    [#8318] site admin button to generate password reset URL and show it
---
 Allura/allura/controllers/site_admin.py            |  9 +++++
 Allura/allura/model/auth.py                        | 17 +++++----
 Allura/allura/templates/mail/forgot_password.txt   |  2 +-
 .../allura/templates/site_admin_user_details.html  | 40 ++++++++++++++++++++++
 Allura/allura/tests/functional/test_site_admin.py  |  9 ++++-
 5 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index 8e38681..aa7e877 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -737,6 +737,15 @@ class AdminUserDetailsController(object):
             pass  # catch redirect to '/'
         redirect(request.referer or '/')
 
+    @expose()
+    @require_post()
+    def make_password_reset_url(self, username):
+        user = M.User.by_username(username)
+        if not user or user.is_anonymous():
+            raise HTTPNotFound()
+        h.auditlog_user('Generated new password reset URL and shown to admin user', user=user)
+        return user.make_password_reset_url()
+
     @h.vardec
     @expose()
     @require_post()
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index ce429b7..005cadd 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -387,21 +387,26 @@ class User(MappedClass, ActivityNode, ActivityObject, SearchIndexable):
     def send_password_reset_email(self, email_address=None, subject_tmpl=u'{site_name} Password
recovery'):
         if email_address is None:
             email_address = self.get_pref('email_address')
-        hash = h.nonce(42)
-        self.set_tool_data('AuthPasswordReset',
-                           hash=hash,
-                           hash_expiry=datetime.utcnow() +
-                                       timedelta(seconds=int(config.get('auth.recovery_hash_expiry_period',
600))))
+        reset_url = self.make_password_reset_url()
 
         log.info('Sending password recovery link to %s', email_address)
         subject = subject_tmpl.format(site_name=config['site_name'])
         text = g.jinja2_env.get_template('allura:templates/mail/forgot_password.txt').render(dict(
             user=self,
             config=config,
-            hash=hash,
+            reset_url=reset_url,
         ))
         allura.tasks.mail_tasks.send_system_mail_to_user(email_address, subject, text)
 
+    def make_password_reset_url(self):
+        hash = h.nonce(42)
+        self.set_tool_data('AuthPasswordReset',
+                           hash=hash,
+                           hash_expiry=datetime.utcnow() +
+                                       timedelta(seconds=int(config.get('auth.recovery_hash_expiry_period',
600))))
+        reset_url = h.absurl('/auth/forgotten_password/{}'.format(hash))
+        return reset_url
+
     def can_send_user_message(self):
         """Return true if User is permitted to send a mesage to another user.
 
diff --git a/Allura/allura/templates/mail/forgot_password.txt b/Allura/allura/templates/mail/forgot_password.txt
index 0e23312..0c73102 100644
--- a/Allura/allura/templates/mail/forgot_password.txt
+++ b/Allura/allura/templates/mail/forgot_password.txt
@@ -21,4 +21,4 @@ Your username is {{ user.username }}
 
 To update your password on {{ config['site_name'] }}, please visit the following URL:
 
-{{ config['base_url'] }}/auth/forgotten_password/{{hash}}
+{{ reset_url }}
diff --git a/Allura/allura/templates/site_admin_user_details.html b/Allura/allura/templates/site_admin_user_details.html
index 3f97e99..38e4a5f 100644
--- a/Allura/allura/templates/site_admin_user_details.html
+++ b/Allura/allura/templates/site_admin_user_details.html
@@ -62,6 +62,20 @@
           <input type='hidden' name='username' value='{{ user.username }}'>
           {{lib.csrf_token()}}
         </form>
+
+        <form action='/nf/admin/user/make_password_reset_url' method="POST" id="get-reset">
+          <input type="submit" value="Get password reset link">
+          <input type='hidden' name='username' value='{{ user.username }}'>
+          {{lib.csrf_token()}}
+        </form>
+        <div id="password_reset_url_modal" class="modal">
+            <h1>Password Reset URL</h1>
+            <p>Be very careful to share this only with the intended user.</p>
+            <input type="url" readonly id="password_reset_url">
+            <a href="#" id="password_reset_url_copy">copy</a>
+            <p>Whenever you regenerate a new password reset URL, previous URLs are
invalidated.</p>
+        </div>
+
         </div>
       </fieldset>
     </div>
@@ -155,6 +169,13 @@
 li .spacer {
    margin: 0 0.5em;
 }
+#password_reset_url_modal {
+    display: none;
+}
+#password_reset_url {
+    width: 30em;
+    margin-right: 1em;
+}
 </style>
 {% endblock %}
 
@@ -166,6 +187,25 @@ $(document).ready(function() {
   $('input[name="status"]').change(function(e) {
     $(this).parents('form').submit();
   });
+  // handling for get password reset URL
+  $('#get-reset').submit(function(e) {
+      e.preventDefault();
+      var $form = $(this);
+      $.post($form.attr('action'), $form.serialize())
+          .done(function(data) {
+              var reset_url = data;
+              $('#password_reset_url_modal').lightbox_me();
+              $('#password_reset_url').val(reset_url);
+          })
+          .fail(function() {
+              $('#messages').notify({message: 'Error getting reset link', status: 'error'});
+          });
+  });
+  $('#password_reset_url_copy').click(function(){
+      $('#password_reset_url').select();
+      document.execCommand("copy");
+      $(this).text('copied!');
+  })
 });
 </script>
 {% endblock %}
diff --git a/Allura/allura/tests/functional/test_site_admin.py b/Allura/allura/tests/functional/test_site_admin.py
index 1e99911..4d691f3 100644
--- a/Allura/allura/tests/functional/test_site_admin.py
+++ b/Allura/allura/tests/functional/test_site_admin.py
@@ -490,7 +490,7 @@ class TestUserDetails(TestController):
     def test_add_comment(self):
         r = self.app.get('/nf/admin/user/test-user')
         assert_not_in(u'Comment by test-admin: I was hêre!', r)
-        form = r.forms[4]
+        form = [f for f in r.forms.itervalues() if f.action.endswith('add_audit_trail_entry')][0]
         assert_equal(form['username'].value, 'test-user')
         form['comment'] = u'I was hêre!'
         r = form.submit()
@@ -717,6 +717,13 @@ To update your password on %s, please visit the following URL:
             message_id=gen_message_id(),
             text=text)
 
+    def test_make_password_reset_url(self):
+        with td.audits('Generated new password reset URL and shown to admin user', user=True):
+            r = self.app.post('/nf/admin/user/make_password_reset_url', params={'username':
'test-user'})
+        user = M.User.by_username('test-user')
+        hash = user.get_tool_data('AuthPasswordReset', 'hash')
+        assert_in(hash, r.text)
+
 
 class TestDeleteProjects(TestController):
 


Mime
View raw message