@@ -214,7 +214,7 @@
Hi {{username}},
You recently requested to reset your password for your account. Use the button below to reset it.
- This password reset is only valid for the next 24 hours.
+ This password reset link is only valid for {{ expiration_delay }}.
diff --git a/fittrackee_api/fittrackee_api/email/templates/password_reset_request/en/body.txt b/fittrackee_api/fittrackee_api/email/templates/password_reset_request/en/body.txt
index a139ff70..3db11c9f 100644
--- a/fittrackee_api/fittrackee_api/email/templates/password_reset_request/en/body.txt
+++ b/fittrackee_api/fittrackee_api/email/templates/password_reset_request/en/body.txt
@@ -1,6 +1,6 @@
Hi {{username}},
-You recently requested to reset your password for your FitTrackee account. Use the button below to reset it. This password reset is only valid for the next 24 hours.
+You recently requested to reset your password for your FitTrackee account. Use the button below to reset it. This password reset link is only valid for {{ expiration_delay }}.
Reset your password ( {{ password_reset_url }} )
diff --git a/fittrackee_api/fittrackee_api/email/templates/password_reset_request/fr/body.html b/fittrackee_api/fittrackee_api/email/templates/password_reset_request/fr/body.html
index 092113cb..a188c548 100644
--- a/fittrackee_api/fittrackee_api/email/templates/password_reset_request/fr/body.html
+++ b/fittrackee_api/fittrackee_api/email/templates/password_reset_request/fr/body.html
@@ -194,8 +194,7 @@
-
-
+
@@ -216,7 +215,7 @@
Bonjour {{username}},
Vous avez récemment demander la réinitilisation du mot de passe de votre compte sur FitTrackee.
Cliquez sur le bouton ci-dessous pour le réinitialiser.
- Cette réinitialisation n'est valide que pendant 1 heure.
+ Cette réinitialisation n'est valide que pendant {{ expiration_delay }}.
diff --git a/fittrackee_api/fittrackee_api/email/templates/password_reset_request/fr/body.txt b/fittrackee_api/fittrackee_api/email/templates/password_reset_request/fr/body.txt
index a0f4fafc..f2643aed 100644
--- a/fittrackee_api/fittrackee_api/email/templates/password_reset_request/fr/body.txt
+++ b/fittrackee_api/fittrackee_api/email/templates/password_reset_request/fr/body.txt
@@ -1,7 +1,7 @@
Bonjour {{username}},
Vous avez récemment demander la réinitilisation du mot de passe de votre compte sur FitTrackee.
-Cliquez sur le lien ci-dessous pour le réinitialiser. Ce lien n'est valide que pendant 1 heure.
+Cliquez sur le lien ci-dessous pour le réinitialiser. Ce lien n'est valide que pendant {{ expiration_delay }}.
Réinitialiser le mot de passe: ( {{ password_reset_url }} )
diff --git a/fittrackee_api/fittrackee_api/tests/template_results/password_reset_request.py b/fittrackee_api/fittrackee_api/tests/template_results/password_reset_request.py
index 06fa7dd0..3c692b6d 100644
--- a/fittrackee_api/fittrackee_api/tests/template_results/password_reset_request.py
+++ b/fittrackee_api/fittrackee_api/tests/template_results/password_reset_request.py
@@ -2,7 +2,7 @@
expected_en_text_body = """Hi test,
-You recently requested to reset your password for your FitTrackee account. Use the button below to reset it. This password reset is only valid for the next 24 hours.
+You recently requested to reset your password for your FitTrackee account. Use the button below to reset it. This password reset link is only valid for 3 seconds.
Reset your password ( http://localhost/password-reset?token=xxx )
@@ -14,7 +14,7 @@ The FitTrackee Team"""
expected_fr_text_body = """Bonjour test,
Vous avez récemment demander la réinitilisation du mot de passe de votre compte sur FitTrackee.
-Cliquez sur le lien ci-dessous pour le réinitialiser. Ce lien n'est valide que pendant 1 heure.
+Cliquez sur le lien ci-dessous pour le réinitialiser. Ce lien n'est valide que pendant 3 secondes.
Réinitialiser le mot de passe: ( http://localhost/password-reset?token=xxx )
@@ -25,7 +25,7 @@ Merci,
L'équipe FitTrackee"""
expected_en_html_body = """
-
+
@@ -45,7 +45,7 @@ expected_en_html_body = """
Hi test,
You recently requested to reset your password for your account. Use the button below to reset it.
- This password reset is only valid for the next 24 hours.
+ This password reset link is only valid for 3 seconds.
@@ -99,8 +99,7 @@ expected_en_html_body = """
"""
expected_fr_html_body = """
-
-
+
@@ -121,7 +120,7 @@ expected_fr_html_body = """
Bonjour test,
Vous avez récemment demander la réinitilisation du mot de passe de votre compte sur FitTrackee.
Cliquez sur le bouton ci-dessous pour le réinitialiser.
- Cette réinitialisation n'est valide que pendant 1 heure.
+ Cette réinitialisation n'est valide que pendant 3 secondes.
diff --git a/fittrackee_api/fittrackee_api/tests/test_email.py b/fittrackee_api/fittrackee_api/tests/test_email.py
index 0aedfcf0..4e65f183 100644
--- a/fittrackee_api/fittrackee_api/tests/test_email.py
+++ b/fittrackee_api/fittrackee_api/tests/test_email.py
@@ -32,6 +32,7 @@ class TestEmailMessage:
class TestEmailSending:
email_data = {
+ 'expiration_delay': '3 seconds',
'username': 'test',
'password_reset_url': f'http://localhost/password-reset?token=xxx',
'operating_system': 'Linux',
diff --git a/fittrackee_api/fittrackee_api/tests/test_email_template_password_request.py b/fittrackee_api/fittrackee_api/tests/test_email_template_password_request.py
index b9ca884a..e37815a3 100644
--- a/fittrackee_api/fittrackee_api/tests/test_email_template_password_request.py
+++ b/fittrackee_api/fittrackee_api/tests/test_email_template_password_request.py
@@ -33,6 +33,7 @@ class TestEmailTemplateForPasswordRequest:
def test_it_gets_text_body(self, app, lang, expected_text_body):
email_template = EmailTemplate(app.config.get('TEMPLATES_FOLDER'))
email_data = {
+ 'expiration_delay': '3 seconds' if lang == 'en' else '3 secondes',
'username': 'test',
'password_reset_url': f'http://localhost/password-reset?token=xxx',
'operating_system': 'Linux',
@@ -48,6 +49,7 @@ class TestEmailTemplateForPasswordRequest:
def test_it_gets_en_html_body(self, app):
email_template = EmailTemplate(app.config.get('TEMPLATES_FOLDER'))
email_data = {
+ 'expiration_delay': '3 seconds',
'username': 'test',
'password_reset_url': f'http://localhost/password-reset?token=xxx',
'operating_system': 'Linux',
@@ -63,6 +65,7 @@ class TestEmailTemplateForPasswordRequest:
def test_it_gets_fr_html_body(self, app):
email_template = EmailTemplate(app.config.get('TEMPLATES_FOLDER'))
email_data = {
+ 'expiration_delay': '3 secondes',
'username': 'test',
'password_reset_url': f'http://localhost/password-reset?token=xxx',
'operating_system': 'Linux',
diff --git a/fittrackee_api/fittrackee_api/users/auth.py b/fittrackee_api/fittrackee_api/users/auth.py
index 3e630d5e..40ae317f 100644
--- a/fittrackee_api/fittrackee_api/users/auth.py
+++ b/fittrackee_api/fittrackee_api/users/auth.py
@@ -14,6 +14,7 @@ from .utils import (
authenticate,
check_passwords,
display_readable_file_size,
+ get_readable_duration,
register_controls,
verify_extension_and_size,
)
@@ -700,6 +701,10 @@ def request_password_reset():
password_reset_token = user.encode_password_reset_token(user.id)
ui_url = current_app.config['UI_URL']
email_data = {
+ 'expiration_delay': get_readable_duration(
+ current_app.config.get('PASSWORD_TOKEN_EXPIRATION_SECONDS'),
+ 'en' if user.language is None else user.language,
+ ),
'username': user.username,
'password_reset_url': (
f'{ui_url}/password-reset?token={password_reset_token.decode()}' # noqa
diff --git a/fittrackee_api/fittrackee_api/users/utils.py b/fittrackee_api/fittrackee_api/users/utils.py
index 4da2b42b..2c8c6f6f 100644
--- a/fittrackee_api/fittrackee_api/users/utils.py
+++ b/fittrackee_api/fittrackee_api/users/utils.py
@@ -1,6 +1,8 @@
import re
+from datetime import timedelta
from functools import wraps
+import humanize
from flask import current_app, jsonify, request
from .models import User
@@ -148,3 +150,12 @@ def display_readable_file_size(size_in_bytes):
return f"{size_in_bytes:3.1f}{unit}"
size_in_bytes /= 1024.0
return f"{size_in_bytes} bytes"
+
+
+def get_readable_duration(duration, locale='en'):
+ if locale != 'en':
+ _t = humanize.i18n.activate(locale) # noqa
+ readable_duration = humanize.naturaldelta(timedelta(seconds=duration))
+ if locale != 'en':
+ humanize.i18n.deactivate()
+ return readable_duration
diff --git a/fittrackee_api/poetry.lock b/fittrackee_api/poetry.lock
index 223fb3bb..eeeb3fe2 100644
--- a/fittrackee_api/poetry.lock
+++ b/fittrackee_api/poetry.lock
@@ -322,6 +322,17 @@ gevent = ["gevent (>=0.13)"]
setproctitle = ["setproctitle"]
tornado = ["tornado (>=0.2)"]
+[[package]]
+category = "main"
+description = "Python humanize utilities"
+name = "humanize"
+optional = false
+python-versions = ">=3.5"
+version = "2.5.0"
+
+[package.extras]
+tests = ["freezegun", "pytest", "pytest-cov"]
+
[[package]]
category = "main"
description = "Internationalized Domain Names in Applications (IDNA)"
@@ -995,7 +1006,7 @@ docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
testing = ["jaraco.itertools", "func-timeout"]
[metadata]
-content-hash = "4199f7c3f0fe738bf7d846017b57e9903aff0b4697a8570be54a9ed63bd20306"
+content-hash = "344f1311eea15fb17b78dea1fe646a994498814a5ff76374d78f37d0643de282"
python-versions = "^3.7"
[metadata.files]
@@ -1192,6 +1203,10 @@ gunicorn = [
{file = "gunicorn-20.0.4-py2.py3-none-any.whl", hash = "sha256:cd4a810dd51bf497552cf3f863b575dabd73d6ad6a91075b65936b151cbf4f9c"},
{file = "gunicorn-20.0.4.tar.gz", hash = "sha256:1904bb2b8a43658807108d59c3f3d56c2b6121a701161de0ddf9ad140073c626"},
]
+humanize = [
+ {file = "humanize-2.5.0-py3-none-any.whl", hash = "sha256:89062c6db8601693b7d223443d0d7529aa9577df43a1387ddd4b9c273abb4a51"},
+ {file = "humanize-2.5.0.tar.gz", hash = "sha256:8a68bd9bccb899fd9bfb1e6d96c1e84e4475551cc9a5b5bdbd69b9b1cfd19c80"},
+]
idna = [
{file = "idna-2.9-py2.py3-none-any.whl", hash = "sha256:a068a21ceac8a4d63dbfd964670474107f541babbd2250d61922f029858365fa"},
{file = "idna-2.9.tar.gz", hash = "sha256:7588d1c14ae4c77d74036e8c22ff447b26d0fde8f007354fd48a7814db15b7cb"},
diff --git a/fittrackee_api/pyproject.toml b/fittrackee_api/pyproject.toml
index 31cb0e27..9794cffb 100644
--- a/fittrackee_api/pyproject.toml
+++ b/fittrackee_api/pyproject.toml
@@ -18,6 +18,7 @@ pytz = "^2020.1"
python-forecastio = "^1.4"
gunicorn = "^20.0"
tqdm = "^4.42"
+humanize = "^2.5.0"
[tool.poetry.dev-dependencies]
pytest = "^5.3"
| | | |