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 2016/09/01 16:08:18 UTC

[1/4] allura git commit: [#8117] make all 2FA pages look nicer; increase pwd reconfirm timeout

Repository: allura
Updated Branches:
  refs/heads/db/8117 57b425241 -> a8d198013


[#8117] make all 2FA pages look nicer; increase pwd reconfirm timeout


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/56fa52cc
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/56fa52cc
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/56fa52cc

Branch: refs/heads/db/8117
Commit: 56fa52ccab3c1e45f7cc4f93ddfbb5c77b3cc722
Parents: 57b4252
Author: Dave Brondsema <da...@brondsema.net>
Authored: Wed Aug 31 17:14:16 2016 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Thu Sep 1 10:29:10 2016 -0400

----------------------------------------------------------------------
 Allura/allura/templates/login_multifactor.html |  7 ++-
 Allura/allura/templates/reconfirm_auth.html    |  7 ++-
 Allura/allura/templates/user_account_base.html |  2 +
 Allura/allura/templates/user_totp.html         | 62 ++++++++++++++++-----
 Allura/allura/tests/functional/test_auth.py    |  4 +-
 Allura/development.ini                         |  2 +-
 6 files changed, 62 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/56fa52cc/Allura/allura/templates/login_multifactor.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/login_multifactor.html b/Allura/allura/templates/login_multifactor.html
index 07eaa80..3edb53c 100644
--- a/Allura/allura/templates/login_multifactor.html
+++ b/Allura/allura/templates/login_multifactor.html
@@ -25,15 +25,18 @@
 
 {% block content %}
 <form method="post" action="/auth/do_multifactor">
-    <h2>Please enter your Multifactor Authentication Code</h2>
+    <h2>Enter your Multifactor Authentication Code</h2>
+    <p>
+    Please enter the {{ config['auth.multifactor.totp.length'] }}-digit code from your authenticator app:<br>
     {% if c.form_errors['code'] %}
-        <div class="fielderror">{{ c.form_errors['code'] }}</div>
+        <span class="fielderror">{{ c.form_errors['code'] }}</span><br>
     {% endif %}
     <input type="text" name="code" autofocus autocomplete="off"/>
     <input type="hidden" name="return_to" value="{{ return_to }}"/>
     <br>
     <input type="submit" value="Log In">
     {{ lib.csrf_token() }}
+    </p>
 </form>
 
 {% endblock %}

http://git-wip-us.apache.org/repos/asf/allura/blob/56fa52cc/Allura/allura/templates/reconfirm_auth.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/reconfirm_auth.html b/Allura/allura/templates/reconfirm_auth.html
index f44be2d..26d6fd2 100644
--- a/Allura/allura/templates/reconfirm_auth.html
+++ b/Allura/allura/templates/reconfirm_auth.html
@@ -26,8 +26,10 @@
 {% block content %}
 <form method="post">
     <h2>Password Confirmation</h2>
-    <p>To access this account security page, you must reconfirm your password:</p>
-    <div class="fielderror">{{ c.form_errors['password'] }}</div>
+    <p>To access this account security page, you must reconfirm your password:<br>
+    {% if c.form_errors['password'] %}
+        <span class="fielderror">{{ c.form_errors['password'] }}</span><br>
+    {% endif %}
     <input type="password" name="password" autofocus>
     <br>
     <input type="submit" value="Submit">
@@ -40,5 +42,6 @@
     {% endfor %}
 
     {{ lib.csrf_token() }}
+    </p>
 </form>
 {% endblock %}

http://git-wip-us.apache.org/repos/asf/allura/blob/56fa52cc/Allura/allura/templates/user_account_base.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/user_account_base.html b/Allura/allura/templates/user_account_base.html
index eb68667..71442ee 100644
--- a/Allura/allura/templates/user_account_base.html
+++ b/Allura/allura/templates/user_account_base.html
@@ -20,6 +20,7 @@
 {% extends g.theme.master %}
 
 {% block content %}
+{% if menu %}
   <ul id="account-nav-menu" class="b-hornav droppy">
       {% for item in menu -%}
       <li id="{{ item.tabid }}">
@@ -30,4 +31,5 @@
       </li>
       {%- endfor %}
   </ul>
+{% endif %}
 {% endblock %}

http://git-wip-us.apache.org/repos/asf/allura/blob/56fa52cc/Allura/allura/templates/user_totp.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/user_totp.html b/Allura/allura/templates/user_totp.html
index 4dce799..241ff42 100644
--- a/Allura/allura/templates/user_totp.html
+++ b/Allura/allura/templates/user_totp.html
@@ -30,26 +30,58 @@
         {% if c.user.get_pref('multifactor') %}
             <h3>Warning: this will invalidate your previous multifactor configuration.</h3>
         {% endif %}
-    <h2>Install App</h2>
-    <p>To use two-factor authentication, you will need to install an app on your phone.
-       You can use Duo Mobile, Authy, Google Authenticator, or Authenticator for Windows phones.</p>
+        <h2>Install App</h2>
+        <p>To use two-factor authentication, you will need to install an app on your phone.<br>
+            Install Google Authenticator for
+            <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2"><b>Android</b></a>
+            or <a href="https://itunes.apple.com/us/app/google-authenticator/id388497605"><b>iOS</b></a>.
+            <br>
+            Or use another app like Duo Mobile, Authy, or Authenticator for Windows phones.
+        </p>
     {% endif %}
 
     <h2>Scan this barcode with your app</h2>
-    <img src="{{ h.base64uri(qr) }}"/>
+    <img class="qrcode" src="{{ h.base64uri(qr) }}"/>
 
     {% if setup %}
-    <h2>Enter the code</h2>
-    <p>
-    Enter the 6-digit code to confirm it is set up correctly:
-    <form method="POST" action="totp_set">
-        <div class="fielderror">{{ c.form_errors['code'] }}</div>
-        <input type="text" name="code" autofocus autocomplete="off"/>
-        {{ lib.csrf_token() }}
-        <br>
-        <input type="submit" value="Submit">
-    </form>
-    </p>
+        <h2>Enter the code</h2>
+        <form method="POST" action="totp_set">
+        <p>
+            Enter the {{ config['auth.multifactor.totp.length'] }}-digit code to confirm it is set up correctly:<br>
+            {% if c.form_errors['code'] %}
+                <span class="fielderror">{{ c.form_errors['code'] }}</span><br>
+            {% endif %}
+            <input type="text" name="code" autofocus autocomplete="off"/>
+            {{ lib.csrf_token() }}
+            <br>
+            <input type="submit" value="Submit">
+            <a class="cancel" href="/auth/preferences/">Cancel</a>
+        </p>
+        </form>
+    {% else %}
+        <p>
+            You may use this to set up additional devices with the same two-factor key.<br>
+            <br>
+            If you are replacing a device, please <a href="totp_new">regenerate a brand new key</a>.<br>
+            <br>
+            <a href="/auth/preferences/">Back</a>
+        </p>
     {% endif %}
   </div>
 {% endblock %}
+
+{% block extra_css %}
+<style type="text/css">
+    .qrcode {
+        /* compensate for whitespace on QR code image */
+        position: relative;
+        top: -15px;
+        margin-bottom: -15px;
+    }
+    a.cancel {
+        /* align with floated button */
+        display: inline-block;
+        margin: 6px 10px;
+    }
+</style>
+{% endblock %}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/allura/blob/56fa52cc/Allura/allura/tests/functional/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index 3483e6f..e203869 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -2037,12 +2037,12 @@ class TestTwoFactor(TestController):
             assert_not_in('Password Confirmation', r)
 
             # still not required
-            datetime.utcnow.return_value = real_datetime(2016, 1, 1, 0, 0, 45)
+            datetime.utcnow.return_value = real_datetime(2016, 1, 1, 0, 1, 45)
             r = self.app.get('/auth/preferences/totp_new')
             assert_not_in('Password Confirmation', r)
 
             # required later
-            datetime.utcnow.return_value = real_datetime(2016, 1, 1, 0, 1, 3)
+            datetime.utcnow.return_value = real_datetime(2016, 1, 1, 0, 2, 3)
             r = self.app.get('/auth/preferences/totp_new')
             assert_in('Password Confirmation', r)
 

http://git-wip-us.apache.org/repos/asf/allura/blob/56fa52cc/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index a72f9fd..31ad42f 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -191,7 +191,7 @@ auth.upload_ssh_url = /auth/preferences/
 auth.recovery_hash_expiry_period = 600
 
 ; Some pages require users to reconfirm their password.  This controls how long that lasts for
-auth.reconfirm.seconds = 60
+auth.reconfirm.seconds = 120
 
 ; TOTP stands for Time-based One Time Password
 ; it is the most common two-factor auth protocol, used with Google Authenticator and other phone apps


[2/4] allura git commit: [#8117] add email notifications to 2FA; add helper with nice From: address

Posted by br...@apache.org.
[#8117] add email notifications to 2FA; add helper with nice From: address


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/b8562071
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/b8562071
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/b8562071

Branch: refs/heads/db/8117
Commit: b85620717fb7a727a6a727c9f5f4dea0eb75e8a7
Parents: 56fa52c
Author: Dave Brondsema <da...@brondsema.net>
Authored: Wed Aug 31 18:29:39 2016 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Thu Sep 1 10:54:05 2016 -0400

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py               | 13 ++++++--
 Allura/allura/lib/multifactor.py                |  2 +-
 Allura/allura/tasks/mail_tasks.py               | 33 +++++++++++++++++++-
 .../allura/templates/mail/twofactor_disabled.md | 26 +++++++++++++++
 .../allura/templates/mail/twofactor_enabled.md  | 26 +++++++++++++++
 Allura/allura/tests/functional/test_auth.py     | 11 +++++++
 6 files changed, 107 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/b8562071/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 7dbfa1b..42840d2 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -50,6 +50,7 @@ from allura.lib.widgets import forms, form_fields as ffw
 from allura.lib import mail_util
 from allura.lib.multifactor import TotpService
 from allura.controllers import BaseController
+from allura.tasks.mail_tasks import send_system_mail_to_user
 
 log = logging.getLogger(__name__)
 
@@ -685,7 +686,6 @@ class PreferencesController(BaseController):
     @reconfirm_auth
     @require_post()
     def totp_set(self, code, **kw):
-        # TODO: email notification
         key = session['totp_new_key']
         totp_service = TotpService.get()
         totp = totp_service.Totp(key)
@@ -702,18 +702,27 @@ class PreferencesController(BaseController):
             del session['totp_new_key']
             session.save()
             tg.flash('Two factor authentication has now been set up.')
+            email_body = g.jinja2_env.get_template('allura:templates/mail/twofactor_enabled.md').render(dict(
+                user=c.user,
+                config=config,
+            ))
+            send_system_mail_to_user(c.user, u'Two-Factor Authentication Enabled', email_body)
             redirect('.')
 
     @expose()
     @require_post()
     @reconfirm_auth
     def multifactor_disable(self, **kw):
-        # TODO: email notification
         h.auditlog_user('Disabled multifactor TOTP')
         totp_service = TotpService.get()
         totp_service.set_secret_key(c.user, None)
         c.user.set_pref('multifactor', False)
         tg.flash('Multifactor authentication has now been disabled.')
+        email_body = g.jinja2_env.get_template('allura:templates/mail/twofactor_disabled.md').render(dict(
+            user=c.user,
+            config=config,
+        ))
+        send_system_mail_to_user(c.user, u'Two-Factor Authentication Disabled', email_body)
         redirect('.')
 
 

http://git-wip-us.apache.org/repos/asf/allura/blob/b8562071/Allura/allura/lib/multifactor.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/multifactor.py b/Allura/allura/lib/multifactor.py
index 9970893..56827a4 100644
--- a/Allura/allura/lib/multifactor.py
+++ b/Allura/allura/lib/multifactor.py
@@ -117,7 +117,7 @@ class TotpService(object):
     def set_secret_key(self, user, key):
         '''
         :param user: a :class:`User <allura.model.auth.User>`
-        :param bytes key: may be `None` to clear out a key
+        :param bytes|None key: may be `None` to clear out a key
         '''
         raise NotImplementedError('set_secret_key')
 

http://git-wip-us.apache.org/repos/asf/allura/blob/b8562071/Allura/allura/tasks/mail_tasks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tasks/mail_tasks.py b/Allura/allura/tasks/mail_tasks.py
index 963555f..ce0f98a 100644
--- a/Allura/allura/tasks/mail_tasks.py
+++ b/Allura/allura/tasks/mail_tasks.py
@@ -18,7 +18,7 @@
 import logging
 import HTMLParser
 
-from pylons import tmpl_context as c, app_globals as g
+from pylons import tmpl_context as c, app_globals as g, config
 from bson import ObjectId
 
 from allura.lib import helpers as h
@@ -30,6 +30,7 @@ log = logging.getLogger(__name__)
 
 smtp_client = mail_util.SMTPClient()
 
+
 def mail_meta_content(metalink):
     '''
     Helper function used to include a view action button in your email client
@@ -47,6 +48,7 @@ def mail_meta_content(metalink):
     <meta itemprop="description" content="View"></meta>
     </div>""" % metalink)
 
+
 @task
 def route_email(
         peer, mailfrom, rcpttos, data):
@@ -223,3 +225,32 @@ def sendsimplemail(
     smtp_client.sendmail(
         [toaddr], fromaddr, reply_to, subject, message_id,
         in_reply_to, multi_msg, sender=sender, references=references, cc=cc, to=toaddr)
+
+
+def send_system_mail_to_user(user_or_emailaddr, subject, text):
+    '''
+    Sends a standard email from the Allura system itself, to a user.
+    This is a helper function around sendsimplemail() that generates a new task
+
+    :param user_or_emailaddr: an email addres (str) or a User object
+    :param subject: subject of the email
+    :param text: text of the email (markdown)
+    '''
+    if isinstance(user_or_emailaddr, basestring):
+        toaddr = user_or_emailaddr
+    else:
+        toaddr = user_or_emailaddr._id
+
+    email = {
+        'toaddr': toaddr,
+        'fromaddr': u'"{}" <{}>'.format(
+            config['site_name'],
+            config['forgemail.return_path']
+        ),
+        'sender': unicode(config['forgemail.return_path']),
+        'reply_to': unicode(config['forgemail.return_path']),
+        'message_id': h.gen_message_id(),
+        'subject': subject,
+        'text': text,
+    }
+    sendsimplemail.post(**email)

http://git-wip-us.apache.org/repos/asf/allura/blob/b8562071/Allura/allura/templates/mail/twofactor_disabled.md
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/mail/twofactor_disabled.md b/Allura/allura/templates/mail/twofactor_disabled.md
new file mode 100644
index 0000000..3e4e619
--- /dev/null
+++ b/Allura/allura/templates/mail/twofactor_disabled.md
@@ -0,0 +1,26 @@
+{#
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+-#}
+
+Hello {{ user.username }},
+
+You have recently disabled two-factor authentication on {{ config['site_name'] }}.  :(
+
+{% block footer %}
+If you did not do this, please contact us immediately.
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/allura/blob/b8562071/Allura/allura/templates/mail/twofactor_enabled.md
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/mail/twofactor_enabled.md b/Allura/allura/templates/mail/twofactor_enabled.md
new file mode 100644
index 0000000..e2d0ca0
--- /dev/null
+++ b/Allura/allura/templates/mail/twofactor_enabled.md
@@ -0,0 +1,26 @@
+{#
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+-#}
+
+Hello {{ user.username }},
+
+You have recently set up new two-factor authentication on {{ config['site_name'] }}.  This is a confirmation email, you are all set.
+
+{% block footer %}
+If you did not do this, please contact us immediately.
+{% endblock %}

http://git-wip-us.apache.org/repos/asf/allura/blob/b8562071/Allura/allura/tests/functional/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index e203869..a50a13a 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -2072,6 +2072,11 @@ class TestTwoFactor(TestController):
             assert_equal('Two factor authentication has now been set up.', json.loads(self.webflash(r))['message'],
                          self.webflash(r))
 
+        tasks = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendsimplemail')).all()
+        assert_equal(len(tasks), 1)
+        assert_equal(tasks[0].kwargs['subject'], 'Two-Factor Authentication Enabled')
+        assert_in('new two-factor authentication', tasks[0].kwargs['text'])
+
     def test_reset_totp(self):
         self._init_totp()
 
@@ -2137,6 +2142,12 @@ class TestTwoFactor(TestController):
         assert_equal(user.get_pref('multifactor'), False)
         assert_equal(TotpService().get().get_secret_key(user), None)
 
+        # email confirmation
+        tasks = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendsimplemail')).all()
+        assert_equal(len(tasks), 1)
+        assert_equal(tasks[0].kwargs['subject'], 'Two-Factor Authentication Disabled')
+        assert_in('disabled two-factor authentication', tasks[0].kwargs['text'])
+
     def test_login_totp(self):
         self._init_totp()
 


[3/4] allura git commit: [#8117] apply new mail helper to other places, so they get nicer From address display

Posted by br...@apache.org.
[#8117] apply new mail helper to other places, so they get nicer From address display


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/62aa90b9
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/62aa90b9
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/62aa90b9

Branch: refs/heads/db/8117
Commit: 62aa90b99a4ab21e4e0cdffb28e4500468b3fdde
Parents: b856207
Author: Dave Brondsema <da...@brondsema.net>
Authored: Thu Sep 1 10:30:45 2016 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Thu Sep 1 10:54:05 2016 -0400

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py                 |  9 +--------
 Allura/allura/model/auth.py                       | 10 +++-------
 Allura/allura/tasks/export_tasks.py               | 14 +++-----------
 Allura/allura/tests/functional/test_auth.py       |  3 ++-
 Allura/allura/tests/functional/test_site_admin.py |  3 ++-
 Allura/allura/tests/test_tasks.py                 |  2 +-
 6 files changed, 12 insertions(+), 29 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/62aa90b9/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 42840d2..669f81f 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -214,14 +214,7 @@ class AuthController(BaseController):
                 config=config,
                 hash=hash,
             ))
-
-            allura.tasks.mail_tasks.sendsimplemail.post(
-                toaddr=email_record.email,
-                fromaddr=config['forgemail.return_path'],
-                reply_to=config['forgemail.return_path'],
-                subject=subject,
-                message_id=h.gen_message_id(),
-                text=text)
+            send_system_mail_to_user(email_record.email, subject, text)
         h.auditlog_user('Password recovery link sent to: %s', email, user=user_record)
         flash(message)
         redirect('/')

http://git-wip-us.apache.org/repos/asf/allura/blob/62aa90b9/Allura/allura/model/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/auth.py b/Allura/allura/model/auth.py
index c1c8235..32b419a 100644
--- a/Allura/allura/model/auth.py
+++ b/Allura/allura/model/auth.py
@@ -188,13 +188,9 @@ class EmailAddress(MappedClass):
                 config=config
             ))
 
-            allura.tasks.mail_tasks.sendsimplemail.post(
-                toaddr=self.email,
-                fromaddr=config['forgemail.return_path'],
-                reply_to=config['forgemail.return_path'],
-                subject=u'%s - Email address claim attempt' % config['site_name'],
-                message_id=h.gen_message_id(),
-                text=text)
+            allura.tasks.mail_tasks.send_system_mail_to_user(self.email,
+                                                             u'%s - Email address claim attempt' % config['site_name'],
+                                                             text)
 
     def set_nonce_hash(self):
         self.nonce = sha256(os.urandom(10)).hexdigest()

http://git-wip-us.apache.org/repos/asf/allura/blob/62aa90b9/Allura/allura/tasks/export_tasks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tasks/export_tasks.py b/Allura/allura/tasks/export_tasks.py
index 9e2d73e..87fcc8b 100644
--- a/Allura/allura/tasks/export_tasks.py
+++ b/Allura/allura/tasks/export_tasks.py
@@ -84,17 +84,9 @@ class BulkExport(object):
             'not_exported_tools': list(set(tools) - set(exported_names)),
         }
 
-        email = {
-            'toaddr': unicode(user._id),
-            'fromaddr': unicode(tg.config['forgemail.return_path']),
-            'sender': unicode(tg.config['forgemail.return_path']),
-            'reply_to': unicode(tg.config['forgemail.return_path']),
-            'message_id': h.gen_message_id(),
-            'subject': u'Bulk export for project %s completed' % project.shortname,
-            'text': tmpl.render(tmpl_context)
-        }
-
-        mail_tasks.sendsimplemail.post(**email)
+        mail_tasks.send_system_mail_to_user(user,
+                                            u'Bulk export for project %s completed' % project.shortname,
+                                            tmpl.render(tmpl_context))
 
     def get_export_path(self, export_base_path, export_filename):
         """Create temporary directory for export files"""

http://git-wip-us.apache.org/repos/asf/allura/blob/62aa90b9/Allura/allura/tests/functional/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index a50a13a..828d207 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -1368,8 +1368,9 @@ To reset your password on %s, please visit the following URL:
 %s/auth/forgotten_password/%s''' % (config['site_name'], config['base_url'], hash)
 
         sendmail.post.assert_called_once_with(
+            sender='noreply@localhost',
             toaddr=email.email,
-            fromaddr=config['forgemail.return_path'],
+            fromaddr=u'"{}" <{}>'.format(config['site_name'], config['forgemail.return_path']),
             reply_to=config['forgemail.return_path'],
             subject='Allura Password recovery',
             message_id=gen_message_id(),

http://git-wip-us.apache.org/repos/asf/allura/blob/62aa90b9/Allura/allura/tests/functional/test_site_admin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_site_admin.py b/Allura/allura/tests/functional/test_site_admin.py
index d4e96a0..64c2dbb 100644
--- a/Allura/allura/tests/functional/test_site_admin.py
+++ b/Allura/allura/tests/functional/test_site_admin.py
@@ -709,8 +709,9 @@ To reset your password on %s, please visit the following URL:
 
 %s/auth/forgotten_password/%s''' % (config['site_name'], config['base_url'], hash)
         sendmail.post.assert_called_once_with(
+            sender='noreply@localhost',
             toaddr='test-user@example.org',
-            fromaddr=config['forgemail.return_path'],
+            fromaddr=u'"{}" <{}>'.format(config['site_name'], config['forgemail.return_path']),
             reply_to=config['forgemail.return_path'],
             subject='Allura Password recovery',
             message_id=gen_message_id(),

http://git-wip-us.apache.org/repos/asf/allura/blob/62aa90b9/Allura/allura/tests/test_tasks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_tasks.py b/Allura/allura/tests/test_tasks.py
index abf22c2..525e7e3 100644
--- a/Allura/allura/tests/test_tasks.py
+++ b/Allura/allura/tests/test_tasks.py
@@ -567,7 +567,7 @@ class TestExportTasks(unittest.TestCase):
         assert_equal(len(tasks), 1)
         assert_equal(tasks[0].kwargs['subject'],
                      'Bulk export for project test completed')
-        assert_equal(tasks[0].kwargs['fromaddr'], g.noreply)
+        assert_equal(tasks[0].kwargs['fromaddr'], '"Allura" <no...@localhost>')
         assert_equal(tasks[0].kwargs['reply_to'], g.noreply)
         text = tasks[0].kwargs['text']
         assert_in('The bulk export for project test is completed.', text)


[4/4] allura git commit: [#8117] option to send app links by email

Posted by br...@apache.org.
[#8117] option to send app links by email


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/a8d19801
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/a8d19801
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/a8d19801

Branch: refs/heads/db/8117
Commit: a8d198013973e1e236c8ca9d76df9bd0e08e3884
Parents: 62aa90b
Author: Dave Brondsema <da...@brondsema.net>
Authored: Thu Sep 1 12:07:56 2016 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Thu Sep 1 12:07:56 2016 -0400

----------------------------------------------------------------------
 Allura/allura/controllers/auth.py              |  9 +++++++
 Allura/allura/templates/mail/twofactor_apps.md | 28 +++++++++++++++++++++
 Allura/allura/templates/user_totp.html         | 22 ++++++++++++++++
 Allura/allura/tests/functional/test_auth.py    | 13 ++++++++++
 4 files changed, 72 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/a8d19801/Allura/allura/controllers/auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/auth.py b/Allura/allura/controllers/auth.py
index 669f81f..382f4b1 100644
--- a/Allura/allura/controllers/auth.py
+++ b/Allura/allura/controllers/auth.py
@@ -718,6 +718,15 @@ class PreferencesController(BaseController):
         send_system_mail_to_user(c.user, u'Two-Factor Authentication Disabled', email_body)
         redirect('.')
 
+    @expose()
+    @require_post()
+    def totp_send_link(self, **kw):
+        email_body = g.jinja2_env.get_template('allura:templates/mail/twofactor_apps.md').render(dict(
+            user=c.user,
+            config=config,
+        ))
+        send_system_mail_to_user(c.user, u'Two-Factor Authentication Apps', email_body)
+
 
 class UserInfoController(BaseController):
 

http://git-wip-us.apache.org/repos/asf/allura/blob/a8d19801/Allura/allura/templates/mail/twofactor_apps.md
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/mail/twofactor_apps.md b/Allura/allura/templates/mail/twofactor_apps.md
new file mode 100644
index 0000000..b5e80bd
--- /dev/null
+++ b/Allura/allura/templates/mail/twofactor_apps.md
@@ -0,0 +1,28 @@
+{#
+       Licensed to the Apache Software Foundation (ASF) under one
+       or more contributor license agreements.  See the NOTICE file
+       distributed with this work for additional information
+       regarding copyright ownership.  The ASF licenses this file
+       to you under the Apache License, Version 2.0 (the
+       "License"); you may not use this file except in compliance
+       with the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+       Unless required by applicable law or agreed to in writing,
+       software distributed under the License is distributed on an
+       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+       KIND, either express or implied.  See the License for the
+       specific language governing permissions and limitations
+       under the License.
+-#}
+
+Hello,
+
+Here are links to install Google Authenticator, which you'll need to use for two-factor authentication:
+
+[Google Authenticator for Android](https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2)
+
+[Google Authenticator for iOS](https://itunes.apple.com/us/app/google-authenticator/id388497605)
+
+Other authenticator apps work too, like Duo Mobile, Authy, and more.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/allura/blob/a8d19801/Allura/allura/templates/user_totp.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/user_totp.html b/Allura/allura/templates/user_totp.html
index 241ff42..53bc928 100644
--- a/Allura/allura/templates/user_totp.html
+++ b/Allura/allura/templates/user_totp.html
@@ -31,13 +31,17 @@
             <h3>Warning: this will invalidate your previous multifactor configuration.</h3>
         {% endif %}
         <h2>Install App</h2>
+        <form action="totp_send_link" id="totp_send_link" method="post">
         <p>To use two-factor authentication, you will need to install an app on your phone.<br>
             Install Google Authenticator for
             <a href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2"><b>Android</b></a>
             or <a href="https://itunes.apple.com/us/app/google-authenticator/id388497605"><b>iOS</b></a>.
+            <a href="#" class="ajax-submit-form">Email me these links.</a>
             <br>
             Or use another app like Duo Mobile, Authy, or Authenticator for Windows phones.
         </p>
+        {{ lib.csrf_token() }}
+        </form>
     {% endif %}
 
     <h2>Scan this barcode with your app</h2>
@@ -84,4 +88,22 @@
         margin: 6px 10px;
     }
 </style>
+{% endblock %}
+
+{% block extra_js %}
+<script type="text/javascript">
+$(function() {
+      $('a.ajax-submit-form').click(function(e){
+          e.preventDefault();
+          $form = $(this).closest('form');
+          $.post($form.attr('action'), $form.serialize())
+                  .done(function() {
+                      $('#messages').notify({message: 'Email sent!'});
+                  })
+                  .fail(function() {
+                      $('#messages').notify({message: 'Error sending email', status: 'error'});
+                  });
+      });
+});
+</script>
 {% endblock %}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/allura/blob/a8d19801/Allura/allura/tests/functional/test_auth.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_auth.py b/Allura/allura/tests/functional/test_auth.py
index 828d207..0e0da43 100644
--- a/Allura/allura/tests/functional/test_auth.py
+++ b/Allura/allura/tests/functional/test_auth.py
@@ -2221,3 +2221,16 @@ class TestTwoFactor(TestController):
             r.form['password'] = 'foo'
             r = r.form.submit()
             assert_in('Scan this barcode', r)
+
+    def test_send_links(self):
+        r = self.app.get('/auth/preferences/totp_new')
+        r.form['password'] = 'foo'
+        r = r.form.submit()
+
+        r = r.forms['totp_send_link'].submit()
+
+        tasks = M.MonQTask.query.find(dict(task_name='allura.tasks.mail_tasks.sendsimplemail')).all()
+        assert_equal(len(tasks), 1)
+        assert_equal(tasks[0].kwargs['subject'], 'Two-Factor Authentication Apps')
+        assert_in('itunes.apple.com', tasks[0].kwargs['text'])
+        assert_in('play.google.com', tasks[0].kwargs['text'])