Skip to content

Commit

Permalink
Send password reset emails to users
Browse files Browse the repository at this point in the history
  • Loading branch information
nigelbabu committed Oct 22, 2012
1 parent fd20d0b commit 64bfc8a
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 11 deletions.
2 changes: 2 additions & 0 deletions pybossa/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from flask import Flask
from flaskext.login import LoginManager, current_user
from flaskext.gravatar import Gravatar
from flask.ext.mail import Mail
from flask.ext.sqlalchemy import SQLAlchemy

from pybossa import default_settings as settings
Expand Down Expand Up @@ -74,4 +75,5 @@ def setup_logging(app):
login_manager.login_message = u"Please sign in to access this page."
app = create_app()
db = SQLAlchemy(app)
mail = Mail(app)
signer = URLSafeTimedSerializer(app.config['ITSDANGEORUSKEY'])
15 changes: 15 additions & 0 deletions pybossa/templates/account/email/forgot_password.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Hello {{ user.fullname }},

We received a request to recover your password for {{ config.BRAND }}.

If you did not request this, please ignore this email.

To recover your password, please visit the URL below:

[Click here to recover your account][recover]

[recover]: {{ recovery_url }}

Regards,

{{ config.BRAND }} Team
12 changes: 12 additions & 0 deletions pybossa/templates/account/email/forgot_password_openid.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Hello {{ user.fullname }},

We received a request to recover your password for {{ config.BRAND }}.

If you did not request this, please ignore this email.

Our records show that you use your {{ account_name }} account to sign in. Please use
the same account to sign-in again. If you forgot the password to your {{ account_name }}
account, please contact {{ acount_name }}.

Regards,
{{ config.BRAND }} Team
36 changes: 33 additions & 3 deletions pybossa/view/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@
# along with PyBOSSA. If not, see <http://www.gnu.org/licenses/>.

from itsdangerous import BadData
from markdown import markdown
from flask import Blueprint, request, url_for, flash, redirect, session, abort
from flask import render_template, current_app
from flaskext.login import login_required, login_user, logout_user,\
current_user
from flask.ext.mail import Message
from flaskext.wtf import Form, TextField, PasswordField, validators,\
ValidationError, IntegerField, HiddenInput

import pybossa.model as model
from pybossa.core import db, signer
from pybossa.core import db, signer, mail
from pybossa.util import Unique
from pybossa.util import Pagination
from pybossa.util import Twitter
Expand Down Expand Up @@ -304,9 +306,37 @@ def forgot_password():
form = ForgotPasswordForm(request.form)
if form.validate_on_submit():
user = model.User.query.filter_by(email_addr=form.email_addr.data
).first()
flash("We've send you email with account recovery instructions!",
).first()
if user and user.email_addr:
msg = Message(subject='Account Recovery',
recipients=[user.email_addr])
if user.twitter_user_id:
msg.body = render_template(
'/account/email/forgot_password_openid.md',
user=user, account_name='Twitter')
elif user.facebook_user_id:
msg.body = render_template(
'/account/email/forgot_password_openid.md',
user=user, account_name='Facebook')
elif user.google_user_id:
msg.body = render_template(
'/account/email/forgot_password_openid.md',
user=user, account_name='Google')
else:
userdict = {'user': user.name, 'password': user.passwd_hash}
key = signer.dumps(userdict, salt='password-reset')
recovery_url = url_for('.reset_password', key=key, _external=True)
msg.body = render_template(
'/account/email/forgot_password.md',
user=user, recovery_url=recovery_url)
msg.html = markdown(msg.body)
mail.send(msg)
flash("We've send you email with account recovery instructions!",
'success')
else:
flash("We don't have this email in our records. You may have"
" signed up with a different email or used Twitter, "
"Facebook, or Google to sign-in", 'error')
if request.method == 'POST' and not form.validate():
flash('Something went wrong, please correct the errors on the '
'form', 'error')
Expand Down
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Flask-WTF==0.6
Flask-Gravatar
Flask-OAuth
Flask-SQLAlchemy
Flask-Mail
dateutils
alembic
psycopg2
Expand Down
2 changes: 1 addition & 1 deletion test/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import pybossa.web as web
import pybossa.model as model
from pybossa.core import db
from pybossa.core import db, mail

_here = os.path.dirname(__file__)
web.app.config['TESTING'] = True
Expand Down
19 changes: 12 additions & 7 deletions test/test_web.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import json

from base import web, model, Fixtures
from base import web, model, Fixtures, mail
from mock import patch
from itsdangerous import BadSignature
from collections import namedtuple
from flask import g
from pybossa.core import db, signer


Expand Down Expand Up @@ -1277,12 +1276,18 @@ def side_effects(*args, **kwargs):
def test_45_password_reset_link(self):
"""Test WEB password reset email form"""
res = self.app.post('/account/forgot-password', data={
'email': '[email protected]'
'email_addr': '[email protected]'
}, follow_redirects=True)
assert "This email doesn't seem to be associated with an account" in res.data
assert ("We don't have this email in our records. You may have"
" signed up with a different email or used Twitter, "
"Facebook, or Google to sign-in") in res.data

self.register()
res = self.app.post('/account/forgot-password', data={
'email': '[email protected]'
# TODO: This is a hack to get tests working. Documented method to
# supress mail sending doesn't seem to work
mail.suppress = True
with mail.record_messages() as outbox:
self.app.post('/account/forgot-password', data={
'email_addr': '[email protected]'
}, follow_redirects=True)
assert g.outbox[0].subject == 'Password Recovery'
assert outbox[0].subject == 'Account Recovery'

0 comments on commit 64bfc8a

Please sign in to comment.