diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index a1c54b49..6cfe6a60 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -24,7 +24,7 @@ class IdnaDomain(db.TypeDecorator): """ Stores a Unicode string in it's IDNA representation (ASCII only) """ - impl = db.String(80, collation="NOCASE") + impl = db.String(80) def process_bind_param(self, value, dialect): return idna.encode(value).decode("ascii").lower() @@ -37,7 +37,7 @@ class IdnaEmail(db.TypeDecorator): """ Stores a Unicode string in it's IDNA representation (ASCII only) """ - impl = db.String(255, collation="NOCASE") + impl = db.String(255) def process_bind_param(self, value, dialect): try: @@ -88,32 +88,39 @@ class JSONEncoded(db.TypeDecorator): return json.loads(value) if value else None -class Config(db.Model): - """ In-database configuration values - """ - - name = db.Column(db.String(255), primary_key=True, nullable=False) - value = db.Column(JSONEncoded) - - -# Many-to-many association table for domain managers -managers = db.Table('manager', - db.Column('domain_name', IdnaDomain, db.ForeignKey('domain.name')), - db.Column('user_email', IdnaEmail, db.ForeignKey('user.email')) -) - - class Base(db.Model): """ Base class for all models """ __abstract__ = True + metadata = sqlalchemy.schema.MetaData( + naming_convention={ + "fk": "%(table_name)s_%(column_0_name)s_fkey", + "pk": "%(table_name)s_pkey" + } + ) + created_at = db.Column(db.Date, nullable=False, default=datetime.now) updated_at = db.Column(db.Date, nullable=True, onupdate=datetime.now) comment = db.Column(db.String(255), nullable=True) +# Many-to-many association table for domain managers +managers = db.Table('manager', Base.metadata, + db.Column('domain_name', IdnaDomain, db.ForeignKey('domain.name')), + db.Column('user_email', IdnaEmail, db.ForeignKey('user.email')) +) + + +class Config(Base): + """ In-database configuration values + """ + + name = db.Column(db.String(255), primary_key=True, nullable=False) + value = db.Column(JSONEncoded) + + class Domain(Base): """ A DNS domain that has mail addresses associated to it. """ @@ -309,7 +316,7 @@ class User(Base, Email): # Settings displayed_name = db.Column(db.String(160), nullable=False, default="") spam_enabled = db.Column(db.Boolean(), nullable=False, default=True) - spam_threshold = db.Column(db.Integer(), nullable=False, default=80.0) + spam_threshold = db.Column(db.Integer(), nullable=False, default=80) # Flask-login attributes is_authenticated = True diff --git a/core/admin/migrations/env.py b/core/admin/migrations/env.py index bb43fc55..a3f9cf18 100755 --- a/core/admin/migrations/env.py +++ b/core/admin/migrations/env.py @@ -22,7 +22,9 @@ logger = logging.getLogger('alembic.env') from flask import current_app config.set_main_option('sqlalchemy.url', current_app.config.get('SQLALCHEMY_DATABASE_URI')) -target_metadata = current_app.extensions['migrate'].db.metadata +#target_metadata = current_app.extensions['migrate'].db.metadata +from mailu import models +target_metadata = models.Base.metadata # other values from the config, defined by the needs of env.py, # can be acquired: diff --git a/core/admin/migrations/versions/546b04c886f0_.py b/core/admin/migrations/versions/546b04c886f0_.py new file mode 100644 index 00000000..35534aa0 --- /dev/null +++ b/core/admin/migrations/versions/546b04c886f0_.py @@ -0,0 +1,79 @@ +""" Fix constraint naming by addint a name to all constraints + +Revision ID: 546b04c886f0 +Revises: 5aeb5811408e +Create Date: 2018-12-08 16:33:37.757634 + +""" + +# revision identifiers, used by Alembic. +revision = '546b04c886f0' +down_revision = 'cd79ed46d9c2' + +from alembic import op, context +import sqlalchemy as sa + + +def upgrade(): + # Only run this for somehow supported data types at the date we started naming constraints + # Among others, these will probably fail on MySQL + if context.get_bind().engine.name not in ('sqlite', 'postgresql'): + return + + metadata = context.get_context().opts['target_metadata'] + + # Drop every constraint on every table + with op.batch_alter_table('alias', naming_convention=metadata.naming_convention) as batch_op: + batch_op.drop_constraint('alias_pkey', type_="primary") + batch_op.drop_constraint('alias_domain_name_fkey', type_="foreignkey") + with op.batch_alter_table('alternative', naming_convention=metadata.naming_convention) as batch_op: + batch_op.drop_constraint('alternative_pkey', type_="primary") + batch_op.drop_constraint('alternative_domain_name_fkey', type_="foreignkey") + with op.batch_alter_table('manager', naming_convention=metadata.naming_convention) as batch_op: + batch_op.drop_constraint('manager_domain_name_fkey', type_="foreignkey") + batch_op.drop_constraint('manager_user_email_fkey', type_="foreignkey") + with op.batch_alter_table('token', naming_convention=metadata.naming_convention) as batch_op: + batch_op.drop_constraint('token_pkey', type_="primary") + batch_op.drop_constraint('token_user_email_fkey', type_="foreignkey") + with op.batch_alter_table('fetch', naming_convention=metadata.naming_convention) as batch_op: + batch_op.drop_constraint('fetch_pkey', type_="primary") + batch_op.drop_constraint('fetch_user_email_fkey', type_="foreignkey") + with op.batch_alter_table('relay', naming_convention=metadata.naming_convention) as batch_op: + batch_op.drop_constraint('relay_pkey', type_="primary") + with op.batch_alter_table('config', naming_convention=metadata.naming_convention) as batch_op: + batch_op.drop_constraint('config_pkey', type_="primary") + with op.batch_alter_table('user', naming_convention=metadata.naming_convention) as batch_op: + batch_op.drop_constraint('user_pkey', type_="primary") + batch_op.drop_constraint('user_domain_name_fkey', type_="foreignkey") + with op.batch_alter_table('domain', naming_convention=metadata.naming_convention) as batch_op: + batch_op.drop_constraint('domain_pkey', type_="primary") + + # Recreate constraints with proper names + with op.batch_alter_table('domain', naming_convention=metadata.naming_convention) as batch_op: + batch_op.create_primary_key('domain_pkey', ['name']) + with op.batch_alter_table('alias', naming_convention=metadata.naming_convention) as batch_op: + batch_op.create_primary_key('alias_pkey', ['email']) + batch_op.create_foreign_key('alias_domain_name_fkey', 'domain', ['domain_name'], ['name']) + with op.batch_alter_table('user', naming_convention=metadata.naming_convention) as batch_op: + batch_op.create_primary_key('user_pkey', ['email']) + batch_op.create_foreign_key('user_domain_name_fkey', 'domain', ['domain_name'], ['name']) + with op.batch_alter_table('alternative', naming_convention=metadata.naming_convention) as batch_op: + batch_op.create_primary_key('alternative_pkey', ['name']) + batch_op.create_foreign_key('alternative_domain_name_fkey', 'domain', ['domain_name'], ['name']) + with op.batch_alter_table('manager', naming_convention=metadata.naming_convention) as batch_op: + batch_op.create_foreign_key('manager_domain_name_fkey', 'domain', ['domain_name'], ['name']) + batch_op.create_foreign_key('manager_user_email_fkey', 'user', ['user_email'], ['email']) + with op.batch_alter_table('token', naming_convention=metadata.naming_convention) as batch_op: + batch_op.create_primary_key('token_pkey', ['id']) + batch_op.create_foreign_key('token_user_email_fkey', 'user', ['user_email'], ['email']) + with op.batch_alter_table('fetch', naming_convention=metadata.naming_convention) as batch_op: + batch_op.create_primary_key('fetch_pkey', ['id']) + batch_op.create_foreign_key('fetch_user_email_fkey', 'user', ['user_email'], ['email']) + with op.batch_alter_table('relay', naming_convention=metadata.naming_convention) as batch_op: + batch_op.create_primary_key('relay_pkey', ['name']) + with op.batch_alter_table('config', naming_convention=metadata.naming_convention) as batch_op: + batch_op.create_primary_key('config_pkey', ['name']) + + +def downgrade(): + pass