Skip to content

Commit

Permalink
chore: QOL improvements on alias delete due to cascade FKs (#2144)
Browse files Browse the repository at this point in the history
  • Loading branch information
cquintana92 authored Jul 8, 2024
1 parent 2d841e9 commit f05f01b
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 7 deletions.
8 changes: 6 additions & 2 deletions app/alias_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
from app.log import LOG
from app.models import (
Alias,
AliasDeleteReason,
CustomDomain,
Directory,
User,
Expand Down Expand Up @@ -309,7 +310,9 @@ def try_auto_create_via_domain(address: str) -> Optional[Alias]:
return None


def delete_alias(alias: Alias, user: User):
def delete_alias(
alias: Alias, user: User, reason: AliasDeleteReason = AliasDeleteReason.Unspecified
):
"""
Delete an alias and add it to either global or domain trash
Should be used instead of Alias.delete, DomainDeletedAlias.create, DeletedAlias.create
Expand All @@ -324,6 +327,7 @@ def delete_alias(alias: Alias, user: User):
user_id=user.id,
email=alias.email,
domain_id=alias.custom_domain_id,
reason=reason,
)
Session.add(domain_deleted_alias)
Session.commit()
Expand All @@ -332,7 +336,7 @@ def delete_alias(alias: Alias, user: User):
)
else:
if not DeletedAlias.get_by(email=alias.email):
deleted_alias = DeletedAlias(email=alias.email)
deleted_alias = DeletedAlias(email=alias.email, reason=reason)
Session.add(deleted_alias)
Session.commit()
LOG.i(f"Moving {alias} to global trash {deleted_alias}")
Expand Down
4 changes: 2 additions & 2 deletions app/api/views/alias.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
)
from app.extensions import limiter
from app.log import LOG
from app.models import Alias, Contact, Mailbox, AliasMailbox
from app.models import Alias, Contact, Mailbox, AliasMailbox, AliasDeleteReason


@deprecated
Expand Down Expand Up @@ -161,7 +161,7 @@ def delete_alias(alias_id):
if not alias or alias.user_id != user.id:
return jsonify(error="Forbidden"), 403

alias_utils.delete_alias(alias, user)
alias_utils.delete_alias(alias, user, AliasDeleteReason.ManualAction)

return jsonify(deleted=True), 200

Expand Down
5 changes: 4 additions & 1 deletion app/dashboard/views/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from app.log import LOG
from app.models import (
Alias,
AliasDeleteReason,
AliasGeneratorEnum,
User,
EmailLog,
Expand Down Expand Up @@ -143,7 +144,9 @@ def index():
if request.form.get("form-name") == "delete-alias":
LOG.i(f"User {current_user} requested deletion of alias {alias}")
email = alias.email
alias_utils.delete_alias(alias, current_user)
alias_utils.delete_alias(
alias, current_user, AliasDeleteReason.ManualAction
)
flash(f"Alias {email} has been deleted", "success")
elif request.form.get("form-name") == "disable-alias":
alias_utils.change_alias_status(alias, enabled=False)
Expand Down
38 changes: 36 additions & 2 deletions app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,15 @@ class UnsubscribeBehaviourEnum(EnumE):
PreserveOriginal = 2


class AliasDeleteReason(EnumE):
Unspecified = 0
UserHasBeenDeleted = 1
ManualAction = 2
DirectoryDeleted = 3
MailboxDeleted = 4
CustomDomainDeleted = 5


class IntEnumType(sa.types.TypeDecorator):
impl = sa.Integer

Expand Down Expand Up @@ -667,6 +676,12 @@ def delete(cls, obj_id, commit=False):
user: User = cls.get(obj_id)
EventDispatcher.send_event(user, EventContent(user_deleted=UserDeleted()))

# Manually delete all aliases for the user that is about to be deleted
from app.alias_utils import delete_alias

for alias in Alias.filter_by(user_id=user.id):
delete_alias(alias, user, AliasDeleteReason.UserHasBeenDeleted)

res = super(User, cls).delete(obj_id)
if commit:
Session.commit()
Expand Down Expand Up @@ -2261,6 +2276,12 @@ class DeletedAlias(Base, ModelMixin):
__tablename__ = "deleted_alias"

email = sa.Column(sa.String(256), unique=True, nullable=False)
reason = sa.Column(
IntEnumType(AliasDeleteReason),
nullable=False,
default=AliasDeleteReason.Unspecified,
server_default=str(AliasDeleteReason.Unspecified.value),
)

@classmethod
def create(cls, **kw):
Expand Down Expand Up @@ -2448,6 +2469,13 @@ def delete(cls, obj_id):
if obj.is_sl_subdomain:
DeletedSubdomain.create(domain=obj.domain)

from app import alias_utils

for alias in Alias.filter_by(custom_domain_id=obj_id):
alias_utils.delete_alias(
alias, obj.user, AliasDeleteReason.CustomDomainDeleted
)

return super(CustomDomain, cls).delete(obj_id)

@property
Expand Down Expand Up @@ -2520,6 +2548,12 @@ class DomainDeletedAlias(Base, ModelMixin):

domain = orm.relationship(CustomDomain)
user = orm.relationship(User, foreign_keys=[user_id])
reason = sa.Column(
IntEnumType(AliasDeleteReason),
nullable=False,
default=AliasDeleteReason.Unspecified,
server_default=str(AliasDeleteReason.Unspecified.value),
)

@classmethod
def create(cls, **kw):
Expand Down Expand Up @@ -2611,7 +2645,7 @@ def delete(cls, obj_id):
for alias in Alias.filter_by(directory_id=obj_id):
from app import alias_utils

alias_utils.delete_alias(alias, user)
alias_utils.delete_alias(alias, user, AliasDeleteReason.DirectoryDeleted)

DeletedDirectory.create(name=obj.name)
cls.filter(cls.id == obj_id).delete()
Expand Down Expand Up @@ -2739,7 +2773,7 @@ def delete(cls, obj_id):
from app import alias_utils

# only put aliases that have mailbox as a single mailbox into trash
alias_utils.delete_alias(alias, user)
alias_utils.delete_alias(alias, user, AliasDeleteReason.MailboxDeleted)
Session.commit()

cls.filter(cls.id == obj_id).delete()
Expand Down
31 changes: 31 additions & 0 deletions migrations/versions/2024_070516_d608b8e48082_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""empty message
Revision ID: d608b8e48082
Revises: 06a9a7133445
Create Date: 2024-07-05 16:56:04.220173
"""
import sqlalchemy_utils
from alembic import op
import sqlalchemy as sa


# revision identifiers, used by Alembic.
revision = 'd608b8e48082'
down_revision = '06a9a7133445'
branch_labels = None
depends_on = None


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('deleted_alias', sa.Column('reason', sa.Integer(), default=0, server_default='0', nullable=False))
op.add_column('domain_deleted_alias', sa.Column('reason', sa.Integer(), default=0, server_default='0', nullable=False))
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('domain_deleted_alias', 'reason')
op.drop_column('deleted_alias', 'reason')
# ### end Alembic commands ###

0 comments on commit f05f01b

Please sign in to comment.