From 8d8ca3312aef4ab065f93c3cc2f328e8ecee24c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Casaj=C3=BAs?= Date: Wed, 5 Feb 2025 10:44:42 +0100 Subject: [PATCH] Send event on account unlink (#2379) * Send event on account unlink * Move unlink to its own module --- app/api/views/setting.py | 2 +- app/api/views/user_info.py | 2 +- app/auth/views/proton.py | 2 +- app/dashboard/views/account_setting.py | 2 +- app/dashboard/views/enter_sudo.py | 2 +- app/dashboard/views/pricing.py | 2 +- app/dashboard/views/setting.py | 3 +- app/events/event_dispatcher.py | 2 +- app/events/generated/event_pb2.py | 12 ++++---- app/events/generated/event_pb2.pyi | 10 +++++-- app/fake_data.py | 2 +- app/jobs/send_event_job.py | 2 +- app/proton/proton_partner.py | 23 ++++++++++++++++ app/proton/{utils.py => proton_unlink.py} | 29 +++++--------------- cron.py | 2 +- init_app.py | 2 +- proto/event.proto | 4 +++ tests/api/test_user_info.py | 2 +- tests/cron/test_get_alias_for_hibp.py | 2 +- tests/events/event_test_utils.py | 2 +- tests/jobs/test_send_event_to_webhook.py | 2 +- tests/models/test_user.py | 2 +- tests/proton/test_account_linking.py | 2 +- tests/proton/test_proton_callback_handler.py | 2 +- tests/test_account_linking.py | 2 +- tests/test_alias_suffixes.py | 2 +- tests/test_coupon_utils.py | 2 +- tests/test_custom_domain_validation.py | 2 +- tests/test_domains.py | 2 +- tests/utils.py | 2 +- 30 files changed, 75 insertions(+), 54 deletions(-) create mode 100644 app/proton/proton_partner.py rename app/proton/{utils.py => proton_unlink.py} (64%) diff --git a/app/api/views/setting.py b/app/api/views/setting.py index f58c7fbd..bf8c1b69 100644 --- a/app/api/views/setting.py +++ b/app/api/views/setting.py @@ -12,7 +12,7 @@ from app.models import ( SenderFormatEnum, AliasSuffixEnum, ) -from app.proton.utils import perform_proton_account_unlink +from app.proton.proton_unlink import perform_proton_account_unlink def setting_to_dict(user: User): diff --git a/app/api/views/user_info.py b/app/api/views/user_info.py index e52e05a2..97371e11 100644 --- a/app/api/views/user_info.py +++ b/app/api/views/user_info.py @@ -12,7 +12,7 @@ from app.dashboard.views.index import get_stats from app.db import Session from app.image_validation import detect_image_format, ImageFormat from app.models import ApiKey, File, PartnerUser, User -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from app.session import logout_session from app.utils import random_string diff --git a/app/auth/views/proton.py b/app/auth/views/proton.py index 8de77763..52e2fb3d 100644 --- a/app/auth/views/proton.py +++ b/app/auth/views/proton.py @@ -23,7 +23,7 @@ from app.proton.proton_callback_handler import ( ProtonCallbackHandler, Action, ) -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from app.utils import sanitize_next_url, sanitize_scheme _authorization_base_url = PROTON_BASE_URL + "/oauth/authorize" diff --git a/app/dashboard/views/account_setting.py b/app/dashboard/views/account_setting.py index efd16496..ee46103a 100644 --- a/app/dashboard/views/account_setting.py +++ b/app/dashboard/views/account_setting.py @@ -39,7 +39,7 @@ from app.models import ( SenderFormatEnum, UnsubscribeBehaviourEnum, ) -from app.proton.utils import perform_proton_account_unlink +from app.proton.proton_unlink import perform_proton_account_unlink from app.utils import ( random_string, CSRFValidationForm, diff --git a/app/dashboard/views/enter_sudo.py b/app/dashboard/views/enter_sudo.py index 8f6b80ab..18115d67 100644 --- a/app/dashboard/views/enter_sudo.py +++ b/app/dashboard/views/enter_sudo.py @@ -11,7 +11,7 @@ from app.dashboard.base import dashboard_bp from app.extensions import limiter from app.log import LOG from app.models import PartnerUser, SocialAuth -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from app.utils import sanitize_next_url _SUDO_GAP = 120 diff --git a/app/dashboard/views/pricing.py b/app/dashboard/views/pricing.py index f9cf4a0c..6e36056e 100644 --- a/app/dashboard/views/pricing.py +++ b/app/dashboard/views/pricing.py @@ -22,7 +22,7 @@ from app.models import ( PartnerUser, PartnerSubscription, ) -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner @dashboard_bp.route("/pricing", methods=["GET", "POST"]) diff --git a/app/dashboard/views/setting.py b/app/dashboard/views/setting.py index c912dc47..6fcec6f2 100644 --- a/app/dashboard/views/setting.py +++ b/app/dashboard/views/setting.py @@ -41,7 +41,8 @@ from app.models import ( PartnerSubscription, UnsubscribeBehaviourEnum, ) -from app.proton.utils import get_proton_partner, can_unlink_proton_account +from app.proton.proton_partner import get_proton_partner +from app.proton.proton_unlink import can_unlink_proton_account from app.utils import ( random_string, CSRFValidationForm, diff --git a/app/events/event_dispatcher.py b/app/events/event_dispatcher.py index 2cf29b7e..586e6f7c 100644 --- a/app/events/event_dispatcher.py +++ b/app/events/event_dispatcher.py @@ -8,7 +8,7 @@ from app.errors import ProtonPartnerNotSetUp from app.events.generated import event_pb2 from app.log import LOG from app.models import User, PartnerUser, SyncEvent -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from typing import Optional NOTIFICATION_CHANNEL = "simplelogin_sync_events" diff --git a/app/events/generated/event_pb2.py b/app/events/generated/event_pb2.py index f56beb69..babfc8d2 100644 --- a/app/events/generated/event_pb2.py +++ b/app/events/generated/event_pb2.py @@ -24,7 +24,7 @@ _sym_db = _symbol_database.Default() -DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0b\x65vent.proto\x12\x12simplelogin_events\":\n\x0fUserPlanChanged\x12\x15\n\rplan_end_time\x18\x01 \x01(\r\x12\x10\n\x08lifetime\x18\x02 \x01(\x08\"\r\n\x0bUserDeleted\"\\\n\x0c\x41liasCreated\x12\n\n\x02id\x18\x01 \x01(\r\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x0c\n\x04note\x18\x03 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x04 \x01(\x08\x12\x12\n\ncreated_at\x18\x05 \x01(\r\"T\n\x12\x41liasStatusChanged\x12\n\n\x02id\x18\x01 \x01(\r\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08\x12\x12\n\ncreated_at\x18\x04 \x01(\r\")\n\x0c\x41liasDeleted\x12\n\n\x02id\x18\x01 \x01(\r\x12\r\n\x05\x65mail\x18\x02 \x01(\t\"D\n\x10\x41liasCreatedList\x12\x30\n\x06\x65vents\x18\x01 \x03(\x0b\x32 .simplelogin_events.AliasCreated\"\x93\x03\n\x0c\x45ventContent\x12?\n\x10user_plan_change\x18\x01 \x01(\x0b\x32#.simplelogin_events.UserPlanChangedH\x00\x12\x37\n\x0cuser_deleted\x18\x02 \x01(\x0b\x32\x1f.simplelogin_events.UserDeletedH\x00\x12\x39\n\ralias_created\x18\x03 \x01(\x0b\x32 .simplelogin_events.AliasCreatedH\x00\x12\x45\n\x13\x61lias_status_change\x18\x04 \x01(\x0b\x32&.simplelogin_events.AliasStatusChangedH\x00\x12\x39\n\ralias_deleted\x18\x05 \x01(\x0b\x32 .simplelogin_events.AliasDeletedH\x00\x12\x41\n\x11\x61lias_create_list\x18\x06 \x01(\x0b\x32$.simplelogin_events.AliasCreatedListH\x00\x42\t\n\x07\x63ontent\"y\n\x05\x45vent\x12\x0f\n\x07user_id\x18\x01 \x01(\r\x12\x18\n\x10\x65xternal_user_id\x18\x02 \x01(\t\x12\x12\n\npartner_id\x18\x03 \x01(\r\x12\x31\n\x07\x63ontent\x18\x04 \x01(\x0b\x32 .simplelogin_events.EventContentb\x06proto3') +DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0b\x65vent.proto\x12\x12simplelogin_events\":\n\x0fUserPlanChanged\x12\x15\n\rplan_end_time\x18\x01 \x01(\r\x12\x10\n\x08lifetime\x18\x02 \x01(\x08\"\r\n\x0bUserDeleted\"\\\n\x0c\x41liasCreated\x12\n\n\x02id\x18\x01 \x01(\r\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x0c\n\x04note\x18\x03 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x04 \x01(\x08\x12\x12\n\ncreated_at\x18\x05 \x01(\r\"T\n\x12\x41liasStatusChanged\x12\n\n\x02id\x18\x01 \x01(\r\x12\r\n\x05\x65mail\x18\x02 \x01(\t\x12\x0f\n\x07\x65nabled\x18\x03 \x01(\x08\x12\x12\n\ncreated_at\x18\x04 \x01(\r\")\n\x0c\x41liasDeleted\x12\n\n\x02id\x18\x01 \x01(\r\x12\r\n\x05\x65mail\x18\x02 \x01(\t\"D\n\x10\x41liasCreatedList\x12\x30\n\x06\x65vents\x18\x01 \x03(\x0b\x32 .simplelogin_events.AliasCreated\"\x0e\n\x0cUserUnlinked\"\xce\x03\n\x0c\x45ventContent\x12?\n\x10user_plan_change\x18\x01 \x01(\x0b\x32#.simplelogin_events.UserPlanChangedH\x00\x12\x37\n\x0cuser_deleted\x18\x02 \x01(\x0b\x32\x1f.simplelogin_events.UserDeletedH\x00\x12\x39\n\ralias_created\x18\x03 \x01(\x0b\x32 .simplelogin_events.AliasCreatedH\x00\x12\x45\n\x13\x61lias_status_change\x18\x04 \x01(\x0b\x32&.simplelogin_events.AliasStatusChangedH\x00\x12\x39\n\ralias_deleted\x18\x05 \x01(\x0b\x32 .simplelogin_events.AliasDeletedH\x00\x12\x41\n\x11\x61lias_create_list\x18\x06 \x01(\x0b\x32$.simplelogin_events.AliasCreatedListH\x00\x12\x39\n\ruser_unlinked\x18\x07 \x01(\x0b\x32 .simplelogin_events.UserUnlinkedH\x00\x42\t\n\x07\x63ontent\"y\n\x05\x45vent\x12\x0f\n\x07user_id\x18\x01 \x01(\r\x12\x18\n\x10\x65xternal_user_id\x18\x02 \x01(\t\x12\x12\n\npartner_id\x18\x03 \x01(\r\x12\x31\n\x07\x63ontent\x18\x04 \x01(\x0b\x32 .simplelogin_events.EventContentb\x06proto3') _globals = globals() _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) @@ -43,8 +43,10 @@ if not _descriptor._USE_C_DESCRIPTORS: _globals['_ALIASDELETED']._serialized_end=331 _globals['_ALIASCREATEDLIST']._serialized_start=333 _globals['_ALIASCREATEDLIST']._serialized_end=401 - _globals['_EVENTCONTENT']._serialized_start=404 - _globals['_EVENTCONTENT']._serialized_end=807 - _globals['_EVENT']._serialized_start=809 - _globals['_EVENT']._serialized_end=930 + _globals['_USERUNLINKED']._serialized_start=403 + _globals['_USERUNLINKED']._serialized_end=417 + _globals['_EVENTCONTENT']._serialized_start=420 + _globals['_EVENTCONTENT']._serialized_end=882 + _globals['_EVENT']._serialized_start=884 + _globals['_EVENT']._serialized_end=1005 # @@protoc_insertion_point(module_scope) diff --git a/app/events/generated/event_pb2.pyi b/app/events/generated/event_pb2.pyi index 58914b1a..83369fcc 100644 --- a/app/events/generated/event_pb2.pyi +++ b/app/events/generated/event_pb2.pyi @@ -57,21 +57,27 @@ class AliasCreatedList(_message.Message): events: _containers.RepeatedCompositeFieldContainer[AliasCreated] def __init__(self, events: _Optional[_Iterable[_Union[AliasCreated, _Mapping]]] = ...) -> None: ... +class UserUnlinked(_message.Message): + __slots__ = () + def __init__(self) -> None: ... + class EventContent(_message.Message): - __slots__ = ("user_plan_change", "user_deleted", "alias_created", "alias_status_change", "alias_deleted", "alias_create_list") + __slots__ = ("user_plan_change", "user_deleted", "alias_created", "alias_status_change", "alias_deleted", "alias_create_list", "user_unlinked") USER_PLAN_CHANGE_FIELD_NUMBER: _ClassVar[int] USER_DELETED_FIELD_NUMBER: _ClassVar[int] ALIAS_CREATED_FIELD_NUMBER: _ClassVar[int] ALIAS_STATUS_CHANGE_FIELD_NUMBER: _ClassVar[int] ALIAS_DELETED_FIELD_NUMBER: _ClassVar[int] ALIAS_CREATE_LIST_FIELD_NUMBER: _ClassVar[int] + USER_UNLINKED_FIELD_NUMBER: _ClassVar[int] user_plan_change: UserPlanChanged user_deleted: UserDeleted alias_created: AliasCreated alias_status_change: AliasStatusChanged alias_deleted: AliasDeleted alias_create_list: AliasCreatedList - def __init__(self, user_plan_change: _Optional[_Union[UserPlanChanged, _Mapping]] = ..., user_deleted: _Optional[_Union[UserDeleted, _Mapping]] = ..., alias_created: _Optional[_Union[AliasCreated, _Mapping]] = ..., alias_status_change: _Optional[_Union[AliasStatusChanged, _Mapping]] = ..., alias_deleted: _Optional[_Union[AliasDeleted, _Mapping]] = ..., alias_create_list: _Optional[_Union[AliasCreatedList, _Mapping]] = ...) -> None: ... + user_unlinked: UserUnlinked + def __init__(self, user_plan_change: _Optional[_Union[UserPlanChanged, _Mapping]] = ..., user_deleted: _Optional[_Union[UserDeleted, _Mapping]] = ..., alias_created: _Optional[_Union[AliasCreated, _Mapping]] = ..., alias_status_change: _Optional[_Union[AliasStatusChanged, _Mapping]] = ..., alias_deleted: _Optional[_Union[AliasDeleted, _Mapping]] = ..., alias_create_list: _Optional[_Union[AliasCreatedList, _Mapping]] = ..., user_unlinked: _Optional[_Union[UserUnlinked, _Mapping]] = ...) -> None: ... class Event(_message.Message): __slots__ = ("user_id", "external_user_id", "partner_id", "content") diff --git a/app/fake_data.py b/app/fake_data.py index 78c50502..6f43db75 100644 --- a/app/fake_data.py +++ b/app/fake_data.py @@ -37,7 +37,7 @@ from app.models import ( PartnerSubscription, ) from app.pgp_utils import load_public_key -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner def fake_data(): diff --git a/app/jobs/send_event_job.py b/app/jobs/send_event_job.py index 3f5ca616..32dd7d38 100644 --- a/app/jobs/send_event_job.py +++ b/app/jobs/send_event_job.py @@ -14,7 +14,7 @@ from app.models import ( Job, PartnerUser, ) -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from events.event_sink import EventSink diff --git a/app/proton/proton_partner.py b/app/proton/proton_partner.py new file mode 100644 index 00000000..7b02e832 --- /dev/null +++ b/app/proton/proton_partner.py @@ -0,0 +1,23 @@ +from typing import Optional + +from app.db import Session +from app.errors import ProtonPartnerNotSetUp +from app.models import Partner + +PROTON_PARTNER_NAME = "Proton" +_PROTON_PARTNER: Optional[Partner] = None + + +def get_proton_partner() -> Partner: + global _PROTON_PARTNER + if _PROTON_PARTNER is None: + partner = Partner.get_by(name=PROTON_PARTNER_NAME) + if partner is None: + raise ProtonPartnerNotSetUp + Session.expunge(partner) + _PROTON_PARTNER = partner + return _PROTON_PARTNER + + +def is_proton_partner(partner: Partner) -> bool: + return partner.name == PROTON_PARTNER_NAME diff --git a/app/proton/utils.py b/app/proton/proton_unlink.py similarity index 64% rename from app/proton/utils.py rename to app/proton/proton_unlink.py index 0bd4ff37..69f5cb97 100644 --- a/app/proton/utils.py +++ b/app/proton/proton_unlink.py @@ -1,31 +1,13 @@ -from typing import Optional - from newrelic import agent from app.db import Session -from app.errors import ProtonPartnerNotSetUp +from app.events.event_dispatcher import EventDispatcher +from app.events.generated.event_pb2 import EventContent, UserUnlinked from app.log import LOG -from app.models import Partner, PartnerUser, User +from app.models import User, PartnerUser +from app.proton.proton_partner import get_proton_partner from app.user_audit_log_utils import emit_user_audit_log, UserAuditLogAction -PROTON_PARTNER_NAME = "Proton" -_PROTON_PARTNER: Optional[Partner] = None - - -def get_proton_partner() -> Partner: - global _PROTON_PARTNER - if _PROTON_PARTNER is None: - partner = Partner.get_by(name=PROTON_PARTNER_NAME) - if partner is None: - raise ProtonPartnerNotSetUp - Session.expunge(partner) - _PROTON_PARTNER = partner - return _PROTON_PARTNER - - -def is_proton_partner(partner: Partner) -> bool: - return partner.name == PROTON_PARTNER_NAME - def can_unlink_proton_account(user: User) -> bool: return (user.flags & User.FLAG_CREATED_FROM_PARTNER) == 0 @@ -45,6 +27,9 @@ def perform_proton_account_unlink(current_user: User) -> bool: action=UserAuditLogAction.UnlinkAccount, message=f"User has unlinked the account (email={partner_user.partner_email} | external_user_id={partner_user.external_user_id})", ) + EventDispatcher.send_event( + partner_user.user, EventContent(user_unlinked=UserUnlinked()) + ) PartnerUser.delete(partner_user.id) Session.commit() agent.record_custom_event("AccountUnlinked", {"partner": proton_partner.name}) diff --git a/cron.py b/cron.py index 76513f92..e22d46ef 100644 --- a/cron.py +++ b/cron.py @@ -59,7 +59,7 @@ from app.models import ( ApiToCookieToken, ) from app.pgp_utils import load_public_key_and_check, PGPException -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from app.user_audit_log_utils import emit_user_audit_log, UserAuditLogAction from app.utils import sanitize_email from server import create_light_app diff --git a/init_app.py b/init_app.py index ced9087a..3e3333cd 100644 --- a/init_app.py +++ b/init_app.py @@ -6,7 +6,7 @@ from app.db import Session from app.log import LOG from app.models import Mailbox, Contact, SLDomain, Partner from app.pgp_utils import load_public_key -from app.proton.utils import PROTON_PARTNER_NAME +from app.proton.proton_partner import PROTON_PARTNER_NAME from server import create_light_app diff --git a/proto/event.proto b/proto/event.proto index 89621f80..1d29ab47 100644 --- a/proto/event.proto +++ b/proto/event.proto @@ -34,6 +34,9 @@ message AliasCreatedList { repeated AliasCreated events = 1; } +message UserUnlinked { +} + message EventContent { oneof content { UserPlanChanged user_plan_change = 1; @@ -42,6 +45,7 @@ message EventContent { AliasStatusChanged alias_status_change = 4; AliasDeleted alias_deleted = 5; AliasCreatedList alias_create_list = 6; + UserUnlinked user_unlinked = 7; } } diff --git a/tests/api/test_user_info.py b/tests/api/test_user_info.py index dd539d82..b260df88 100644 --- a/tests/api/test_user_info.py +++ b/tests/api/test_user_info.py @@ -3,7 +3,7 @@ from flask import url_for from app import config from app.db import Session from app.models import User, PartnerUser -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from tests.api.utils import get_new_user_and_api_key from tests.utils import login, random_token, random_email diff --git a/tests/cron/test_get_alias_for_hibp.py b/tests/cron/test_get_alias_for_hibp.py index 370c6ff8..9f645f30 100644 --- a/tests/cron/test_get_alias_for_hibp.py +++ b/tests/cron/test_get_alias_for_hibp.py @@ -14,7 +14,7 @@ from app.models import ( PartnerSubscription, User, ) -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from tests.utils import create_new_user, random_token diff --git a/tests/events/event_test_utils.py b/tests/events/event_test_utils.py index d7b6e969..1979ff04 100644 --- a/tests/events/event_test_utils.py +++ b/tests/events/event_test_utils.py @@ -1,7 +1,7 @@ from app.events.event_dispatcher import Dispatcher from app.events.generated import event_pb2 from app.models import PartnerUser, User -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from tests.utils import create_new_user, random_token from typing import Tuple diff --git a/tests/jobs/test_send_event_to_webhook.py b/tests/jobs/test_send_event_to_webhook.py index dacc4805..245240af 100644 --- a/tests/jobs/test_send_event_to_webhook.py +++ b/tests/jobs/test_send_event_to_webhook.py @@ -4,7 +4,7 @@ from app import config from app.events.generated.event_pb2 import EventContent, AliasDeleted from app.jobs.send_event_job import SendEventToWebhookJob from app.models import PartnerUser -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from events.event_sink import ConsoleEventSink from tests.utils import create_new_user, random_token diff --git a/tests/models/test_user.py b/tests/models/test_user.py index 211cb3f8..11c39eb3 100644 --- a/tests/models/test_user.py +++ b/tests/models/test_user.py @@ -2,7 +2,7 @@ import arrow from app import config from app.db import Session from app.models import User, Job, PartnerSubscription, PartnerUser, ManualSubscription -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from tests.utils import random_email, random_token diff --git a/tests/proton/test_account_linking.py b/tests/proton/test_account_linking.py index d2511c0c..8aa9c73f 100644 --- a/tests/proton/test_account_linking.py +++ b/tests/proton/test_account_linking.py @@ -7,7 +7,7 @@ from app.account_linking import ( ) from app.db import Session from app.models import User, PartnerUser, PartnerSubscription -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from app.utils import random_string from tests.utils import random_email diff --git a/tests/proton/test_proton_callback_handler.py b/tests/proton/test_proton_callback_handler.py index adf87119..00edd4cc 100644 --- a/tests/proton/test_proton_callback_handler.py +++ b/tests/proton/test_proton_callback_handler.py @@ -11,7 +11,7 @@ from app.proton.proton_callback_handler import ( generate_account_not_allowed_to_log_in, ) from app.models import User, PartnerUser, Job, JobState -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from app.utils import random_string from typing import Optional from tests.utils import random_email diff --git a/tests/test_account_linking.py b/tests/test_account_linking.py index a4524238..b38448f9 100644 --- a/tests/test_account_linking.py +++ b/tests/test_account_linking.py @@ -19,7 +19,7 @@ from app.account_linking import ( from app.db import Session from app.errors import AccountAlreadyLinkedToAnotherPartnerException from app.models import Partner, PartnerUser, User, UserAuditLog -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from app.user_audit_log_utils import UserAuditLogAction from app.utils import random_string, canonicalize_email from tests.utils import random_email diff --git a/tests/test_alias_suffixes.py b/tests/test_alias_suffixes.py index 870baa16..b1be2944 100644 --- a/tests/test_alias_suffixes.py +++ b/tests/test_alias_suffixes.py @@ -3,7 +3,7 @@ import re from app.alias_suffix import get_alias_suffixes from app.db import Session from app.models import SLDomain, PartnerUser, AliasOptions, CustomDomain -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from init_app import add_sl_domains from tests.utils import create_new_user, random_token diff --git a/tests/test_coupon_utils.py b/tests/test_coupon_utils.py index e9475912..743f4ef0 100644 --- a/tests/test_coupon_utils.py +++ b/tests/test_coupon_utils.py @@ -18,7 +18,7 @@ from app.models import ( PartnerSubscription, PartnerUser, ) -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from tests.utils import create_new_user, random_string, random_email diff --git a/tests/test_custom_domain_validation.py b/tests/test_custom_domain_validation.py index c417fe2a..fbeb54d8 100644 --- a/tests/test_custom_domain_validation.py +++ b/tests/test_custom_domain_validation.py @@ -6,7 +6,7 @@ from app.custom_domain_validation import CustomDomainValidation from app.db import Session from app.dns_utils import InMemoryDNSClient from app.models import CustomDomain, User -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from app.utils import random_string from tests.utils import create_new_user, random_domain diff --git a/tests/test_domains.py b/tests/test_domains.py index 5783aa03..58c28e35 100644 --- a/tests/test_domains.py +++ b/tests/test_domains.py @@ -1,6 +1,6 @@ from app.db import Session from app.models import SLDomain, PartnerUser, AliasOptions -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from init_app import add_sl_domains from tests.utils import create_new_user, random_token diff --git a/tests/utils.py b/tests/utils.py index 179cbb2e..b7798d01 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -10,7 +10,7 @@ import jinja2 from flask import url_for from app.models import User, PartnerUser -from app.proton.utils import get_proton_partner +from app.proton.proton_partner import get_proton_partner from app.utils import random_string