API - display password reset link expiration delay in email
This commit is contained in:
parent
b351f3d42c
commit
075f98e6e5
@ -194,7 +194,7 @@
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<span class="preheader">Use this link to reset your password. The link is only valid for 24 hours.</span>
|
||||
<span class="preheader">Use this link to reset your password. The link is only valid for {{ expiration_delay }}.</span>
|
||||
<table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td align="center">
|
||||
@ -214,7 +214,7 @@
|
||||
<div class="f-fallback">
|
||||
<h1>Hi {{username}},</h1>
|
||||
<p>You recently requested to reset your password for your account. Use the button below to reset it.
|
||||
<strong>This password reset is only valid for the next 24 hours.</strong>
|
||||
<strong>This password reset link is only valid for {{ expiration_delay }}.</strong>
|
||||
</p>
|
||||
<table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
|
@ -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 }} )
|
||||
|
||||
|
@ -194,8 +194,7 @@
|
||||
<![endif]-->
|
||||
</head>
|
||||
<body>
|
||||
<span class="preheader">Use this link to reset your password. The link is only valid for 24 hours.</span>
|
||||
<span class="preheader">Utiliser ce lien pour réinitialiser le mot de passe. Ce lien n'est valide que pendant 1 heure.</span>
|
||||
<span class="preheader">Utiliser ce lien pour réinitialiser le mot de passe. Ce lien n'est valide que pendant {{ expiration_delay }}.</span>
|
||||
<table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td align="center">
|
||||
@ -216,7 +215,7 @@
|
||||
<h1>Bonjour {{username}},</h1>
|
||||
<p>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.
|
||||
<strong>Cette réinitialisation n'est valide que pendant 1 heure.</strong>
|
||||
<strong>Cette réinitialisation n'est valide que pendant {{ expiration_delay }}.</strong>
|
||||
</p>
|
||||
<table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
|
@ -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 }} )
|
||||
|
||||
|
@ -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 = """ <body>
|
||||
<span class="preheader">Use this link to reset your password. The link is only valid for 24 hours.</span>
|
||||
<span class="preheader">Use this link to reset your password. The link is only valid for 3 seconds.</span>
|
||||
<table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td align="center">
|
||||
@ -45,7 +45,7 @@ expected_en_html_body = """ <body>
|
||||
<div class="f-fallback">
|
||||
<h1>Hi test,</h1>
|
||||
<p>You recently requested to reset your password for your account. Use the button below to reset it.
|
||||
<strong>This password reset is only valid for the next 24 hours.</strong>
|
||||
<strong>This password reset link is only valid for 3 seconds.</strong>
|
||||
</p>
|
||||
<table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
@ -99,8 +99,7 @@ expected_en_html_body = """ <body>
|
||||
</html>"""
|
||||
|
||||
expected_fr_html_body = """ <body>
|
||||
<span class="preheader">Use this link to reset your password. The link is only valid for 24 hours.</span>
|
||||
<span class="preheader">Utiliser ce lien pour réinitialiser le mot de passe. Ce lien n'est valide que pendant 1 heure.</span>
|
||||
<span class="preheader">Utiliser ce lien pour réinitialiser le mot de passe. Ce lien n'est valide que pendant 3 secondes.</span>
|
||||
<table class="email-wrapper" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
<td align="center">
|
||||
@ -121,7 +120,7 @@ expected_fr_html_body = """ <body>
|
||||
<h1>Bonjour test,</h1>
|
||||
<p>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.
|
||||
<strong>Cette réinitialisation n'est valide que pendant 1 heure.</strong>
|
||||
<strong>Cette réinitialisation n'est valide que pendant 3 secondes.</strong>
|
||||
</p>
|
||||
<table class="body-action" align="center" width="100%" cellpadding="0" cellspacing="0" role="presentation">
|
||||
<tr>
|
||||
|
@ -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',
|
||||
|
@ -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',
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
17
fittrackee_api/poetry.lock
generated
17
fittrackee_api/poetry.lock
generated
@ -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"},
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user