From 2cae0200a8b1c7327b7598020dbf00d5baa5721a Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Fri, 14 Aug 2020 12:02:33 +0200 Subject: [PATCH 1/5] use delete_alias(alias,user) instead of Alias.delete, DomainDeletedAlias.create, DeletedAlias.create --- app/alias_utils.py | 18 ++++++++++++------ app/models.py | 14 +++++++++++++- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/app/alias_utils.py b/app/alias_utils.py index e9506055..d3c00b8c 100644 --- a/app/alias_utils.py +++ b/app/alias_utils.py @@ -142,14 +142,17 @@ def try_auto_create_catch_all_domain(address: str) -> Optional[Alias]: def delete_alias(alias: Alias, user: User): - Alias.delete(alias.id) - db.session.commit() - + """ + Delete an alias and add it to either global or domain trash + Should be used instead of Alias.delete, DomainDeletedAlias.create, DeletedAlias.create + """ # save deleted alias to either global or domain trash if alias.custom_domain_id: try: - DomainDeletedAlias.create( - user_id=user.id, email=alias.email, domain_id=alias.custom_domain_id + db.session.add( + DomainDeletedAlias( + user_id=user.id, email=alias.email, domain_id=alias.custom_domain_id + ) ) db.session.commit() except IntegrityError: @@ -161,8 +164,11 @@ def delete_alias(alias: Alias, user: User): db.session.rollback() else: try: - DeletedAlias.create(email=alias.email) + db.session.add(DeletedAlias(email=alias.email)) db.session.commit() except IntegrityError: LOG.exception("alias %s has been added before to DeletedAlias", alias.email) db.session.rollback() + + Alias.query.filter(Alias.id == alias.id).delete() + db.session.commit() diff --git a/app/models.py b/app/models.py index ecd9c584..a7b4220f 100644 --- a/app/models.py +++ b/app/models.py @@ -13,7 +13,7 @@ from sqlalchemy import text, desc, CheckConstraint, and_, func from sqlalchemy.exc import IntegrityError from sqlalchemy_utils import ArrowType -from app import s3 +from app import s3, alias_utils from app.config import ( MAX_NB_EMAIL_FREE_PLAN, URL, @@ -870,6 +870,10 @@ class Alias(db.Model, ModelMixin): mailbox_id=mailbox_id or user.default_mailbox_id, ) + @classmethod + def delete(cls, obj_id): + raise Exception("should use delete_alias(alias,user) instead") + @classmethod def create_new_random( cls, @@ -1292,6 +1296,10 @@ class DeletedAlias(db.Model, ModelMixin): email = db.Column(db.String(256), unique=True, nullable=False) + @classmethod + def create(cls, **kw): + raise Exception("should use delete_alias(alias,user) instead") + def __repr__(self): return f"" @@ -1411,6 +1419,10 @@ class DomainDeletedAlias(db.Model, ModelMixin): ) user_id = db.Column(db.ForeignKey(User.id, ondelete="cascade"), nullable=False) + @classmethod + def create(cls, **kw): + raise Exception("should use delete_alias(alias,user) instead") + class LifetimeCoupon(db.Model, ModelMixin): code = db.Column(db.String(128), nullable=False, unique=True) From b4eb110971fc8e0d9386b805ee78c1863eaf3eaf Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Fri, 14 Aug 2020 12:02:54 +0200 Subject: [PATCH 2/5] fix Directory.create: use alias_utils.delete_alias --- app/models.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/app/models.py b/app/models.py index a7b4220f..2996534a 100644 --- a/app/models.py +++ b/app/models.py @@ -1451,15 +1451,11 @@ class Directory(db.Model, ModelMixin): @classmethod def delete(cls, obj_id): - # Put all aliases belonging to this directory to global trash - try: - for alias in Alias.query.filter_by(directory_id=obj_id): - DeletedAlias.create(email=alias.email) - db.session.commit() - # this can happen when a previously deleted alias is re-created via catch-all or directory feature - except IntegrityError: - LOG.exception("Some aliases have been added before to DeletedAlias") - db.session.rollback() + obj: Directory = cls.get(obj_id) + user = obj.user + # Put all aliases belonging to this directory to global or domain trash + for alias in Alias.query.filter_by(directory_id=obj_id): + alias_utils.delete_alias(alias, user) cls.query.filter(cls.id == obj_id).delete() db.session.commit() From 6bc0c5ada46edfddf56a5565a4baf3730948f16e Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Fri, 14 Aug 2020 12:03:41 +0200 Subject: [PATCH 3/5] fix Mailbox.delete: use alias_utils.delete_alias --- app/models.py | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/app/models.py b/app/models.py index 2996534a..f9053155 100644 --- a/app/models.py +++ b/app/models.py @@ -1509,23 +1509,21 @@ class Mailbox(db.Model, ModelMixin): @classmethod def delete(cls, obj_id): - # Put all aliases belonging to this mailbox to global trash - try: - for alias in Alias.query.filter_by(mailbox_id=obj_id): - # special handling for alias that has several mailboxes and has mailbox_id=obj_id - if len(alias.mailboxes) > 1: - # use the first mailbox found in alias._mailboxes - first_mb = alias._mailboxes[0] - alias.mailbox_id = first_mb.id - alias._mailboxes.remove(first_mb) - else: - # only put aliases that have mailbox as a single mailbox into trash - DeletedAlias.create(email=alias.email) - db.session.commit() - # this can happen when a previously deleted alias is re-created via catch-all or directory feature - except IntegrityError: - LOG.exception("Some aliases have been added before to DeletedAlias") - db.session.rollback() + mailbox: Mailbox = cls.get(obj_id) + user = mailbox.user + + # Put all aliases belonging to this mailbox to global or domain trash + for alias in Alias.query.filter_by(mailbox_id=obj_id): + # special handling for alias that has several mailboxes and has mailbox_id=obj_id + if len(alias.mailboxes) > 1: + # use the first mailbox found in alias._mailboxes + first_mb = alias._mailboxes[0] + alias.mailbox_id = first_mb.id + alias._mailboxes.remove(first_mb) + else: + # only put aliases that have mailbox as a single mailbox into trash + alias_utils.delete_alias(alias, user) + db.session.commit() cls.query.filter(cls.id == obj_id).delete() db.session.commit() From 5636b7ba32c84d0ff1a7cb1717664f684689a93c Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Fri, 14 Aug 2020 12:03:59 +0200 Subject: [PATCH 4/5] do not use DomainDeletedAlias.create --- server.py | 4 ---- shell.py | 12 +++++++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/server.py b/server.py index 63c57555..cc4254bd 100644 --- a/server.py +++ b/server.py @@ -275,10 +275,6 @@ def fake_data(): ClientUser.create(user_id=user.id, client_id=client1.id, name="Fake Name") - DeletedAlias.create(email="d1@ab.cd") - DeletedAlias.create(email="d2@ab.cd") - db.session.commit() - referral = Referral.create(user_id=user.id, code="REFCODE", name="First referral") db.session.commit() diff --git a/shell.py b/shell.py index 5072fbb5..a39291d2 100644 --- a/shell.py +++ b/shell.py @@ -106,11 +106,13 @@ def migrate_domain_trash(): domain = CustomDomain.get_by(domain=alias_domain) if domain: LOG.d("move %s to domain %s trash", deleted_alias, domain) - DomainDeletedAlias.create( - user_id=domain.user_id, - email=deleted_alias.email, - domain_id=domain.id, - created_at=deleted_alias.created_at, + db.session.add( + DomainDeletedAlias( + user_id=domain.user_id, + email=deleted_alias.email, + domain_id=domain.id, + created_at=deleted_alias.created_at, + ) ) DeletedAlias.delete(deleted_alias.id) From 89830e217355ab883f47fc15a623240870932012 Mon Sep 17 00:00:00 2001 From: Son NK <> Date: Fri, 14 Aug 2020 12:06:26 +0200 Subject: [PATCH 5/5] fix import --- app/models.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/models.py b/app/models.py index f9053155..8d1bda81 100644 --- a/app/models.py +++ b/app/models.py @@ -10,10 +10,9 @@ from arrow import Arrow from flask import url_for from flask_login import UserMixin from sqlalchemy import text, desc, CheckConstraint, and_, func -from sqlalchemy.exc import IntegrityError from sqlalchemy_utils import ArrowType -from app import s3, alias_utils +from app import s3 from app.config import ( MAX_NB_EMAIL_FREE_PLAN, URL, @@ -1455,6 +1454,8 @@ class Directory(db.Model, ModelMixin): user = obj.user # Put all aliases belonging to this directory to global or domain trash for alias in Alias.query.filter_by(directory_id=obj_id): + from app import alias_utils + alias_utils.delete_alias(alias, user) cls.query.filter(cls.id == obj_id).delete() @@ -1521,6 +1522,8 @@ class Mailbox(db.Model, ModelMixin): alias.mailbox_id = first_mb.id alias._mailboxes.remove(first_mb) else: + from app import alias_utils + # only put aliases that have mailbox as a single mailbox into trash alias_utils.delete_alias(alias, user) db.session.commit()