diff --git a/app/dao/services_dao.py b/app/dao/services_dao.py index da8b80b42..18819a862 100644 --- a/app/dao/services_dao.py +++ b/app/dao/services_dao.py @@ -361,7 +361,7 @@ def dao_resume_service(service_id): def dao_fetch_active_users_for_service(service_id): query = User.query.filter( - User.user_to_service.any(id=service_id), + User.services.any(id=service_id), User.state == 'active' ) diff --git a/app/models.py b/app/models.py index 68dd46b3d..7bc0d2c45 100644 --- a/app/models.py +++ b/app/models.py @@ -119,7 +119,7 @@ class User(db.Model): services = db.relationship( 'Service', secondary='user_to_service', - backref='user_to_service') + backref='users') organisations = db.relationship( 'Organisation', secondary='user_to_organisation', @@ -169,13 +169,16 @@ class User(db.Model): } -user_to_service = db.Table( - 'user_to_service', - db.Model.metadata, - db.Column('user_id', UUID(as_uuid=True), db.ForeignKey('users.id')), - db.Column('service_id', UUID(as_uuid=True), db.ForeignKey('services.id')), - UniqueConstraint('user_id', 'service_id', name='uix_user_to_service') -) +class ServiceUser(db.Model): + __tablename__ = 'user_to_service' + user_id = db.Column(UUID(as_uuid=True), db.ForeignKey('users.id'), primary_key=True) + service_id = db.Column(UUID(as_uuid=True), db.ForeignKey('services.id'), primary_key=True) + + __table_args__ = ( + UniqueConstraint('user_id', 'service_id', name='uix_user_to_service'), + ) + + user = db.relationship('User') user_to_organisation = db.Table( @@ -187,6 +190,17 @@ user_to_organisation = db.Table( ) +user_folder_permissions = db.Table( + 'user_folder_permissions', + db.Model.metadata, + db.Column('user_id', UUID(as_uuid=True), primary_key=True), + db.Column('template_folder_id', UUID(as_uuid=True), db.ForeignKey('template_folder.id'), primary_key=True), + db.Column('service_id', UUID(as_uuid=True), primary_key=True), + db.ForeignKeyConstraint(['user_id', 'service_id'], ['user_to_service.user_id', 'user_to_service.service_id']), + db.ForeignKeyConstraint(['template_folder_id', 'service_id'], ['template_folder.id', 'template_folder.service_id']) +) + + BRANDING_GOVUK = 'govuk' # Deprecated outside migrations BRANDING_ORG = 'org' BRANDING_BOTH = 'both' @@ -344,10 +358,6 @@ class Service(db.Model, Versioned): onupdate=datetime.datetime.utcnow) active = db.Column(db.Boolean, index=False, unique=False, nullable=False, default=True) message_limit = db.Column(db.BigInteger, index=False, unique=False, nullable=False) - users = db.relationship( - 'User', - secondary=user_to_service, - backref=db.backref('user_to_service', lazy='dynamic')) restricted = db.Column(db.Boolean, index=False, unique=False, nullable=False) research_mode = db.Column(db.Boolean, index=False, unique=False, nullable=False, default=False) email_from = db.Column(db.Text, index=False, unique=True, nullable=False) @@ -727,6 +737,17 @@ class TemplateFolder(db.Model): service = db.relationship('Service', backref='all_template_folders') parent = db.relationship('TemplateFolder', remote_side=[id], backref='subfolders') + users = db.relationship( + 'ServiceUser', + uselist=True, + backref=db.backref('folders', foreign_keys='user_folder_permissions.c.template_folder_id'), + secondary='user_folder_permissions', + primaryjoin='TemplateFolder.id == user_folder_permissions.c.template_folder_id' + ) + + __table_args__ = ( + UniqueConstraint('id', 'service_id', name='ix_id_service_id'), {} + ) def serialize(self): return { diff --git a/migrations/versions/0266_user_folder_perms_table.py b/migrations/versions/0266_user_folder_perms_table.py new file mode 100644 index 000000000..cbd3c1ffb --- /dev/null +++ b/migrations/versions/0266_user_folder_perms_table.py @@ -0,0 +1,32 @@ +""" + +Revision ID: 0266_user_folder_perms_table +Revises: 0265_add_confirm_edit_templates +Create Date: 2019-02-26 17:00:13.247321 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +revision = '0266_user_folder_perms_table' +down_revision = '0265_add_confirm_edit_templates' + + +def upgrade(): + op.create_unique_constraint('ix_id_service_id', 'template_folder', ['id', 'service_id']) + op.create_table('user_folder_permissions', + sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False), + sa.Column('template_folder_id', postgresql.UUID(as_uuid=True), nullable=False), + sa.Column('service_id', postgresql.UUID(as_uuid=True), nullable=False), + sa.ForeignKeyConstraint(['template_folder_id', 'service_id'], ['template_folder.id', 'template_folder.service_id'], ), + sa.ForeignKeyConstraint(['user_id', 'service_id'], ['user_to_service.user_id', 'user_to_service.service_id'], ), + sa.ForeignKeyConstraint(['template_folder_id'], ['template_folder.id'], ), + sa.PrimaryKeyConstraint('user_id', 'template_folder_id', 'service_id'), + ) + + + +def downgrade(): + op.drop_table('user_folder_permissions') + op.drop_constraint('ix_id_service_id', 'template_folder', type_='unique')