diff --git a/lemur/migrations/versions/449c3d5c7299_.py b/lemur/migrations/versions/449c3d5c7299_.py new file mode 100644 index 00000000..1dcb7ab5 --- /dev/null +++ b/lemur/migrations/versions/449c3d5c7299_.py @@ -0,0 +1,28 @@ +"""Add unique constraint to certificate_notification_associations table. + +Revision ID: 449c3d5c7299 +Revises: 5770674184de +Create Date: 2018-02-24 22:51:35.369229 + +""" + +# revision identifiers, used by Alembic. +revision = '449c3d5c7299' +down_revision = '5770674184de' + +from alembic import op +from flask_sqlalchemy import SQLAlchemy + +db = SQLAlchemy() + +CONSTRAINT_NAME = "uq_dest_not_ids" +TABLE = "certificate_notification_associations" +COLUMNS = ["notification_id", "certificate_id"] + + +def upgrade(): + op.create_unique_constraint(CONSTRAINT_NAME, TABLE, COLUMNS) + + +def downgrade(): + op.drop_constraint(CONSTRAINT_NAME, TABLE) diff --git a/lemur/migrations/versions/5770674184de_.py b/lemur/migrations/versions/5770674184de_.py new file mode 100644 index 00000000..99183525 --- /dev/null +++ b/lemur/migrations/versions/5770674184de_.py @@ -0,0 +1,42 @@ +"""Remove duplicates from certificate_notification_associations. + +Revision ID: 5770674184de +Revises: ce547319f7be +Create Date: 2018-02-23 15:27:30.335435 + +""" + +# revision identifiers, used by Alembic. +revision = '5770674184de' +down_revision = 'ce547319f7be' + +from flask_sqlalchemy import SQLAlchemy +from lemur.models import certificate_notification_associations + +db = SQLAlchemy() +session = db.session() + + +def upgrade(): + # Query for all entries in table + results = session.query(certificate_notification_associations).with_entities( + certificate_notification_associations.c.certificate_id, + certificate_notification_associations.c.notification_id, + certificate_notification_associations.c.id, + ) + + seen = {} + # Iterate through all entries and mark as seen for each certificate_id and notification_id pair + for x in results: + # If we've seen a pair already, delete the duplicates + if seen.get("{}-{}".format(x.certificate_id, x.notification_id)): + d = session.query(certificate_notification_associations).filter(certificate_notification_associations.c.id==x.id) + d.delete(synchronize_session=False) + seen["{}-{}".format(x.certificate_id, x.notification_id)] = True + db.session.commit() + db.session.flush() + + +def downgrade(): + # No way to downgrade this + pass diff --git a/lemur/migrations/versions/ce547319f7be_.py b/lemur/migrations/versions/ce547319f7be_.py new file mode 100644 index 00000000..fb130466 --- /dev/null +++ b/lemur/migrations/versions/ce547319f7be_.py @@ -0,0 +1,34 @@ +"""Add id column to certificate_notification_associations. + +Revision ID: ce547319f7be +Revises: 5bc47fa7cac4 +Create Date: 2018-02-23 11:00:02.150561 + +""" + +# revision identifiers, used by Alembic. +revision = 'ce547319f7be' +down_revision = '5bc47fa7cac4' + +import sqlalchemy as sa + +from alembic import op +from flask_sqlalchemy import SQLAlchemy + + +db = SQLAlchemy() + +TABLE = "certificate_notification_associations" + + +def upgrade(): + print("Adding id column") + op.add_column( + TABLE, + sa.Column('id', sa.Integer, primary_key=True, autoincrement=True) + ) + + +def downgrade(): + op.drop_column(TABLE, "id") + diff --git a/lemur/models.py b/lemur/models.py index f189d76c..244130ee 100644 --- a/lemur/models.py +++ b/lemur/models.py @@ -8,7 +8,7 @@ :license: Apache, see LICENSE for more details. .. moduleauthor:: Kevin Glisson """ -from sqlalchemy import Column, Integer, ForeignKey, Index +from sqlalchemy import Column, Integer, ForeignKey, Index, UniqueConstraint from lemur.database import db @@ -41,7 +41,9 @@ certificate_notification_associations = db.Table('certificate_notification_assoc Column('notification_id', Integer, ForeignKey('notifications.id', ondelete='cascade')), Column('certificate_id', Integer, - ForeignKey('certificates.id', ondelete='cascade')) + ForeignKey('certificates.id', ondelete='cascade')), + Column('id', Integer, primary_key=True, autoincrement=True), + UniqueConstraint('notification_id', 'certificate_id', name='uq_dest_not_ids') ) Index('certificate_notification_associations_ix', certificate_notification_associations.c.notification_id, certificate_notification_associations.c.certificate_id)