From 52e2e67081e97284eb8011093187bacd96d5d4c0 Mon Sep 17 00:00:00 2001 From: Son Nguyen Kim Date: Tue, 17 Aug 2021 19:02:35 +0200 Subject: [PATCH] add CustomDomain ownership_verified, ownership_txt_token column. Set ownership_verified=True for domain that has verified=True --- app/models.py | 37 ++++++++++++++++++- .../versions/2021_081718_d4392342465f_.py | 36 ++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 migrations/versions/2021_081718_d4392342465f_.py diff --git a/app/models.py b/app/models.py index 7b16e1e5..2512b40f 100644 --- a/app/models.py +++ b/app/models.py @@ -8,7 +8,7 @@ import arrow from arrow import Arrow from flask import url_for from flask_login import UserMixin -from sqlalchemy import text, desc, CheckConstraint, Index +from sqlalchemy import text, desc, CheckConstraint, Index, Column from sqlalchemy.orm import deferred from sqlalchemy_utils import ArrowType @@ -1785,6 +1785,7 @@ class CustomDomain(db.Model, ModelMixin): # default name to use when user replies/sends from alias name = db.Column(db.String(128), nullable=True, default=None) + # mx verified verified = db.Column(db.Boolean, nullable=False, default=False) dkim_verified = db.Column( db.Boolean, nullable=False, default=False, server_default="0" @@ -1813,6 +1814,26 @@ class CustomDomain(db.Model, ModelMixin): db.Integer, default=0, server_default="0", nullable=False ) + # only domain has the ownership verified can go the next DNS step + # MX verified domains before this change don't have to do the TXT check + # and therefore have ownership_verified=True + ownership_verified = db.Column( + db.Boolean, nullable=False, default=False, server_default="0" + ) + + # randomly generated TXT value for verifying domain ownership + # the TXT record should be sl-verification=txt_token + ownership_txt_token = db.Column(db.String(128), nullable=True) + + __table_args__ = ( + Index( + "ix_unique_domain", # Index name + "domain", # Columns which are part of the index + unique=True, + postgresql_where=Column("ownership_verified"), + ), # The condition + ) + user = db.relationship(User, foreign_keys=[user_id]) @property @@ -1828,6 +1849,20 @@ class CustomDomain(db.Model, ModelMixin): def get_trash_url(self): return URL + f"/dashboard/domains/{self.id}/trash" + def get_ownership_dns_txt_value(self): + return f"sl-verification={self.ownership_txt_token}" + + @classmethod + def create(cls, **kw): + domain: CustomDomain = super(CustomDomain, cls).create(**kw) + + # generate a domain ownership txt token + if not domain.ownership_txt_token: + domain.ownership_txt_token = random_string(30) + db.session.commit() + + return domain + def __repr__(self): return f"" diff --git a/migrations/versions/2021_081718_d4392342465f_.py b/migrations/versions/2021_081718_d4392342465f_.py new file mode 100644 index 00000000..8f77d626 --- /dev/null +++ b/migrations/versions/2021_081718_d4392342465f_.py @@ -0,0 +1,36 @@ +"""empty message + +Revision ID: d4392342465f +Revises: 9014cca7097c +Create Date: 2021-08-17 18:53:27.134187 + +""" +import sqlalchemy_utils +from alembic import op +import sqlalchemy as sa + +# revision identifiers, used by Alembic. +revision = 'd4392342465f' +down_revision = '9014cca7097c' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('custom_domain', sa.Column('ownership_txt_token', sa.String(length=128), nullable=True)) + op.add_column('custom_domain', sa.Column('ownership_verified', sa.Boolean(), server_default='0', nullable=False)) + op.create_index('ix_unique_domain', 'custom_domain', ['domain'], unique=True, + postgresql_where=sa.text('ownership_verified')) + + # set ownership_verified=True for domain that has verified=True + op.execute('UPDATE custom_domain SET ownership_verified = true WHERE verified = true') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_index('ix_unique_domain', table_name='custom_domain') + op.drop_column('custom_domain', 'ownership_verified') + op.drop_column('custom_domain', 'ownership_txt_token') + # ### end Alembic commands ###