diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 32e4adf3..b91de94b 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -20,6 +20,7 @@ Changed - Simpler and safer authentication logic (#270) - Use token based auth to reset passwords (#269) - Better install doc (#275) +- Use token based auth in invitation e-mails (#280) Added ===== diff --git a/ihatemoney/models.py b/ihatemoney/models.py index c801b745..9e11054d 100644 --- a/ihatemoney/models.py +++ b/ihatemoney/models.py @@ -5,8 +5,8 @@ from flask_sqlalchemy import SQLAlchemy, BaseQuery from flask import g, current_app from sqlalchemy import orm -from itsdangerous import (TimedJSONWebSignatureSerializer - as Serializer, BadSignature, SignatureExpired) +from itsdangerous import (TimedJSONWebSignatureSerializer, URLSafeSerializer, + BadSignature, SignatureExpired) db = SQLAlchemy() @@ -201,22 +201,32 @@ class Project(db.Model): db.session.delete(self) db.session.commit() - def generate_token(self, expiration): + def generate_token(self, expiration=0): """Generate a timed and serialized JsonWebToken :param expiration: Token expiration time (in seconds) """ - serializer = Serializer(current_app.config['SECRET_KEY'], expiration) - return serializer.dumps({'project_id': self.id}).decode('utf-8') + if expiration: + serializer = TimedJSONWebSignatureSerializer( + current_app.config['SECRET_KEY'], + expiration) + token = serializer.dumps({'project_id': self.id}).decode('utf-8') + else: + serializer = URLSafeSerializer(current_app.config['SECRET_KEY']) + token = serializer.dumps({'project_id': self.id}) + return token @staticmethod - def verify_token(token): + def verify_token(token, token_type="timed_token"): """Return the project id associated to the provided token, None if the provided token is expired or not valid. :param token: Serialized TimedJsonWebToken """ - serializer = Serializer(current_app.config['SECRET_KEY']) + if token_type == "timed_token": + serializer = TimedJSONWebSignatureSerializer(current_app.config['SECRET_KEY']) + else: + serializer = URLSafeSerializer(current_app.config['SECRET_KEY']) try: data = serializer.loads(token) except SignatureExpired: diff --git a/ihatemoney/templates/authenticate.html b/ihatemoney/templates/authenticate.html index 98914d09..4e8eb779 100644 --- a/ihatemoney/templates/authenticate.html +++ b/ihatemoney/templates/authenticate.html @@ -3,8 +3,9 @@

Authentication

{% if create_project %} -

{{ _("The project you are trying to access do not exist, do you want -to") }} {{ _("create it") }}{{ _("?") }} +

{{ _("The project you are trying to access do not exist, do you want to") }} + + {{ _("create it") }}{{ _("?") }}

{% endif %}
diff --git a/ihatemoney/templates/invitation_mail.en b/ihatemoney/templates/invitation_mail.en index 03f51412..eeaafdb9 100644 --- a/ihatemoney/templates/invitation_mail.en +++ b/ihatemoney/templates/invitation_mail.en @@ -4,7 +4,9 @@ Someone using the email address {{ g.project.contact_email }} invited you to sha It's as simple as saying what did you paid for, for who, and how much did it cost you, we are caring about the rest. -You can access it here: {{ config['SITE_URL'] }}{{ url_for(".list_bills") }} and the private code is "{{ g.project.password }}". +You can log in using this link: {{ url_for(".authenticate", _external=True, token=g.project.generate_token()) }}. +Once logged in you can use the following link which is easier to remember: {{ url_for(".list_bills", _external=True) }} +If your cookie gets deleted or if you log out, you will need to log back in using the first link. Enjoy, Some weird guys (with beards) diff --git a/ihatemoney/templates/invitation_mail.fr b/ihatemoney/templates/invitation_mail.fr index 53698ddc..a95f9e9e 100644 --- a/ihatemoney/templates/invitation_mail.fr +++ b/ihatemoney/templates/invitation_mail.fr @@ -4,6 +4,8 @@ Quelqu'un avec l'addresse email "{{ g.project.contact_email }}" vous à invité C'est aussi simple que de dire qui à payé pour quoi, pour qui, et combien celà à coûté, on s'occuppe du reste. -Vous pouvez accéder à la page ici: {{ config['SITE_URL'] }}{{ url_for(".list_bills") }} et le code est "{{ g.project.password }}". +Vous pouvez vous authentifier avec le lien suivant: {{ url_for(".authenticate", _external=True, token=g.project.generate_token()) }}. +Une fois authentifié, vous pouvez utiliser le lien suivant qui est plus facile à mémoriser: {{ url_for(".list_bills", _external=True) }} +Si votre cookie est supprimé ou si vous vous déconnectez, voous devrez vous réauthentifier en utilisant le premier lien. Have fun, diff --git a/ihatemoney/templates/list_bills.html b/ihatemoney/templates/list_bills.html index 13866369..e4034d48 100644 --- a/ihatemoney/templates/list_bills.html +++ b/ihatemoney/templates/list_bills.html @@ -92,7 +92,7 @@ {% endblock %} {% block content %} -
{{ _("The project identifier is") }} {{ g.project.id }}, {{ _("remember it!") }}
+
{{ _("Invite people to join this project!") }}
{{ _("Add a new bill") }}