API - set language on account creation and use it in confirmation email
This commit is contained in:
parent
c50c3c1f92
commit
5549eff08b
@ -1,6 +1,7 @@
|
||||
import json
|
||||
from datetime import datetime, timedelta
|
||||
from io import BytesIO
|
||||
from typing import Optional
|
||||
from unittest.mock import MagicMock, Mock, patch
|
||||
|
||||
import pytest
|
||||
@ -233,7 +234,16 @@ class TestUserRegistration(ApiTestCaseMixin):
|
||||
assert data['status'] == 'success'
|
||||
assert 'auth_token' not in data
|
||||
|
||||
def test_it_creates_user_with_inactive_account(self, app: Flask) -> None:
|
||||
@pytest.mark.parametrize(
|
||||
'input_language,expected_language',
|
||||
[('en', 'en'), ('fr', 'fr'), ('invalid', 'en'), (None, 'en')],
|
||||
)
|
||||
def test_it_creates_user_with_inactive_account(
|
||||
self,
|
||||
app: Flask,
|
||||
input_language: Optional[str],
|
||||
expected_language: str,
|
||||
) -> None:
|
||||
client = app.test_client()
|
||||
username = self.random_string()
|
||||
email = self.random_email()
|
||||
@ -245,6 +255,7 @@ class TestUserRegistration(ApiTestCaseMixin):
|
||||
username=username,
|
||||
email=email,
|
||||
password=self.random_string(),
|
||||
language=input_language,
|
||||
)
|
||||
),
|
||||
content_type='application/json',
|
||||
@ -254,9 +265,18 @@ class TestUserRegistration(ApiTestCaseMixin):
|
||||
assert new_user.email == email
|
||||
assert new_user.password is not None
|
||||
assert new_user.is_active is False
|
||||
assert new_user.language == expected_language
|
||||
|
||||
def test_it_calls_account_confirmation_email_if_payload_is_valid(
|
||||
self, app: Flask, account_confirmation_email_mock: Mock
|
||||
@pytest.mark.parametrize(
|
||||
'input_language,expected_language',
|
||||
[('en', 'en'), ('fr', 'fr'), ('invalid', 'en'), (None, 'en')],
|
||||
)
|
||||
def test_it_calls_account_confirmation_email_when_payload_is_valid(
|
||||
self,
|
||||
app: Flask,
|
||||
account_confirmation_email_mock: Mock,
|
||||
input_language: Optional[str],
|
||||
expected_language: str,
|
||||
) -> None:
|
||||
client = app.test_client()
|
||||
email = self.random_email()
|
||||
@ -271,6 +291,7 @@ class TestUserRegistration(ApiTestCaseMixin):
|
||||
username=username,
|
||||
email=email,
|
||||
password='12345678',
|
||||
language=input_language,
|
||||
)
|
||||
),
|
||||
content_type='application/json',
|
||||
@ -279,7 +300,7 @@ class TestUserRegistration(ApiTestCaseMixin):
|
||||
|
||||
account_confirmation_email_mock.send.assert_called_once_with(
|
||||
{
|
||||
'language': 'en',
|
||||
'language': expected_language,
|
||||
'email': email,
|
||||
},
|
||||
{
|
||||
@ -1227,8 +1248,16 @@ class TestUserPreferencesUpdate(ApiTestCaseMixin):
|
||||
|
||||
self.assert_400(response)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
'input_language,expected_language',
|
||||
[('en', 'en'), ('fr', 'fr'), ('invalid', 'en'), (None, 'en')],
|
||||
)
|
||||
def test_it_updates_user_preferences(
|
||||
self, app: Flask, user_1: User
|
||||
self,
|
||||
app: Flask,
|
||||
user_1: User,
|
||||
input_language: Optional[str],
|
||||
expected_language: str,
|
||||
) -> None:
|
||||
client, auth_token = self.get_test_client_and_auth_token(
|
||||
app, user_1.email
|
||||
@ -1241,7 +1270,7 @@ class TestUserPreferencesUpdate(ApiTestCaseMixin):
|
||||
dict(
|
||||
timezone='America/New_York',
|
||||
weekm=True,
|
||||
language='fr',
|
||||
language=input_language,
|
||||
imperial_units=True,
|
||||
)
|
||||
),
|
||||
@ -1252,6 +1281,7 @@ class TestUserPreferencesUpdate(ApiTestCaseMixin):
|
||||
data = json.loads(response.data.decode())
|
||||
assert data['status'] == 'success'
|
||||
assert data['message'] == 'user preferences updated'
|
||||
assert data['data']['language'] == expected_language
|
||||
assert data['data'] == jsonify_dict(user_1.serialize(user_1))
|
||||
|
||||
|
||||
@ -2237,6 +2267,7 @@ class TestResendAccountConfirmationEmail(ApiTestCaseMixin):
|
||||
) -> None:
|
||||
client = app.test_client()
|
||||
expected_token = self.random_string()
|
||||
inactive_user.language = 'fr'
|
||||
|
||||
with patch('secrets.token_urlsafe', return_value=expected_token):
|
||||
client.post(
|
||||
@ -2248,7 +2279,7 @@ class TestResendAccountConfirmationEmail(ApiTestCaseMixin):
|
||||
|
||||
account_confirmation_email_mock.send.assert_called_once_with(
|
||||
{
|
||||
'language': 'en',
|
||||
'language': inactive_user.language,
|
||||
'email': inactive_user.email,
|
||||
},
|
||||
{
|
||||
|
@ -2,7 +2,7 @@ import datetime
|
||||
import os
|
||||
import re
|
||||
import secrets
|
||||
from typing import Dict, Tuple, Union
|
||||
from typing import Dict, Optional, Tuple, Union
|
||||
|
||||
import jwt
|
||||
from flask import Blueprint, current_app, request
|
||||
@ -43,6 +43,13 @@ HEX_COLOR_REGEX = regex = "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$"
|
||||
NOT_FOUND_MESSAGE = 'the requested URL was not found on the server'
|
||||
|
||||
|
||||
def get_language(language: Optional[str]) -> str:
|
||||
# Note: some users may not have language preferences set
|
||||
if not language or language not in current_app.config['LANGUAGES']:
|
||||
language = 'en'
|
||||
return language
|
||||
|
||||
|
||||
def send_account_confirmation_email(user: User) -> None:
|
||||
if current_app.config['CAN_SEND_EMAILS']:
|
||||
ui_url = current_app.config['UI_URL']
|
||||
@ -57,7 +64,7 @@ def send_account_confirmation_email(user: User) -> None:
|
||||
),
|
||||
}
|
||||
user_data = {
|
||||
'language': 'en',
|
||||
'language': get_language(user.language),
|
||||
'email': user.email,
|
||||
}
|
||||
account_confirmation_email.send(user_data, email_data)
|
||||
@ -106,6 +113,8 @@ def register_user() -> Union[Tuple[Dict, int], HttpResponse]:
|
||||
:<json string username: username (3 to 30 characters required)
|
||||
:<json string email: user email
|
||||
:<json string password: password (8 characters required)
|
||||
:<json string lang: user language preferences (if not provided or invalid,
|
||||
fallback to 'en' (english))
|
||||
|
||||
:statuscode 200: success
|
||||
:statuscode 400:
|
||||
@ -138,6 +147,7 @@ def register_user() -> Union[Tuple[Dict, int], HttpResponse]:
|
||||
username = post_data.get('username')
|
||||
email = post_data.get('email')
|
||||
password = post_data.get('password')
|
||||
language = get_language(post_data.get('language'))
|
||||
|
||||
try:
|
||||
ret = register_controls(username, email, password)
|
||||
@ -165,6 +175,7 @@ def register_user() -> Union[Tuple[Dict, int], HttpResponse]:
|
||||
new_user = User(username=username, email=email, password=password)
|
||||
new_user.timezone = 'Europe/Paris'
|
||||
new_user.confirmation_token = secrets.token_urlsafe(30)
|
||||
new_user.language = language
|
||||
db.session.add(new_user)
|
||||
db.session.commit()
|
||||
|
||||
@ -661,9 +672,7 @@ def update_user_account(auth_user: User) -> Union[Dict, HttpResponse]:
|
||||
if current_app.config['CAN_SEND_EMAILS']:
|
||||
ui_url = current_app.config['UI_URL']
|
||||
user_data = {
|
||||
'language': (
|
||||
'en' if auth_user.language is None else auth_user.language
|
||||
),
|
||||
'language': get_language(auth_user.language),
|
||||
'email': auth_user.email,
|
||||
}
|
||||
data = {
|
||||
@ -830,7 +839,7 @@ def edit_user_preferences(auth_user: User) -> Union[Dict, HttpResponse]:
|
||||
return InvalidPayloadErrorResponse()
|
||||
|
||||
imperial_units = post_data.get('imperial_units')
|
||||
language = post_data.get('language')
|
||||
language = get_language(post_data.get('language'))
|
||||
timezone = post_data.get('timezone')
|
||||
weekm = post_data.get('weekm')
|
||||
|
||||
@ -1189,7 +1198,7 @@ def request_password_reset() -> Union[Dict, HttpResponse]:
|
||||
if user:
|
||||
password_reset_token = user.encode_password_reset_token(user.id)
|
||||
ui_url = current_app.config['UI_URL']
|
||||
user_language = 'en' if user.language is None else user.language
|
||||
user_language = get_language(user.language)
|
||||
email_data = {
|
||||
'expiration_delay': get_readable_duration(
|
||||
current_app.config['PASSWORD_TOKEN_EXPIRATION_SECONDS'],
|
||||
@ -1280,9 +1289,7 @@ def update_password() -> Union[Dict, HttpResponse]:
|
||||
if current_app.config['CAN_SEND_EMAILS']:
|
||||
password_change_email.send(
|
||||
{
|
||||
'language': (
|
||||
'en' if user.language is None else user.language
|
||||
),
|
||||
'language': get_language(user.language),
|
||||
'email': user.email,
|
||||
},
|
||||
{
|
||||
|
@ -23,6 +23,7 @@ from fittrackee.responses import (
|
||||
from fittrackee.utils import get_readable_duration
|
||||
from fittrackee.workouts.models import Record, Workout, WorkoutSegment
|
||||
|
||||
from .auth import get_language
|
||||
from .decorators import authenticate, authenticate_as_admin
|
||||
from .exceptions import InvalidEmailException, UserNotFoundException
|
||||
from .models import User, UserSportPreference
|
||||
@ -530,7 +531,7 @@ def update_user(auth_user: User, user_name: str) -> Union[Dict, HttpResponse]:
|
||||
)
|
||||
|
||||
if current_app.config['CAN_SEND_EMAILS']:
|
||||
user_language = 'en' if user.language is None else user.language
|
||||
user_language = get_language(user.language)
|
||||
ui_url = current_app.config['UI_URL']
|
||||
if reset_password:
|
||||
user_data = {
|
||||
|
Loading…
Reference in New Issue
Block a user