From a2336c5de836267a4e88961422fc3f26cedab47e Mon Sep 17 00:00:00 2001 From: Cédric Bonhomme Date: Thu, 18 Feb 2016 21:41:50 +0100 Subject: we now specify the validity period of the activation link. --- src/conf.py | 2 ++ src/conf/conf.cfg-sample | 1 + src/web/lib/user_utils.py | 6 +++--- src/web/notifications.py | 17 ++++++++++++----- src/web/templates/emails/account_activation.txt | 9 +++++++++ src/web/views/user.py | 2 +- 6 files changed, 28 insertions(+), 9 deletions(-) create mode 100644 src/web/templates/emails/account_activation.txt (limited to 'src') diff --git a/src/conf.py b/src/conf.py index 1cef95dc..0fcb330e 100644 --- a/src/conf.py +++ b/src/conf.py @@ -28,6 +28,7 @@ DEFAULTS = {"platform_url": "https://jarr.herokuapp.com/", "postmark_api_key": "", "recaptcha_public_key": "", "recaptcha_private_key": "", + "token_validity_period": "3600", "nb_worker": "100", "api_login": "", "api_passwd": "", @@ -79,6 +80,7 @@ RECAPTCHA_PUBLIC_KEY = config.get('misc', 'recaptcha_public_key') RECAPTCHA_PRIVATE_KEY = config.get('misc', 'recaptcha_private_key') SECURITY_PASSWORD_SALT = config.get('misc', 'security_password_salt') +TOKEN_VALIDITY_PERIOD = config.getint('misc', 'token_validity_period') LOG_PATH = os.path.abspath(config.get('misc', 'log_path')) NB_WORKER = config.getint('misc', 'nb_worker') API_LOGIN = config.get('crawler', 'api_login') diff --git a/src/conf/conf.cfg-sample b/src/conf/conf.cfg-sample index 286ccbe5..1fd572ba 100644 --- a/src/conf/conf.cfg-sample +++ b/src/conf/conf.cfg-sample @@ -10,6 +10,7 @@ admin_email = recaptcha_public_key = recaptcha_private_key = security_password_salt = a secret to confirm user account +token_validity_period = 3600 log_path = ./src/web/var/jarr.log nb_worker = 5 log_level = info diff --git a/src/web/lib/user_utils.py b/src/web/lib/user_utils.py index d5c3da22..dfeb8dfa 100644 --- a/src/web/lib/user_utils.py +++ b/src/web/lib/user_utils.py @@ -1,7 +1,7 @@ from itsdangerous import URLSafeTimedSerializer - +import conf from bootstrap import application @@ -10,13 +10,13 @@ def generate_confirmation_token(email): return serializer.dumps(email, salt=application.config['SECURITY_PASSWORD_SALT']) -def confirm_token(token, expiration=3600): +def confirm_token(token): serializer = URLSafeTimedSerializer(application.config['SECRET_KEY']) try: email = serializer.loads( token, salt=application.config['SECURITY_PASSWORD_SALT'], - max_age=expiration + max_age=conf.TOKEN_VALIDITY_PERIOD ) except: return False diff --git a/src/web/notifications.py b/src/web/notifications.py index 309da2a3..19562fad 100644 --- a/src/web/notifications.py +++ b/src/web/notifications.py @@ -19,6 +19,7 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +from flask import render_template import conf from web import emails from web.lib.user_utils import generate_confirmation_token @@ -43,10 +44,16 @@ def new_account_notification(user): Account creation notification. """ token = generate_confirmation_token(user.email) - plaintext = """Hello,\n\nYour account has been created. Click on the following link to confirm it:\n%s\n\nSee you,""" % \ - (conf.PLATFORM_URL + 'user/confirm_account/' + token) + expire_time = datetime.datetime.now() + \ + datetime.timedelta(seconds=conf.TOKEN_VALIDITY_PERIOD) + + plaintext = render_template('emails/account_activation.txt', + user=user, platform_url=conf.PLATFORM_URL, + token=token, + expire_time=expire_time) + emails.send(to=user.email, bcc=conf.NOTIFICATION_EMAIL, - subject="[jarr] Account creation", plaintext=plaintext) + subject="[JARR] Account creation", plaintext=plaintext) def new_account_activation(user): """ @@ -55,7 +62,7 @@ def new_account_activation(user): plaintext = """Hello,\n\nYour account has been activated. You can now connect to the platform:\n%s\n\nSee you,""" % \ (conf.PLATFORM_URL) emails.send(to=user.email, bcc=conf.NOTIFICATION_EMAIL, - subject="[jarr] Account activated", plaintext=plaintext) + subject="[JARR] Account activated", plaintext=plaintext) def new_password_notification(user, password): """ @@ -66,4 +73,4 @@ def new_password_notification(user, password): plaintext += "\n\nIt is advised to replace it as soon as connected to jarr.\n\nSee you," emails.send(to=user.email, bcc=conf.NOTIFICATION_EMAIL, - subject="[jarr] New password", plaintext=plaintext) + subject="[JARR] New password", plaintext=plaintext) diff --git a/src/web/templates/emails/account_activation.txt b/src/web/templates/emails/account_activation.txt new file mode 100644 index 00000000..ce7a8dc2 --- /dev/null +++ b/src/web/templates/emails/account_activation.txt @@ -0,0 +1,9 @@ +Hello {{ user.nickname }}, + +Your account has been created. +Click on the following link to confirm it: +{{ platform_url }}user/confirm_account/{{ token }} + +The link expires at {{ expire_time.strftime('%Y-%m-%d %H:%M') }}. + +See you, diff --git a/src/web/views/user.py b/src/web/views/user.py index 57153003..06dc2089 100644 --- a/src/web/views/user.py +++ b/src/web/views/user.py @@ -111,7 +111,7 @@ def confirm_account(token=None): user_contr = UserController() user, email = None, None if token != "": - email = confirm_token(token, expiration=3600) + email = confirm_token(token) if email: user = user_contr.read(email=email).first() if user is not None: -- cgit