From 627ad302d241f0136b5939fc69e7d13b8e58494d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Casaj=C3=BAs?= Date: Wed, 8 Nov 2023 09:58:01 +0100 Subject: [PATCH] Creating account via partner also canonicalizes email (#1939) --- app/account_linking.py | 18 +++++++++++--- tests/test_account_linking.py | 47 ++++++++++++++++++++++++++++++++++- 2 files changed, 61 insertions(+), 4 deletions(-) diff --git a/app/account_linking.py b/app/account_linking.py index 61fcc9ac..ea0451de 100644 --- a/app/account_linking.py +++ b/app/account_linking.py @@ -5,10 +5,11 @@ from typing import Optional from arrow import Arrow from newrelic import agent +from sqlalchemy import or_ from app.db import Session from app.email_utils import send_welcome_email -from app.utils import sanitize_email +from app.utils import sanitize_email, canonicalize_email from app.errors import ( AccountAlreadyLinkedToAnotherPartnerException, AccountIsUsingAliasAsEmail, @@ -131,8 +132,9 @@ class ClientMergeStrategy(ABC): class NewUserStrategy(ClientMergeStrategy): def process(self) -> LinkResult: # Will create a new SL User with a random password + canonical_email = canonicalize_email(self.link_request.email) new_user = User.create( - email=self.link_request.email, + email=canonical_email, name=self.link_request.name, password=random_string(20), activated=True, @@ -213,11 +215,21 @@ def process_login_case( partner_id=partner.id, external_user_id=link_request.external_user_id ) if partner_user is None: + canonical_email = canonicalize_email(link_request.email) # We didn't find any SimpleLogin user registered with that partner user id # Make sure they aren't using an alias as their link email check_alias(link_request.email) + check_alias(canonical_email) # Try to find it using the partner's e-mail address - user = User.get_by(email=link_request.email) + users = User.filter( + or_(User.email == link_request.email, User.email == canonical_email) + ).all() + if len(users) > 1: + user = [user for user in users if user.email == canonical_email][0] + elif len(users) == 1: + user = users[0] + else: + user = None return get_login_strategy(link_request, user, partner).process() else: # We found the SL user registered with that partner user id diff --git a/tests/test_account_linking.py b/tests/test_account_linking.py index 0825dafd..1ef7222e 100644 --- a/tests/test_account_linking.py +++ b/tests/test_account_linking.py @@ -18,7 +18,7 @@ from app.db import Session from app.errors import AccountAlreadyLinkedToAnotherPartnerException from app.models import Partner, PartnerUser, User from app.proton.utils import get_proton_partner -from app.utils import random_string +from app.utils import random_string, canonicalize_email from tests.utils import random_email @@ -377,3 +377,48 @@ def test_link_account_with_uppercase(flask_client): ) assert partner_user.partner_id == get_proton_partner().id assert partner_user.external_user_id == partner_user_id + + +def test_login_to_account_with_canonical_email(flask_client): + email = "a.{rand}@gmail.com".format(rand=random_string(10)) + canonical_email = canonicalize_email(email) + assert email != canonical_email + partner_user_id = random_string() + link_request = random_link_request( + external_user_id=partner_user_id, email=email.upper() + ) + user = create_user(canonical_email) + assert user.email == canonical_email + res = process_login_case(link_request, get_proton_partner()) + assert res.user.id == user.id + + +def test_login_to_account_with_canonical_email_if_there_is_also_non_canonical( + flask_client, +): + email = "a.{rand}@gmail.com".format(rand=random_string(10)) + canonical_email = canonicalize_email(email) + assert email != canonical_email + partner_user_id = random_string() + link_request = random_link_request( + external_user_id=partner_user_id, email=email.upper() + ) + user = create_user(canonical_email) + create_user(email) + assert user.email == canonical_email + res = process_login_case(link_request, get_proton_partner()) + assert res.user.id == user.id + + +def test_login_creates_account_with_canonical_email( + flask_client, +): + email = "a.{rand}@gmail.com".format(rand=random_string(10)) + canonical_email = canonicalize_email(email) + assert email != canonical_email + partner_user_id = random_string() + link_request = random_link_request( + external_user_id=partner_user_id, email=email.upper() + ) + res = process_login_case(link_request, get_proton_partner()) + assert res.user.email == canonical_email