diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d70dc57549e841f78918213e56d5b42a0fb6356c..b11a4c23ba80a5b12d89de7435b1e0c93805ce43 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -75,33 +75,30 @@ linter:bullseye: reports: codequality: codeclimate.json +linter:bookworm: + image: registry.git.cccv.de/uffd/docker-images/bookworm + stage: test + needs: [] + script: + - pip3 install $PYLINT_PIN pylint-gitlab pylint-flask-sqlalchemy # this force-updates jinja2 and some other packages! + - python3 -m pylint --output-format=pylint_gitlab.GitlabCodeClimateReporter:codeclimate.json,pylint_gitlab.GitlabPagesHtmlReporter:pylint.html,colorized uffd + artifacts: + when: always + paths: + - pylint.html + reports: + codequality: codeclimate.json + tests:buster:sqlite: image: registry.git.cccv.de/uffd/docker-images/buster stage: test needs: [] script: - - rm -rf pages - - mkdir -p pages - - cp -r uffd/static pages/static - - DUMP_PAGES=pages python3-coverage run --include 'uffd/*.py' -m pytest --junitxml=report.xml || touch failed - - sed -i -e 's/href="\/static\//href=".\/static\//g' -e 's/src="\/static\//src=".\/static\//g' pages/*.html || true - - python3-coverage report -m - - python3-coverage html - - python3-coverage xml - - test ! -e failed + - python3 -m pytest --junitxml=report.xml artifacts: when: always - paths: - - htmlcov/index.html - - htmlcov - - pages - expose_as: 'Coverage Report' reports: - coverage_report: - coverage_format: cobertura - path: coverage.xml junit: report.xml - coverage: '/^TOTAL.*\s+(\d+\%)$/' tests:buster:mysql: image: registry.git.cccv.de/uffd/docker-images/buster @@ -138,10 +135,50 @@ tests:bullseye:mysql: reports: junit: report.xml +tests:bookworm:sqlite: + image: registry.git.cccv.de/uffd/docker-images/bookworm + stage: test + needs: [] + script: + - rm -rf pages + - mkdir -p pages + - cp -r uffd/static pages/static + - DUMP_PAGES=pages python3-coverage run --include 'uffd/*.py' -m pytest --junitxml=report.xml || touch failed + - sed -i -e 's/href="\/static\//href=".\/static\//g' -e 's/src="\/static\//src=".\/static\//g' pages/*.html || true + - python3-coverage report -m + - python3-coverage html + - python3-coverage xml + - test ! -e failed + artifacts: + when: always + paths: + - htmlcov/index.html + - htmlcov + - pages + expose_as: 'Coverage Report' + reports: + coverage_report: + coverage_format: cobertura + path: coverage.xml + junit: report.xml + coverage: '/^TOTAL.*\s+(\d+\%)$/' + +tests:bookworm:mysql: + image: registry.git.cccv.de/uffd/docker-images/bookworm + stage: test + needs: [] + script: + - service mariadb start + - TEST_WITH_MYSQL=1 python3 -m pytest --junitxml=report.xml + artifacts: + when: always + reports: + junit: report.xml + html5validator: stage: test needs: - - job: tests:buster:sqlite + - job: tests:bookworm:sqlite script: - html5validator --root pages 2>&1 | tee html5validator.log artifacts: @@ -177,6 +214,14 @@ test:package:pip:bullseye: script: - pip3 install dist/*.tar.gz +test:package:pip:bookworm: + image: registry.git.cccv.de/uffd/docker-images/bookworm + stage: test + needs: + - job: build:pip + script: + - pip3 install dist/*.tar.gz + # Since we want to test if the package installs correctly on a fresh Debian # install (has correct dependencies, etc.), we don't use uffd/docker-images # here @@ -210,6 +255,21 @@ test:package:apt:bullseye: - uffd-admin routes - curl -Lv 127.0.0.1:5000 +test:package:apt:bookworm: + image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/debian:bookworm + stage: test + needs: + - job: build:apt + before_script: [] + script: + - apt -y update + - apt -y install curl ./*.deb + - service uwsgi start uffd || ( service uwsgi status uffd ; sleep 15; cat /var/log/uwsgi/app/uffd.log; ) + - echo "server { listen 127.0.0.1:5000 default_server; include /etc/uffd/nginx.include.conf; }" > /etc/nginx/sites-enabled/uffd.ini + - service nginx start || ( service nginx status; nginx -t; exit 1; ) + - uffd-admin routes + - curl -Lv 127.0.0.1:5000 + .publish: stage: deploy rules: @@ -234,5 +294,6 @@ publish:apt: - echo Update published repo for all distros - 'curl --user "${APTLY_API_USER}:${APTLY_API_PW}" -X PUT -H "Content-Type: application/json" --data "{ }" "${APT_API_URL}/api/publish/uffd/buster"' - 'curl --user "${APTLY_API_USER}:${APTLY_API_PW}" -X PUT -H "Content-Type: application/json" --data "{ }" "${APT_API_URL}/api/publish/uffd/bullseye"' + - 'curl --user "${APTLY_API_USER}:${APTLY_API_PW}" -X PUT -H "Content-Type: application/json" --data "{ }" "${APT_API_URL}/api/publish/uffd/bookworm"' dependencies: - build:apt diff --git a/README.md b/README.md index f9e79f31372d4811f3ee4805395a40262d6f2bde..f1cd4f309c75460fd5cb38f7bc7943caa70685e5 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Please note that we refer to Debian packages here and **not** pip packages. - python3-itsdangerous (also a dependency of python3-flask) - python3-mysqldb or python3-pymysql for MariaDB support -Some of the dependencies (especially fido2) changed their API in recent versions, so make sure to install the versions from Debian Buster or Bullseye. +Some of the dependencies (especially fido2) changed their API in recent versions, so make sure to install the versions from Debian Bookworm, Bullseye or Buster. For development, you can also use virtualenv with the supplied `requirements.txt`. ## Development @@ -57,7 +57,7 @@ The dependencies of the pip package roughly represent the versions shipped by De We do not keep them updated and we do not test the pip package! The pip package only exists for local testing/development and to help build the Debian package. -We provide packages for Debian stable and oldstable (currently Bullseye and Buster). +We provide packages for Debian stable, oldstable and oldoldstable (currently Bookworm, Bullseye and Buster). Since all dependencies are available in the official package mirrors, you will get security updates for everything but uffd itself from Debian. To install uffd on Debian Bullseye, add our package mirror to `/etc/sources.list`: diff --git a/tests/views/test_selfservice.py b/tests/views/test_selfservice.py index b5b202414faa3ba2be6825e21e74574c5b2544ee..2396b77f868fc3d7d7a4c49b0ad90e4a100a045d 100644 --- a/tests/views/test_selfservice.py +++ b/tests/views/test_selfservice.py @@ -21,25 +21,23 @@ class TestSelfservice(UffdTestCase): def test_update_displayname(self): self.login_as('user') - user = request.user r = self.client.post(path=url_for('selfservice.update_profile'), data={'displayname': 'New Display Name'}, follow_redirects=True) dump('update_displayname', r) self.assertEqual(r.status_code, 200) - _user = request.user - self.assertEqual(_user.displayname, 'New Display Name') + user = self.get_user() + self.assertEqual(user.displayname, 'New Display Name') def test_update_displayname_invalid(self): self.login_as('user') - user = request.user r = self.client.post(path=url_for('selfservice.update_profile'), data={'displayname': ''}, follow_redirects=True) dump('update_displayname_invalid', r) self.assertEqual(r.status_code, 200) - _user = request.user - self.assertNotEqual(_user.displayname, '') + user = self.get_user() + self.assertNotEqual(user.displayname, '') def test_add_email(self): self.login_as('user') @@ -52,7 +50,7 @@ class TestSelfservice(UffdTestCase): m = re.search(r'/email/([0-9]+)/verify/(.*)', str(self.app.last_mail.get_content())) email_id, secret = m.groups() email = UserEmail.query.get(email_id) - self.assertEqual(email.user, request.user) + self.assertEqual(email.user.id, request.user.id) self.assertEqual(email.address, 'new@example.com') self.assertFalse(email.verified) self.assertFalse(email.verification_expired) @@ -164,7 +162,7 @@ class TestSelfservice(UffdTestCase): m = re.search(r'/email/([0-9]+)/verify/(.*)', str(self.app.last_mail.get_content())) email_id, secret = m.groups() email = UserEmail.query.get(email_id) - self.assertEqual(email.user, request.user) + self.assertEqual(email.user.id, request.user.id) self.assertEqual(email.address, 'new@example.com') self.assertFalse(email.verified) self.assertFalse(email.verification_expired) @@ -245,17 +243,20 @@ class TestSelfservice(UffdTestCase): r = self.client.post(path=url_for('selfservice.update_email_preferences'), data={'primary_email': str(email_id), 'recovery_email': 'primary'}, follow_redirects=True) - self.assertEqual(self.get_user().primary_email.address, 'test@example.com') + with self.app.test_request_context(): + self.assertEqual(self.get_user().primary_email.address, 'test@example.com') with self.assertRaises(Exception): r = self.client.post(path=url_for('selfservice.update_email_preferences'), data={'primary_email': str(old_email_id), 'recovery_email': str(email_id)}, follow_redirects=True) - self.assertIsNone(self.get_user().recovery_email) + with self.app.test_request_context(): + self.assertIsNone(self.get_user().recovery_email) with self.assertRaises(Exception): r = self.client.post(path=url_for('selfservice.update_email_preferences'), data={'primary_email': str(old_email_id), 'recovery_email': 'primary', f'service_{service_id}_email': str(email_id)}, follow_redirects=True) - self.assertIsNone(ServiceUser.query.get((service_id, user_id)).service_email) + with self.app.test_request_context(): + self.assertIsNone(ServiceUser.query.get((service_id, user_id)).service_email) def test_update_email_preferences_invalid(self): self.login_as('user') @@ -284,52 +285,47 @@ class TestSelfservice(UffdTestCase): def test_change_password(self): self.login_as('user') - user = request.user r = self.client.post(path=url_for('selfservice.change_password'), data={'password1': 'newpassword', 'password2': 'newpassword'}, follow_redirects=True) dump('change_password', r) self.assertEqual(r.status_code, 200) - _user = request.user - self.assertTrue(_user.password.verify('newpassword')) + self.assertTrue(self.get_user().password.verify('newpassword')) def test_change_password_invalid(self): self.login_as('user') - user = request.user r = self.client.post(path=url_for('selfservice.change_password'), data={'password1': 'shortpw', 'password2': 'shortpw'}, follow_redirects=True) dump('change_password_invalid', r) self.assertEqual(r.status_code, 200) - _user = request.user - self.assertFalse(_user.password.verify('shortpw')) - self.assertTrue(_user.password.verify('userpassword')) + user = self.get_user() + self.assertFalse(user.password.verify('shortpw')) + self.assertTrue(user.password.verify('userpassword')) # Regression test for #100 (login not possible if password contains character disallowed by SASLprep) def test_change_password_samlprep_invalid(self): self.login_as('user') - user = request.user r = self.client.post(path=url_for('selfservice.change_password'), data={'password1': 'shortpw\n', 'password2': 'shortpw\n'}, follow_redirects=True) dump('change_password_samlprep_invalid', r) self.assertEqual(r.status_code, 200) - _user = request.user - self.assertFalse(_user.password.verify('shortpw\n')) - self.assertTrue(_user.password.verify('userpassword')) + user = self.get_user() + self.assertFalse(user.password.verify('shortpw\n')) + self.assertTrue(user.password.verify('userpassword')) def test_change_password_mismatch(self): self.login_as('user') - user = request.user r = self.client.post(path=url_for('selfservice.change_password'), data={'password1': 'newpassword1', 'password2': 'newpassword2'}, follow_redirects=True) dump('change_password_mismatch', r) self.assertEqual(r.status_code, 200) - _user = request.user - self.assertFalse(_user.password.verify('newpassword1')) - self.assertFalse(_user.password.verify('newpassword2')) - self.assertTrue(_user.password.verify('userpassword')) + user = self.get_user() + self.assertFalse(user.password.verify('newpassword1')) + self.assertFalse(user.password.verify('newpassword2')) + self.assertTrue(user.password.verify('userpassword')) def test_leave_role(self): baserole = Role(name='baserole', is_default=True) diff --git a/uffd/migrations/versions/23293f32b503_deactivate_users.py b/uffd/migrations/versions/23293f32b503_deactivate_users.py index c25dbf6cbc1045a0f398f0a2730da096c466806e..d6b9c9c243bef49537f29bf142f6e1df472e3ced 100644 --- a/uffd/migrations/versions/23293f32b503_deactivate_users.py +++ b/uffd/migrations/versions/23293f32b503_deactivate_users.py @@ -16,15 +16,15 @@ depends_on = None def upgrade(): meta = sa.MetaData(bind=op.get_bind()) with op.batch_alter_table('service', schema=None) as batch_op: - batch_op.add_column(sa.Column('hide_deactivated_users', sa.Boolean(), nullable=False, server_default=sa.false())) + batch_op.add_column(sa.Column('hide_deactivated_users', sa.Boolean(create_constraint=True), nullable=False, server_default=sa.false())) service = sa.Table('service', meta, sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('name', sa.String(length=255), nullable=False), - sa.Column('limit_access', sa.Boolean(), nullable=False), + sa.Column('limit_access', sa.Boolean(create_constraint=True), nullable=False), sa.Column('access_group_id', sa.Integer(), nullable=True), - sa.Column('remailer_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', name='remailermode'), nullable=False), - sa.Column('enable_email_preferences', sa.Boolean(), nullable=False), - sa.Column('hide_deactivated_users', sa.Boolean(), nullable=False, server_default=sa.false()), + sa.Column('remailer_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', create_constraint=True, name='remailermode'), nullable=False), + sa.Column('enable_email_preferences', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('hide_deactivated_users', sa.Boolean(create_constraint=True), nullable=False, server_default=sa.false()), sa.ForeignKeyConstraint(['access_group_id'], ['group.id'], name=op.f('fk_service_access_group_id_group'), onupdate='CASCADE', ondelete='SET NULL'), sa.PrimaryKeyConstraint('id', name=op.f('pk_service')), sa.UniqueConstraint('name', name=op.f('uq_service_name')) @@ -32,7 +32,7 @@ def upgrade(): with op.batch_alter_table('service', copy_from=service) as batch_op: batch_op.alter_column('hide_deactivated_users', server_default=None) with op.batch_alter_table('user', schema=None) as batch_op: - batch_op.add_column(sa.Column('is_deactivated', sa.Boolean(), nullable=False, server_default=sa.false())) + batch_op.add_column(sa.Column('is_deactivated', sa.Boolean(create_constraint=True), nullable=False, server_default=sa.false())) user = sa.Table('user', meta, sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('unix_uid', sa.Integer(), nullable=False), @@ -41,8 +41,8 @@ def upgrade(): sa.Column('primary_email_id', sa.Integer(), nullable=False), sa.Column('recovery_email_id', sa.Integer(), nullable=True), sa.Column('pwhash', sa.Text(), nullable=True), - sa.Column('is_service_user', sa.Boolean(), nullable=False), - sa.Column('is_deactivated', sa.Boolean(), nullable=False, server_default=sa.false()), + sa.Column('is_service_user', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('is_deactivated', sa.Boolean(create_constraint=True), nullable=False, server_default=sa.false()), sa.ForeignKeyConstraint(['primary_email_id'], ['user_email.id'], name=op.f('fk_user_primary_email_id_user_email'), onupdate='CASCADE'), sa.ForeignKeyConstraint(['recovery_email_id'], ['user_email.id'], name=op.f('fk_user_recovery_email_id_user_email'), onupdate='CASCADE', ondelete='SET NULL'), sa.ForeignKeyConstraint(['unix_uid'], ['uid_allocation.id'], name=op.f('fk_user_unix_uid_uid_allocation')), @@ -63,8 +63,8 @@ def downgrade(): sa.Column('primary_email_id', sa.Integer(), nullable=False), sa.Column('recovery_email_id', sa.Integer(), nullable=True), sa.Column('pwhash', sa.Text(), nullable=True), - sa.Column('is_service_user', sa.Boolean(), nullable=False), - sa.Column('is_deactivated', sa.Boolean(), nullable=False), + sa.Column('is_service_user', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('is_deactivated', sa.Boolean(create_constraint=True), nullable=False), sa.ForeignKeyConstraint(['primary_email_id'], ['user_email.id'], name=op.f('fk_user_primary_email_id_user_email'), onupdate='CASCADE'), sa.ForeignKeyConstraint(['recovery_email_id'], ['user_email.id'], name=op.f('fk_user_recovery_email_id_user_email'), onupdate='CASCADE', ondelete='SET NULL'), sa.ForeignKeyConstraint(['unix_uid'], ['uid_allocation.id'], name=op.f('fk_user_unix_uid_uid_allocation')), @@ -77,11 +77,11 @@ def downgrade(): service = sa.Table('service', meta, sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('name', sa.String(length=255), nullable=False), - sa.Column('limit_access', sa.Boolean(), nullable=False), + sa.Column('limit_access', sa.Boolean(create_constraint=True), nullable=False), sa.Column('access_group_id', sa.Integer(), nullable=True), - sa.Column('remailer_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', name='remailermode'), nullable=False), - sa.Column('enable_email_preferences', sa.Boolean(), nullable=False), - sa.Column('hide_deactivated_users', sa.Boolean(), nullable=False), + sa.Column('remailer_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', create_constraint=True, name='remailermode'), nullable=False), + sa.Column('enable_email_preferences', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('hide_deactivated_users', sa.Boolean(create_constraint=True), nullable=False), sa.ForeignKeyConstraint(['access_group_id'], ['group.id'], name=op.f('fk_service_access_group_id_group'), onupdate='CASCADE', ondelete='SET NULL'), sa.PrimaryKeyConstraint('id', name=op.f('pk_service')), sa.UniqueConstraint('name', name=op.f('uq_service_name')) diff --git a/uffd/migrations/versions/2b68f688bec1_remailer_v2.py b/uffd/migrations/versions/2b68f688bec1_remailer_v2.py index bdf95ccc793e6cd5eb3f50c7a0d6bdd158e67428..d48c3af170d40a6a1e412fceedcd3ed0489711f9 100644 --- a/uffd/migrations/versions/2b68f688bec1_remailer_v2.py +++ b/uffd/migrations/versions/2b68f688bec1_remailer_v2.py @@ -15,22 +15,22 @@ depends_on = None def upgrade(): with op.batch_alter_table('service', schema=None) as batch_op: - batch_op.add_column(sa.Column('remailer_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', name='remailermode'), nullable=False, server_default='DISABLED')) + batch_op.add_column(sa.Column('remailer_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', create_constraint=True, name='remailermode'), nullable=False, server_default='DISABLED')) service = sa.table('service', sa.column('id', sa.Integer), - sa.column('use_remailer', sa.Boolean), - sa.column('remailer_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', name='remailermode')), + sa.column('use_remailer', sa.Boolean(create_constraint=True)), + sa.column('remailer_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', create_constraint=True, name='remailermode')), ) op.execute(service.update().values(remailer_mode='ENABLED_V1').where(service.c.use_remailer)) meta = sa.MetaData(bind=op.get_bind()) service = sa.Table('service', meta, sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('name', sa.String(length=255), nullable=False), - sa.Column('limit_access', sa.Boolean(), nullable=False), + sa.Column('limit_access', sa.Boolean(create_constraint=True), nullable=False), sa.Column('access_group_id', sa.Integer(), nullable=True), - sa.Column('use_remailer', sa.Boolean(), nullable=False), - sa.Column('enable_email_preferences', sa.Boolean(), nullable=False), - sa.Column('remailer_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', name='remailermode'), nullable=False, server_default='DISABLED'), + sa.Column('use_remailer', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('enable_email_preferences', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('remailer_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', create_constraint=True, name='remailermode'), nullable=False, server_default='DISABLED'), sa.ForeignKeyConstraint(['access_group_id'], ['group.id'], name=op.f('fk_service_access_group_id_group'), onupdate='CASCADE', ondelete='SET NULL'), sa.PrimaryKeyConstraint('id', name=op.f('pk_service')), sa.UniqueConstraint('name', name=op.f('uq_service_name')) @@ -44,19 +44,19 @@ def downgrade(): batch_op.add_column(sa.Column('use_remailer', sa.BOOLEAN(), nullable=False, server_default=sa.false())) service = sa.table('service', sa.column('id', sa.Integer), - sa.column('use_remailer', sa.Boolean), - sa.column('remailer_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', name='remailermode')), + sa.column('use_remailer', sa.Boolean(create_constraint=True)), + sa.column('remailer_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', create_constraint=True, name='remailermode')), ) op.execute(service.update().values(use_remailer=sa.true()).where(service.c.remailer_mode != 'DISABLED')) meta = sa.MetaData(bind=op.get_bind()) service = sa.Table('service', meta, sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('name', sa.String(length=255), nullable=False), - sa.Column('limit_access', sa.Boolean(), nullable=False), + sa.Column('limit_access', sa.Boolean(create_constraint=True), nullable=False), sa.Column('access_group_id', sa.Integer(), nullable=True), - sa.Column('use_remailer', sa.Boolean(), nullable=False, server_default=sa.false()), - sa.Column('enable_email_preferences', sa.Boolean(), nullable=False), - sa.Column('remailer_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', name='remailermode'), nullable=False), + sa.Column('use_remailer', sa.Boolean(create_constraint=True), nullable=False, server_default=sa.false()), + sa.Column('enable_email_preferences', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('remailer_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', create_constraint=True, name='remailermode'), nullable=False), sa.ForeignKeyConstraint(['access_group_id'], ['group.id'], name=op.f('fk_service_access_group_id_group'), onupdate='CASCADE', ondelete='SET NULL'), sa.PrimaryKeyConstraint('id', name=op.f('pk_service')), sa.UniqueConstraint('name', name=op.f('uq_service_name')) diff --git a/uffd/migrations/versions/468995a9c9ee_unique_email_addresses.py b/uffd/migrations/versions/468995a9c9ee_unique_email_addresses.py index 2c776195e443b307262c203f8ea94fee48ab05c9..b9bc7058a55bf9b81eadd43f2a93d6ad82065812 100644 --- a/uffd/migrations/versions/468995a9c9ee_unique_email_addresses.py +++ b/uffd/migrations/versions/468995a9c9ee_unique_email_addresses.py @@ -37,16 +37,16 @@ def iter_rows_paged(table, pk='id', limit=1000): def upgrade(): with op.batch_alter_table('user_email', schema=None) as batch_op: batch_op.add_column(sa.Column('address_normalized', sa.String(length=128), nullable=True)) - batch_op.add_column(sa.Column('enable_strict_constraints', sa.Boolean(), nullable=True)) - batch_op.alter_column('verified', existing_type=sa.Boolean(), nullable=True) + batch_op.add_column(sa.Column('enable_strict_constraints', sa.Boolean(create_constraint=True), nullable=True)) + batch_op.alter_column('verified', existing_type=sa.Boolean(create_constraint=True), nullable=True) meta = sa.MetaData(bind=op.get_bind()) user_email_table = sa.Table('user_email', meta, sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('user_id', sa.Integer(), nullable=True), sa.Column('address', sa.String(length=128), nullable=False), sa.Column('address_normalized', sa.String(length=128), nullable=True), - sa.Column('enable_strict_constraints', sa.Boolean(), nullable=True), - sa.Column('verified', sa.Boolean(), nullable=True), + sa.Column('enable_strict_constraints', sa.Boolean(create_constraint=True), nullable=True), + sa.Column('verified', sa.Boolean(create_constraint=True), nullable=True), sa.Column('verification_legacy_id', sa.Integer(), nullable=True), sa.Column('verification_secret', sa.Text(), nullable=True), sa.Column('verification_expires', sa.DateTime(), nullable=True), @@ -81,8 +81,8 @@ def downgrade(): sa.Column('user_id', sa.Integer(), nullable=True), sa.Column('address', sa.String(length=128), nullable=False), sa.Column('address_normalized', sa.String(length=128), nullable=False), - sa.Column('enable_strict_constraints', sa.Boolean(), nullable=True), - sa.Column('verified', sa.Boolean(), nullable=True), + sa.Column('enable_strict_constraints', sa.Boolean(create_constraint=True), nullable=True), + sa.Column('verified', sa.Boolean(create_constraint=True), nullable=True), sa.Column('verification_legacy_id', sa.Integer(), nullable=True), sa.Column('verification_secret', sa.Text(), nullable=True), sa.Column('verification_expires', sa.DateTime(), nullable=True), @@ -96,7 +96,7 @@ def downgrade(): with op.batch_alter_table('user_email', copy_from=user_email_table) as batch_op: batch_op.drop_constraint('uq_user_email_user_id_address_normalized', type_='unique') batch_op.drop_constraint('uq_user_email_address_normalized_verified', type_='unique') - batch_op.alter_column('verified', existing_type=sa.Boolean(), nullable=False) + batch_op.alter_column('verified', existing_type=sa.Boolean(create_constraint=True), nullable=False) batch_op.drop_column('enable_strict_constraints') batch_op.drop_column('address_normalized') op.drop_table('feature_flag') diff --git a/uffd/migrations/versions/54b2413586fd_invite_pk_change.py b/uffd/migrations/versions/54b2413586fd_invite_pk_change.py index a59e2ca69336fd8027a967e9436e250605b4a6b8..75d60783b5783a7ba6ca55952eb96a95adad8503 100644 --- a/uffd/migrations/versions/54b2413586fd_invite_pk_change.py +++ b/uffd/migrations/versions/54b2413586fd_invite_pk_change.py @@ -38,10 +38,10 @@ def upgrade(): sa.Column('token', sa.String(length=128), nullable=False), sa.Column('created', sa.DateTime(), nullable=False), sa.Column('valid_until', sa.DateTime(), nullable=False), - sa.Column('single_use', sa.Boolean(name=op.f('ck_invite_single_use')), nullable=False), - sa.Column('allow_signup', sa.Boolean(name=op.f('ck_invite_allow_signup')), nullable=False), - sa.Column('used', sa.Boolean(name=op.f('ck_invite_used')), nullable=False), - sa.Column('disabled', sa.Boolean(name=op.f('ck_invite_disabled')), nullable=False), + sa.Column('single_use', sa.Boolean(create_constraint=True, name=op.f('ck_invite_single_use')), nullable=False), + sa.Column('allow_signup', sa.Boolean(create_constraint=True, name=op.f('ck_invite_allow_signup')), nullable=False), + sa.Column('used', sa.Boolean(create_constraint=True, name=op.f('ck_invite_used')), nullable=False), + sa.Column('disabled', sa.Boolean(create_constraint=True, name=op.f('ck_invite_disabled')), nullable=False), sa.PrimaryKeyConstraint('token', name=op.f('pk_invite')) ) with op.batch_alter_table('invite_grant', schema=None) as batch_op: @@ -115,10 +115,10 @@ def downgrade(): sa.Column('token', sa.String(length=128), nullable=False), sa.Column('created', sa.DateTime(), nullable=False), sa.Column('valid_until', sa.DateTime(), nullable=False), - sa.Column('single_use', sa.Boolean(name=op.f('ck_invite_single_use')), nullable=False), - sa.Column('allow_signup', sa.Boolean(name=op.f('ck_invite_allow_signup')), nullable=False), - sa.Column('used', sa.Boolean(name=op.f('ck_invite_used')), nullable=False), - sa.Column('disabled', sa.Boolean(name=op.f('ck_invite_disabled')), nullable=False), + sa.Column('single_use', sa.Boolean(create_constraint=True, name=op.f('ck_invite_single_use')), nullable=False), + sa.Column('allow_signup', sa.Boolean(create_constraint=True, name=op.f('ck_invite_allow_signup')), nullable=False), + sa.Column('used', sa.Boolean(create_constraint=True, name=op.f('ck_invite_used')), nullable=False), + sa.Column('disabled', sa.Boolean(create_constraint=True, name=op.f('ck_invite_disabled')), nullable=False), sa.PrimaryKeyConstraint('id', name=op.f('pk_invite')), sa.UniqueConstraint('token', name=op.f('uq_invite_token')) ) diff --git a/uffd/migrations/versions/704d1245331c_remailer_setting_and_api_permission.py b/uffd/migrations/versions/704d1245331c_remailer_setting_and_api_permission.py index 8933610d6ea6032407268bbe304c14d12b926cbb..3e63561b974033632be6643ee8450ea7eed6e24e 100644 --- a/uffd/migrations/versions/704d1245331c_remailer_setting_and_api_permission.py +++ b/uffd/migrations/versions/704d1245331c_remailer_setting_and_api_permission.py @@ -21,19 +21,19 @@ def upgrade(): # table. To keep the resulting database consistent, we remove the # server_default afterwards. with op.batch_alter_table('api_client') as batch_op: - batch_op.add_column(sa.Column('perm_remailer', sa.Boolean(), nullable=False, server_default=sa.false())) + batch_op.add_column(sa.Column('perm_remailer', sa.Boolean(create_constraint=True), nullable=False, server_default=sa.false())) with op.batch_alter_table('service') as batch_op: - batch_op.add_column(sa.Column('use_remailer', sa.Boolean(), nullable=False, server_default=sa.false())) + batch_op.add_column(sa.Column('use_remailer', sa.Boolean(create_constraint=True), nullable=False, server_default=sa.false())) meta = sa.MetaData(bind=op.get_bind()) api_client = sa.Table('api_client', meta, sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('service_id', sa.Integer(), nullable=False), sa.Column('auth_username', sa.String(length=40), nullable=False), sa.Column('auth_password', sa.Text(), nullable=False), - sa.Column('perm_users', sa.Boolean(), nullable=False), - sa.Column('perm_checkpassword', sa.Boolean(), nullable=False), - sa.Column('perm_mail_aliases', sa.Boolean(), nullable=False), - sa.Column('perm_remailer', sa.Boolean(), nullable=False, server_default=sa.false()), + sa.Column('perm_users', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('perm_checkpassword', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('perm_mail_aliases', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('perm_remailer', sa.Boolean(create_constraint=True), nullable=False, server_default=sa.false()), sa.ForeignKeyConstraint(['service_id'], ['service.id'], name=op.f('fk_api_client_service_id_service'), onupdate='CASCADE', ondelete='CASCADE'), sa.PrimaryKeyConstraint('id', name=op.f('pk_api_client')), sa.UniqueConstraint('auth_username', name=op.f('uq_api_client_auth_username')) @@ -41,9 +41,9 @@ def upgrade(): service = sa.Table('service', meta, sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('name', sa.String(length=255), nullable=False), - sa.Column('limit_access', sa.Boolean(), nullable=False), + sa.Column('limit_access', sa.Boolean(create_constraint=True), nullable=False), sa.Column('access_group_id', sa.Integer(), nullable=True), - sa.Column('use_remailer', sa.Boolean(), nullable=False, server_default=sa.false()), + sa.Column('use_remailer', sa.Boolean(create_constraint=True), nullable=False, server_default=sa.false()), sa.ForeignKeyConstraint(['access_group_id'], ['group.id'], name=op.f('fk_service_access_group_id_group'), onupdate='CASCADE', ondelete='SET NULL'), sa.PrimaryKeyConstraint('id', name=op.f('pk_service')), sa.UniqueConstraint('name', name=op.f('uq_service_name')) @@ -60,10 +60,10 @@ def downgrade(): sa.Column('service_id', sa.Integer(), nullable=False), sa.Column('auth_username', sa.String(length=40), nullable=False), sa.Column('auth_password', sa.Text(), nullable=False), - sa.Column('perm_users', sa.Boolean(), nullable=False), - sa.Column('perm_checkpassword', sa.Boolean(), nullable=False), - sa.Column('perm_mail_aliases', sa.Boolean(), nullable=False), - sa.Column('perm_remailer', sa.Boolean(), nullable=False), + sa.Column('perm_users', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('perm_checkpassword', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('perm_mail_aliases', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('perm_remailer', sa.Boolean(create_constraint=True), nullable=False), sa.ForeignKeyConstraint(['service_id'], ['service.id'], name=op.f('fk_api_client_service_id_service'), onupdate='CASCADE', ondelete='CASCADE'), sa.PrimaryKeyConstraint('id', name=op.f('pk_api_client')), sa.UniqueConstraint('auth_username', name=op.f('uq_api_client_auth_username')) @@ -71,9 +71,9 @@ def downgrade(): service = sa.Table('service', meta, sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('name', sa.String(length=255), nullable=False), - sa.Column('limit_access', sa.Boolean(), nullable=False), + sa.Column('limit_access', sa.Boolean(create_constraint=True), nullable=False), sa.Column('access_group_id', sa.Integer(), nullable=True), - sa.Column('use_remailer', sa.Boolean(), nullable=False), + sa.Column('use_remailer', sa.Boolean(create_constraint=True), nullable=False), sa.ForeignKeyConstraint(['access_group_id'], ['group.id'], name=op.f('fk_service_access_group_id_group'), onupdate='CASCADE', ondelete='SET NULL'), sa.PrimaryKeyConstraint('id', name=op.f('pk_service')), sa.UniqueConstraint('name', name=op.f('uq_service_name')) diff --git a/uffd/migrations/versions/878b25c4fae7_ldap_to_db.py b/uffd/migrations/versions/878b25c4fae7_ldap_to_db.py index 2249f75919e1bf6a605b7684707e46bf2fb6997d..d8d6313636778dbe7f2bb07629cebff1be8f5a63 100644 --- a/uffd/migrations/versions/878b25c4fae7_ldap_to_db.py +++ b/uffd/migrations/versions/878b25c4fae7_ldap_to_db.py @@ -205,7 +205,7 @@ def upgrade(): sa.Column('displayname', sa.String(length=128), nullable=False), sa.Column('mail', sa.String(length=128), nullable=False), sa.Column('pwhash', sa.String(length=256), nullable=True), - sa.Column('is_service_user', sa.Boolean(name=op.f('ck_user_is_service_user')), nullable=False), + sa.Column('is_service_user', sa.Boolean(create_constraint=True, name=op.f('ck_user_is_service_user')), nullable=False), sa.PrimaryKeyConstraint('id', name=op.f('pk_user')), sa.UniqueConstraint('loginname', name=op.f('uq_user_loginname')), sa.UniqueConstraint('unix_uid', name=op.f('uq_user_unix_uid')) @@ -337,10 +337,10 @@ def upgrade(): sa.Column('creator_id', sa.Integer(), nullable=True), sa.Column('creator_dn', sa.String(length=128), nullable=True), sa.Column('valid_until', sa.DateTime(), nullable=False), - sa.Column('single_use', sa.Boolean(name=op.f('ck_invite_single_use')), nullable=False), - sa.Column('allow_signup', sa.Boolean(name=op.f('ck_invite_allow_signup')), nullable=False), - sa.Column('used', sa.Boolean(name=op.f('ck_invite_used')), nullable=False), - sa.Column('disabled', sa.Boolean(name=op.f('ck_invite_disabled')), nullable=False), + sa.Column('single_use', sa.Boolean(create_constraint=True, name=op.f('ck_invite_single_use')), nullable=False), + sa.Column('allow_signup', sa.Boolean(create_constraint=True, name=op.f('ck_invite_allow_signup')), nullable=False), + sa.Column('used', sa.Boolean(create_constraint=True, name=op.f('ck_invite_used')), nullable=False), + sa.Column('disabled', sa.Boolean(create_constraint=True, name=op.f('ck_invite_disabled')), nullable=False), sa.ForeignKeyConstraint(['creator_id'], ['user.id'], name=op.f('fk_invite_creator_id_user'), onupdate='CASCADE'), sa.PrimaryKeyConstraint('id', name=op.f('pk_invite')), sa.UniqueConstraint('token', name=op.f('uq_invite_token')) @@ -373,7 +373,7 @@ def upgrade(): batch_op.create_foreign_key(batch_op.f('fk_mfa_method_user_id_user'), 'user', ['user_id'], ['id']) mfa_method = sa.Table('mfa_method', meta, sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('type', sa.Enum('RECOVERY_CODE', 'TOTP', 'WEBAUTHN', name='ck_mfa_method_type'), nullable=True), + sa.Column('type', sa.Enum('RECOVERY_CODE', 'TOTP', 'WEBAUTHN', create_constraint=True, name='ck_mfa_method_type'), nullable=True), sa.Column('created', sa.DateTime(), nullable=True), sa.Column('name', sa.String(length=128), nullable=True), sa.Column('user_id', sa.Integer(), nullable=True), @@ -390,7 +390,7 @@ def upgrade(): with op.batch_alter_table('mfa_method', copy_from=mfa_method) as batch_op: batch_op.alter_column('user_id', nullable=False, existing_type=sa.Integer()) batch_op.alter_column('created', existing_type=sa.DateTime(), nullable=False) - batch_op.alter_column('type', existing_type=sa.Enum('RECOVERY_CODE', 'TOTP', 'WEBAUTHN', name='ck_mfa_method_type'), nullable=False) + batch_op.alter_column('type', existing_type=sa.Enum('RECOVERY_CODE', 'TOTP', 'WEBAUTHN', create_constraint=True, name='ck_mfa_method_type'), nullable=False) batch_op.drop_constraint('fk_mfa_method_user_id_user', type_='foreignkey') batch_op.create_foreign_key(batch_op.f('fk_mfa_method_user_id_user'), 'user', ['user_id'], ['id'], onupdate='CASCADE', ondelete='CASCADE') batch_op.drop_column('dn') @@ -457,8 +457,8 @@ def upgrade(): sa.Column('description', sa.Text(), nullable=True), sa.Column('moderator_group_id', sa.Integer(), nullable=True), sa.Column('moderator_group_dn', sa.String(length=128), nullable=True), - sa.Column('locked', sa.Boolean(name=op.f('ck_role_locked')), nullable=False), - sa.Column('is_default', sa.Boolean(name=op.f('ck_role_is_default')), nullable=False), + sa.Column('locked', sa.Boolean(create_constraint=True, name=op.f('ck_role_locked')), nullable=False), + sa.Column('is_default', sa.Boolean(create_constraint=True, name=op.f('ck_role_is_default')), nullable=False), sa.PrimaryKeyConstraint('id', name=op.f('pk_role')), sa.UniqueConstraint('name', name=op.f('uq_role_name')) ) @@ -630,7 +630,7 @@ def downgrade(): sa.Column('displayname', sa.String(length=128), nullable=False), sa.Column('mail', sa.String(length=128), nullable=False), sa.Column('pwhash', sa.String(length=256), nullable=True), - sa.Column('is_service_user', sa.Boolean(name=op.f('ck_user_is_service_user')), nullable=False), + sa.Column('is_service_user', sa.Boolean(create_constraint=True, name=op.f('ck_user_is_service_user')), nullable=False), sa.PrimaryKeyConstraint('id', name=op.f('pk_user')), sa.UniqueConstraint('loginname', name=op.f('uq_user_loginname')), sa.UniqueConstraint('unix_uid', name=op.f('uq_user_unix_uid')) @@ -742,8 +742,8 @@ def downgrade(): sa.Column('description', sa.Text(), nullable=True), sa.Column('moderator_group_id', sa.Integer(), nullable=True), sa.Column('moderator_group_dn', sa.String(length=128), nullable=True), - sa.Column('locked', sa.Boolean(name=op.f('ck_role_locked')), nullable=False), - sa.Column('is_default', sa.Boolean(name=op.f('ck_role_is_default')), nullable=False), + sa.Column('locked', sa.Boolean(create_constraint=True, name=op.f('ck_role_locked')), nullable=False), + sa.Column('is_default', sa.Boolean(create_constraint=True, name=op.f('ck_role_is_default')), nullable=False), sa.ForeignKeyConstraint(['moderator_group_id'], ['group.id'], name=op.f('fk_role_moderator_group_id_group'), onupdate='CASCADE', ondelete='SET NULL'), sa.PrimaryKeyConstraint('id', name=op.f('pk_role')), sa.UniqueConstraint('name', name=op.f('uq_role_name')) @@ -813,7 +813,7 @@ def downgrade(): batch_op.add_column(sa.Column('dn', sa.String(length=128), nullable=True)) mfa_method = sa.Table('mfa_method', meta, sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('type', sa.Enum('RECOVERY_CODE', 'TOTP', 'WEBAUTHN', name='ck_mfa_method_type'), nullable=False), + sa.Column('type', sa.Enum('RECOVERY_CODE', 'TOTP', 'WEBAUTHN', create_constraint=True, name='ck_mfa_method_type'), nullable=False), sa.Column('created', sa.DateTime(), nullable=False), sa.Column('name', sa.String(length=128), nullable=True), sa.Column('user_id', sa.Integer(), nullable=False), @@ -829,7 +829,7 @@ def downgrade(): op.execute(mfa_method.delete().where(mfa_method.c.dn==None)) with op.batch_alter_table('mfa_method', copy_from=mfa_method) as batch_op: batch_op.drop_constraint('fk_mfa_method_user_id_user', 'foreignkey') - batch_op.alter_column('type', existing_type=sa.Enum('RECOVERY_CODE', 'TOTP', 'WEBAUTHN', name='ck_mfa_method_type'), nullable=True) + batch_op.alter_column('type', existing_type=sa.Enum('RECOVERY_CODE', 'TOTP', 'WEBAUTHN', create_constraint=True, name='ck_mfa_method_type'), nullable=True) batch_op.alter_column('created', existing_type=sa.DateTime(), nullable=True) batch_op.drop_column('user_id') @@ -861,10 +861,10 @@ def downgrade(): sa.Column('creator_id', sa.Integer(), nullable=True), sa.Column('creator_dn', sa.String(length=128), nullable=True), sa.Column('valid_until', sa.DateTime(), nullable=False), - sa.Column('single_use', sa.Boolean(name=op.f('ck_invite_single_use')), nullable=False), - sa.Column('allow_signup', sa.Boolean(name=op.f('ck_invite_allow_signup')), nullable=False), - sa.Column('used', sa.Boolean(name=op.f('ck_invite_used')), nullable=False), - sa.Column('disabled', sa.Boolean(name=op.f('ck_invite_disabled')), nullable=False), + sa.Column('single_use', sa.Boolean(create_constraint=True, name=op.f('ck_invite_single_use')), nullable=False), + sa.Column('allow_signup', sa.Boolean(create_constraint=True, name=op.f('ck_invite_allow_signup')), nullable=False), + sa.Column('used', sa.Boolean(create_constraint=True, name=op.f('ck_invite_used')), nullable=False), + sa.Column('disabled', sa.Boolean(create_constraint=True, name=op.f('ck_invite_disabled')), nullable=False), sa.ForeignKeyConstraint(['creator_id'], ['user.id'], name=op.f('fk_invite_creator_id_user')), sa.PrimaryKeyConstraint('id', name=op.f('pk_invite')), sa.UniqueConstraint('token', name=op.f('uq_invite_token')) diff --git a/uffd/migrations/versions/a29870f95175_initial_migration.py b/uffd/migrations/versions/a29870f95175_initial_migration.py index 828fee28a5a4229cf83cde69ee9e5939eaba9bc8..156d03c148ac8a45b8eb8bbd3b10b9ed0eebab12 100644 --- a/uffd/migrations/versions/a29870f95175_initial_migration.py +++ b/uffd/migrations/versions/a29870f95175_initial_migration.py @@ -21,10 +21,10 @@ def upgrade(): sa.Column('token', sa.String(length=128), nullable=False), sa.Column('created', sa.DateTime(), nullable=False), sa.Column('valid_until', sa.DateTime(), nullable=False), - sa.Column('single_use', sa.Boolean(), nullable=False), - sa.Column('allow_signup', sa.Boolean(), nullable=False), - sa.Column('used', sa.Boolean(), nullable=False), - sa.Column('disabled', sa.Boolean(), nullable=False), + sa.Column('single_use', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('allow_signup', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('used', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('disabled', sa.Boolean(create_constraint=True), nullable=False), sa.PrimaryKeyConstraint('token') ) op.create_table('mailToken', @@ -36,7 +36,7 @@ def upgrade(): ) op.create_table('mfa_method', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('type', sa.Enum('RECOVERY_CODE', 'TOTP', 'WEBAUTHN', name='mfatype'), nullable=True), + sa.Column('type', sa.Enum('RECOVERY_CODE', 'TOTP', 'WEBAUTHN', create_constraint=True, name='mfatype'), nullable=True), sa.Column('created', sa.DateTime(), nullable=True), sa.Column('name', sa.String(length=128), nullable=True), sa.Column('dn', sa.String(length=128), nullable=True), diff --git a/uffd/migrations/versions/a594d3b3e05b_added_role_locked.py b/uffd/migrations/versions/a594d3b3e05b_added_role_locked.py index 5ca1b89a97010bdfb11c51f35410d9281187e3a8..18f54212fef06a495ebe5558dc7b4e95c9381cb6 100644 --- a/uffd/migrations/versions/a594d3b3e05b_added_role_locked.py +++ b/uffd/migrations/versions/a594d3b3e05b_added_role_locked.py @@ -16,8 +16,20 @@ depends_on = None def upgrade(): with op.batch_alter_table('role', schema=None) as batch_op: - batch_op.add_column(sa.Column('locked', sa.Boolean(name=op.f('ck_role_locked')), nullable=False, default=False)) + batch_op.add_column(sa.Column('locked', sa.Boolean(create_constraint=True, name=op.f('ck_role_locked')), nullable=False, default=False)) def downgrade(): - with op.batch_alter_table('role', schema=None) as batch_op: + meta = sa.MetaData(bind=op.get_bind()) + table = sa.Table('role', meta, + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('name', sa.String(length=32), nullable=True), + sa.Column('description', sa.Text(), nullable=True), + sa.Column('moderator_group_dn', sa.String(length=128), nullable=True), + sa.Column('locked', sa.Boolean(create_constraint=False), nullable=False), + sa.CheckConstraint('locked IN (0, 1)', name=op.f('ck_role_locked')), + sa.PrimaryKeyConstraint('id', name=op.f('pk_role')), + sa.UniqueConstraint('name', name=op.f('uq_role_name')) + ) + with op.batch_alter_table('role', copy_from=table) as batch_op: + batch_op.drop_constraint(op.f('ck_role_locked'), 'check') batch_op.drop_column('locked') diff --git a/uffd/migrations/versions/a60ce68b9214_fix_not_null_on_role_groups_group_id.py b/uffd/migrations/versions/a60ce68b9214_fix_not_null_on_role_groups_group_id.py index 3f97f8c113a8ca7f8d586a7f6f9562e3df9dcf1f..d131db68e34ddc35bd3d77928ae07d5bdce6ba1a 100644 --- a/uffd/migrations/versions/a60ce68b9214_fix_not_null_on_role_groups_group_id.py +++ b/uffd/migrations/versions/a60ce68b9214_fix_not_null_on_role_groups_group_id.py @@ -22,7 +22,7 @@ def upgrade(): role_groups = sa.Table('role_groups', meta, sa.Column('role_id', sa.Integer(), nullable=False), sa.Column('group_id', sa.Integer(), nullable=True), - sa.Column('requires_mfa', sa.Boolean(), nullable=False), + sa.Column('requires_mfa', sa.Boolean(create_constraint=True), nullable=False), sa.ForeignKeyConstraint(['group_id'], ['group.id'], name=op.f('fk_role_groups_group_id_group'), onupdate='CASCADE', ondelete='CASCADE'), sa.ForeignKeyConstraint(['role_id'], ['role.id'], name=op.f('fk_role_groups_role_id_role'), onupdate='CASCADE', ondelete='CASCADE'), sa.PrimaryKeyConstraint('role_id', 'group_id', name=op.f('pk_role_groups')) @@ -35,7 +35,7 @@ def downgrade(): role_groups = sa.Table('role_groups', meta, sa.Column('role_id', sa.Integer(), nullable=False), sa.Column('group_id', sa.Integer(), nullable=False), - sa.Column('requires_mfa', sa.Boolean(), nullable=False), + sa.Column('requires_mfa', sa.Boolean(create_constraint=True), nullable=False), sa.ForeignKeyConstraint(['group_id'], ['group.id'], name=op.f('fk_role_groups_group_id_group'), onupdate='CASCADE', ondelete='CASCADE'), sa.ForeignKeyConstraint(['role_id'], ['role.id'], name=op.f('fk_role_groups_role_id_role'), onupdate='CASCADE', ondelete='CASCADE'), sa.PrimaryKeyConstraint('role_id', 'group_id', name=op.f('pk_role_groups')) diff --git a/uffd/migrations/versions/a8c6b6e91c28_device_login.py b/uffd/migrations/versions/a8c6b6e91c28_device_login.py index efdbc3018b5980a588c5bf490f18f77ebeb82cde..e4b3a3370d02cb6189859b7dc1f04786a55adb4f 100644 --- a/uffd/migrations/versions/a8c6b6e91c28_device_login.py +++ b/uffd/migrations/versions/a8c6b6e91c28_device_login.py @@ -17,7 +17,7 @@ depends_on = None def upgrade(): op.create_table('device_login_initiation', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('type', sa.Enum('OAUTH2', name='devicelogintype'), nullable=False), + sa.Column('type', sa.Enum('OAUTH2', create_constraint=True, name='devicelogintype'), nullable=False), sa.Column('code0', sa.String(length=32), nullable=False), sa.Column('code1', sa.String(length=32), nullable=False), sa.Column('secret', sa.String(length=128), nullable=False), diff --git a/uffd/migrations/versions/aeb07202a6c8_locking_and_new_id_allocation.py b/uffd/migrations/versions/aeb07202a6c8_locking_and_new_id_allocation.py index 204cad29b81fc2843d31fd41f6d96eb58517e3ec..69fc5e1dcbc3332a6ba03e92d2ba6f15de97520e 100644 --- a/uffd/migrations/versions/aeb07202a6c8_locking_and_new_id_allocation.py +++ b/uffd/migrations/versions/aeb07202a6c8_locking_and_new_id_allocation.py @@ -26,7 +26,7 @@ def upgrade(): sa.Column('primary_email_id', sa.Integer(), nullable=False), sa.Column('recovery_email_id', sa.Integer(), nullable=True), sa.Column('pwhash', sa.Text(), nullable=True), - sa.Column('is_service_user', sa.Boolean(), nullable=False), + sa.Column('is_service_user', sa.Boolean(create_constraint=True), nullable=False), sa.ForeignKeyConstraint(['primary_email_id'], ['user_email.id'], name=op.f('fk_user_primary_email_id_user_email'), onupdate='CASCADE'), sa.ForeignKeyConstraint(['recovery_email_id'], ['user_email.id'], name=op.f('fk_user_recovery_email_id_user_email'), onupdate='CASCADE', ondelete='SET NULL'), sa.PrimaryKeyConstraint('id', name=op.f('pk_user')), @@ -137,7 +137,7 @@ def downgrade(): sa.Column('primary_email_id', sa.Integer(), nullable=False), sa.Column('recovery_email_id', sa.Integer(), nullable=True), sa.Column('pwhash', sa.Text(), nullable=True), - sa.Column('is_service_user', sa.Boolean(), nullable=False), + sa.Column('is_service_user', sa.Boolean(create_constraint=True), nullable=False), sa.ForeignKeyConstraint(['primary_email_id'], ['user_email.id'], name=op.f('fk_user_primary_email_id_user_email'), onupdate='CASCADE'), sa.ForeignKeyConstraint(['recovery_email_id'], ['user_email.id'], name=op.f('fk_user_recovery_email_id_user_email'), onupdate='CASCADE', ondelete='SET NULL'), sa.ForeignKeyConstraint(['unix_uid'], ['uid_allocation.id'], name=op.f('fk_user_unix_uid_uid_allocation')), diff --git a/uffd/migrations/versions/af07cea65391_unified_password_hashing_for_user_and_signup.py b/uffd/migrations/versions/af07cea65391_unified_password_hashing_for_user_and_signup.py index 58fb2f48533b561b2f8f752d4dedb7bdc974400b..55bbf485b52e92e25522d2f3c1caa4b82797cf95 100644 --- a/uffd/migrations/versions/af07cea65391_unified_password_hashing_for_user_and_signup.py +++ b/uffd/migrations/versions/af07cea65391_unified_password_hashing_for_user_and_signup.py @@ -37,7 +37,7 @@ def upgrade(): sa.Column('displayname', sa.String(length=128), nullable=False), sa.Column('mail', sa.String(length=128), nullable=False), sa.Column('pwhash', sa.String(length=256), nullable=True), - sa.Column('is_service_user', sa.Boolean(), nullable=False), + sa.Column('is_service_user', sa.Boolean(create_constraint=True), nullable=False), sa.PrimaryKeyConstraint('id', name=op.f('pk_user')), sa.UniqueConstraint('loginname', name=op.f('uq_user_loginname')), sa.UniqueConstraint('unix_uid', name=op.f('uq_user_unix_uid')) @@ -71,7 +71,7 @@ def downgrade(): sa.Column('displayname', sa.String(length=128), nullable=False), sa.Column('mail', sa.String(length=128), nullable=False), sa.Column('pwhash', sa.Text(), nullable=True), - sa.Column('is_service_user', sa.Boolean(), nullable=False), + sa.Column('is_service_user', sa.Boolean(create_constraint=True), nullable=False), sa.PrimaryKeyConstraint('id', name=op.f('pk_user')), sa.UniqueConstraint('loginname', name=op.f('uq_user_loginname')), sa.UniqueConstraint('unix_uid', name=op.f('uq_user_unix_uid')) diff --git a/uffd/migrations/versions/aff5f350dcdf_added_role_is_default.py b/uffd/migrations/versions/aff5f350dcdf_added_role_is_default.py index b903fbd7078d2bedc91c9ffe3adb99de1f98583e..909b15d0cf0e1bb24030268f4d8d05367a469d98 100644 --- a/uffd/migrations/versions/aff5f350dcdf_added_role_is_default.py +++ b/uffd/migrations/versions/aff5f350dcdf_added_role_is_default.py @@ -16,8 +16,22 @@ depends_on = None def upgrade(): with op.batch_alter_table('role', schema=None) as batch_op: - batch_op.add_column(sa.Column('is_default', sa.Boolean(name=op.f('ck_role_is_default')), nullable=False, default=False)) + batch_op.add_column(sa.Column('is_default', sa.Boolean(create_constraint=True, name=op.f('ck_role_is_default')), nullable=False, default=False)) def downgrade(): - with op.batch_alter_table('role', schema=None) as batch_op: + meta = sa.MetaData(bind=op.get_bind()) + table = sa.Table('role', meta, + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('name', sa.String(length=32), nullable=True), + sa.Column('description', sa.Text(), nullable=True), + sa.Column('moderator_group_dn', sa.String(length=128), nullable=True), + sa.Column('locked', sa.Boolean(create_constraint=False), nullable=False), + sa.Column('is_default', sa.Boolean(create_constraint=False), nullable=False), + sa.CheckConstraint('locked IN (0, 1)', name=op.f('ck_role_locked')), + sa.CheckConstraint('is_default IN (0, 1)', name=op.f('ck_role_is_default')), + sa.PrimaryKeyConstraint('id', name=op.f('pk_role')), + sa.UniqueConstraint('name', name=op.f('uq_role_name')) + ) + with op.batch_alter_table('role', copy_from=table) as batch_op: + batch_op.drop_constraint(op.f('ck_role_is_default'), 'check') batch_op.drop_column('is_default') diff --git a/uffd/migrations/versions/b273d7fdaa25_multiple_email_addresses.py b/uffd/migrations/versions/b273d7fdaa25_multiple_email_addresses.py index ca83799f275997ef41de980d802aece4aebf8a81..adb8e107be0e60d9a4d6d1059c8372855ed86f30 100644 --- a/uffd/migrations/versions/b273d7fdaa25_multiple_email_addresses.py +++ b/uffd/migrations/versions/b273d7fdaa25_multiple_email_addresses.py @@ -36,7 +36,7 @@ def upgrade(): sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('user_id', sa.Integer(), nullable=True), sa.Column('address', sa.String(length=128), nullable=False), - sa.Column('verified', sa.Boolean(), nullable=False), + sa.Column('verified', sa.Boolean(create_constraint=True), nullable=False), sa.Column('verification_legacy_id', sa.Integer(), nullable=True), sa.Column('verification_secret', sa.Text(), nullable=True), sa.Column('verification_expires', sa.DateTime(), nullable=True), @@ -50,7 +50,7 @@ def upgrade(): ) op.execute(user_email_table.insert().from_select( ['user_id', 'address', 'verified'], - sa.select([user_table.c.id, user_table.c.mail, sa.literal(True, sa.Boolean())]) + sa.select([user_table.c.id, user_table.c.mail, sa.literal(True, sa.Boolean(create_constraint=True))]) )) with op.batch_alter_table('user', schema=None) as batch_op: batch_op.add_column(sa.Column('primary_email_id', sa.Integer(), nullable=True)) @@ -67,7 +67,7 @@ def upgrade(): sa.Column('primary_email_id', sa.Integer(), nullable=True), sa.Column('recovery_email_id', sa.Integer(), nullable=True), sa.Column('pwhash', sa.Text(), nullable=True), - sa.Column('is_service_user', sa.Boolean(), nullable=False), + sa.Column('is_service_user', sa.Boolean(create_constraint=True), nullable=False), sa.ForeignKeyConstraint(['primary_email_id'], ['user_email.id'], name=op.f('fk_user_primary_email_id_user_email'), onupdate='CASCADE'), sa.ForeignKeyConstraint(['recovery_email_id'], ['user_email.id'], name=op.f('fk_user_recovery_email_id_user_email'), onupdate='CASCADE', ondelete='SET NULL'), sa.PrimaryKeyConstraint('id', name=op.f('pk_user')), @@ -110,7 +110,7 @@ def downgrade(): sa.Column('primary_email_id', sa.Integer(), nullable=False), sa.Column('recovery_email_id', sa.Integer(), nullable=True), sa.Column('pwhash', sa.Text(), nullable=True), - sa.Column('is_service_user', sa.Boolean(), nullable=False), + sa.Column('is_service_user', sa.Boolean(create_constraint=True), nullable=False), sa.ForeignKeyConstraint(['primary_email_id'], ['user_email.id'], name=op.f('fk_user_primary_email_id_user_email'), onupdate='CASCADE'), sa.ForeignKeyConstraint(['recovery_email_id'], ['user_email.id'], name=op.f('fk_user_recovery_email_id_user_email'), onupdate='CASCADE', ondelete='SET NULL'), sa.PrimaryKeyConstraint('id', name=op.f('pk_user')), diff --git a/uffd/migrations/versions/b8fbefca3675_added_api_permission_for_metrics.py b/uffd/migrations/versions/b8fbefca3675_added_api_permission_for_metrics.py index ca86b66a621d01fe35b67268cc5acb676cf375f3..326e8231a58d01614d27e0935786849582d2e042 100644 --- a/uffd/migrations/versions/b8fbefca3675_added_api_permission_for_metrics.py +++ b/uffd/migrations/versions/b8fbefca3675_added_api_permission_for_metrics.py @@ -20,16 +20,16 @@ def upgrade(): sa.Column('service_id', sa.Integer(), nullable=False), sa.Column('auth_username', sa.String(length=40), nullable=False), sa.Column('auth_password', sa.Text(), nullable=False), - sa.Column('perm_users', sa.Boolean(), nullable=False), - sa.Column('perm_checkpassword', sa.Boolean(), nullable=False), - sa.Column('perm_mail_aliases', sa.Boolean(), nullable=False), - sa.Column('perm_remailer', sa.Boolean(), nullable=False), + sa.Column('perm_users', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('perm_checkpassword', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('perm_mail_aliases', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('perm_remailer', sa.Boolean(create_constraint=True), nullable=False), sa.ForeignKeyConstraint(['service_id'], ['service.id'], name=op.f('fk_api_client_service_id_service'), onupdate='CASCADE', ondelete='CASCADE'), sa.PrimaryKeyConstraint('id', name=op.f('pk_api_client')), sa.UniqueConstraint('auth_username', name=op.f('uq_api_client_auth_username')) ) with op.batch_alter_table('api_client', copy_from=api_client) as batch_op: - batch_op.add_column(sa.Column('perm_metrics', sa.Boolean(), nullable=False, server_default=sa.false())) + batch_op.add_column(sa.Column('perm_metrics', sa.Boolean(create_constraint=True), nullable=False, server_default=sa.false())) def downgrade(): meta = sa.MetaData(bind=op.get_bind()) @@ -38,11 +38,11 @@ def downgrade(): sa.Column('service_id', sa.Integer(), nullable=False), sa.Column('auth_username', sa.String(length=40), nullable=False), sa.Column('auth_password', sa.Text(), nullable=False), - sa.Column('perm_users', sa.Boolean(), nullable=False), - sa.Column('perm_checkpassword', sa.Boolean(), nullable=False), - sa.Column('perm_mail_aliases', sa.Boolean(), nullable=False), - sa.Column('perm_remailer', sa.Boolean(), nullable=False), - sa.Column('perm_metrics', sa.Boolean(), nullable=False, server_default=sa.false()), + sa.Column('perm_users', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('perm_checkpassword', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('perm_mail_aliases', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('perm_remailer', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('perm_metrics', sa.Boolean(create_constraint=True), nullable=False, server_default=sa.false()), sa.ForeignKeyConstraint(['service_id'], ['service.id'], name=op.f('fk_api_client_service_id_service'), onupdate='CASCADE', ondelete='CASCADE'), sa.PrimaryKeyConstraint('id', name=op.f('pk_api_client')), sa.UniqueConstraint('auth_username', name=op.f('uq_api_client_auth_username')) diff --git a/uffd/migrations/versions/b9d3f7dac9db_move_api_and_oauth2_clients_to_db.py b/uffd/migrations/versions/b9d3f7dac9db_move_api_and_oauth2_clients_to_db.py index 34c1a4fdff31cf76c4e9e7e17cb54ee662add8c5..0fd1230c2e8d0e98be8edf5121bfe5514c4c85a7 100644 --- a/uffd/migrations/versions/b9d3f7dac9db_move_api_and_oauth2_clients_to_db.py +++ b/uffd/migrations/versions/b9d3f7dac9db_move_api_and_oauth2_clients_to_db.py @@ -99,7 +99,7 @@ def upgrade(): service_table = op.create_table('service', sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('name', sa.String(length=255), nullable=False), - sa.Column('limit_access', sa.Boolean(), nullable=False), + sa.Column('limit_access', sa.Boolean(create_constraint=True), nullable=False), sa.Column('access_group_id', sa.Integer(), nullable=True), sa.ForeignKeyConstraint(['access_group_id'], ['group.id'], name=op.f('fk_service_access_group_id_group'), onupdate='CASCADE', ondelete='SET NULL'), sa.PrimaryKeyConstraint('id', name=op.f('pk_service')), @@ -118,9 +118,9 @@ def upgrade(): sa.Column('service_id', sa.Integer(), nullable=False), sa.Column('auth_username', sa.String(length=40), nullable=False), sa.Column('auth_password', sa.Text(), nullable=False), - sa.Column('perm_users', sa.Boolean(), nullable=False), - sa.Column('perm_checkpassword', sa.Boolean(), nullable=False), - sa.Column('perm_mail_aliases', sa.Boolean(), nullable=False), + sa.Column('perm_users', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('perm_checkpassword', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('perm_mail_aliases', sa.Boolean(create_constraint=True), nullable=False), sa.ForeignKeyConstraint(['service_id'], ['service.id'], name=op.f('fk_api_client_service_id_service'), onupdate='CASCADE', ondelete='CASCADE'), sa.PrimaryKeyConstraint('id', name=op.f('pk_api_client')), sa.UniqueConstraint('auth_username', name=op.f('uq_api_client_auth_username')) @@ -164,7 +164,7 @@ def upgrade(): batch_op.create_foreign_key(batch_op.f('fk_device_login_initiation_oauth2_client_db_id_oauth2client'), 'oauth2client', ['oauth2_client_db_id'], ['db_id'], onupdate='CASCADE', ondelete='CASCADE') device_login_initiation_table = sa.Table('device_login_initiation', meta, sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('type', sa.Enum('OAUTH2', name='devicelogintype'), nullable=False), + sa.Column('type', sa.Enum('OAUTH2', create_constraint=True, name='devicelogintype'), nullable=False), sa.Column('code0', sa.String(length=32), nullable=False), sa.Column('code1', sa.String(length=32), nullable=False), sa.Column('secret', sa.String(length=128), nullable=False), @@ -293,7 +293,7 @@ def downgrade(): batch_op.add_column(sa.Column('oauth2_client_id', sa.VARCHAR(length=40), nullable=True)) device_login_initiation_table = sa.Table('device_login_initiation', meta, sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('type', sa.Enum('OAUTH2', name='devicelogintype'), nullable=False), + sa.Column('type', sa.Enum('OAUTH2', create_constraint=True, name='devicelogintype'), nullable=False), sa.Column('code0', sa.String(length=32), nullable=False), sa.Column('code1', sa.String(length=32), nullable=False), sa.Column('secret', sa.String(length=128), nullable=False), diff --git a/uffd/migrations/versions/bad6fc529510_added_rolegroup_requires_mfa_and_cleanup.py b/uffd/migrations/versions/bad6fc529510_added_rolegroup_requires_mfa_and_cleanup.py index c97861859c4bd5d9c8f642f813672555c7d4df85..bd0dc72f410722492947cfee0da3c0636dac87aa 100644 --- a/uffd/migrations/versions/bad6fc529510_added_rolegroup_requires_mfa_and_cleanup.py +++ b/uffd/migrations/versions/bad6fc529510_added_rolegroup_requires_mfa_and_cleanup.py @@ -31,7 +31,7 @@ def upgrade(): batch_op.drop_column('id') batch_op.alter_column('dn', new_column_name='group_dn', nullable=False, existing_type=sa.String(128)) batch_op.alter_column('role_id', nullable=False, existing_type=sa.Integer()) - batch_op.add_column(sa.Column('requires_mfa', sa.Boolean(name=op.f('ck_role-group_requires_mfa')), nullable=False, default=False)) + batch_op.add_column(sa.Column('requires_mfa', sa.Boolean(create_constraint=True, name=op.f('ck_role-group_requires_mfa')), nullable=False, default=False)) batch_op.create_primary_key(batch_op.f('pk_role-group'), ['role_id', 'group_dn']) def downgrade(): @@ -39,7 +39,7 @@ def downgrade(): table = sa.Table('role-group', meta, sa.Column('role_id', sa.Integer(), nullable=False), sa.Column('group_dn', sa.String(128), nullable=False), - sa.Column('requires_mfa', sa.Boolean(name=op.f('ck_role-group_requires_mfa')), nullable=False, default=False), + sa.Column('requires_mfa', sa.Boolean(create_constraint=True, name=op.f('ck_role-group_requires_mfa')), nullable=False, default=False), sa.ForeignKeyConstraint(['role_id'], ['role.id'], name=op.f('fk_role-group_role_id_role')), sa.PrimaryKeyConstraint('role_id', 'group_dn', name=op.f('pk_role-group')) ) diff --git a/uffd/migrations/versions/cbca20cf64d9_constraint_name_fixes.py b/uffd/migrations/versions/cbca20cf64d9_constraint_name_fixes.py index 541e1dbf1f3d0a2edc980cb34aa83e909d4a0e16..db84513f5598e8122d49532f6ad685b09f7c0cee 100644 --- a/uffd/migrations/versions/cbca20cf64d9_constraint_name_fixes.py +++ b/uffd/migrations/versions/cbca20cf64d9_constraint_name_fixes.py @@ -80,10 +80,10 @@ def upgrade(): sa.Column('token', sa.String(length=128), nullable=False), sa.Column('created', sa.DateTime(), nullable=False), sa.Column('valid_until', sa.DateTime(), nullable=False), - sa.Column('single_use', sa.Boolean(name=op.f('ck_invite_single_use')), nullable=False), - sa.Column('allow_signup', sa.Boolean(name=op.f('ck_invite_allow_signup')), nullable=False), - sa.Column('used', sa.Boolean(name=op.f('ck_invite_used')), nullable=False), - sa.Column('disabled', sa.Boolean(name=op.f('ck_invite_disabled')), nullable=False), + sa.Column('single_use', sa.Boolean(create_constraint=True, name=op.f('ck_invite_single_use')), nullable=False), + sa.Column('allow_signup', sa.Boolean(create_constraint=True, name=op.f('ck_invite_allow_signup')), nullable=False), + sa.Column('used', sa.Boolean(create_constraint=True, name=op.f('ck_invite_used')), nullable=False), + sa.Column('disabled', sa.Boolean(create_constraint=True, name=op.f('ck_invite_disabled')), nullable=False), sa.PrimaryKeyConstraint('token', name=op.f('pk_invite')) ) with op.batch_alter_table(table.name, copy_from=table, recreate='always') as batch_op: @@ -99,7 +99,7 @@ def upgrade(): pass table = sa.Table('mfa_method', meta, sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('type', sa.Enum('RECOVERY_CODE', 'TOTP', 'WEBAUTHN', name='mfatype'), nullable=True), + sa.Column('type', sa.Enum('RECOVERY_CODE', 'TOTP', 'WEBAUTHN', create_constraint=True, name='mfatype'), nullable=True), sa.Column('created', sa.DateTime(), nullable=True), sa.Column('name', sa.String(length=128), nullable=True), sa.Column('dn', sa.String(length=128), nullable=True), diff --git a/uffd/migrations/versions/e13b733ec856_per_service_email_preferences.py b/uffd/migrations/versions/e13b733ec856_per_service_email_preferences.py index e7afe43e324c04dd0b56964734047c4d49337397..1652358f1d4dbf6a33ba1705beab4e71692ed5bc 100644 --- a/uffd/migrations/versions/e13b733ec856_per_service_email_preferences.py +++ b/uffd/migrations/versions/e13b733ec856_per_service_email_preferences.py @@ -15,7 +15,7 @@ depends_on = None def upgrade(): with op.batch_alter_table('service', schema=None) as batch_op: - batch_op.add_column(sa.Column('enable_email_preferences', sa.Boolean(), nullable=False, server_default=sa.false())) + batch_op.add_column(sa.Column('enable_email_preferences', sa.Boolean(create_constraint=True), nullable=False, server_default=sa.false())) with op.batch_alter_table('service_user', schema=None) as batch_op: batch_op.add_column(sa.Column('service_email_id', sa.Integer(), nullable=True)) batch_op.create_foreign_key(batch_op.f('fk_service_user_service_email_id_user_email'), 'user_email', ['service_email_id'], ['id'], onupdate='CASCADE', ondelete='SET NULL') @@ -23,10 +23,10 @@ def upgrade(): service = sa.Table('service', meta, sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), sa.Column('name', sa.String(length=255), nullable=False), - sa.Column('limit_access', sa.Boolean(), nullable=False), + sa.Column('limit_access', sa.Boolean(create_constraint=True), nullable=False), sa.Column('access_group_id', sa.Integer(), nullable=True), - sa.Column('use_remailer', sa.Boolean(), nullable=False), - sa.Column('enable_email_preferences', sa.Boolean(), nullable=False, server_default=sa.false()), + sa.Column('use_remailer', sa.Boolean(create_constraint=True), nullable=False), + sa.Column('enable_email_preferences', sa.Boolean(create_constraint=True), nullable=False, server_default=sa.false()), sa.ForeignKeyConstraint(['access_group_id'], ['group.id'], name=op.f('fk_service_access_group_id_group'), onupdate='CASCADE', ondelete='SET NULL'), sa.PrimaryKeyConstraint('id', name=op.f('pk_service')), sa.UniqueConstraint('name', name=op.f('uq_service_name')) diff --git a/uffd/migrations/versions/e249233e2a31_remailer_mode_overwrite.py b/uffd/migrations/versions/e249233e2a31_remailer_mode_overwrite.py index 10c617ee70e3f14d9be935cc4171724f36b5a666..12ebc6ce06cea2d2928804251e2210466d1c380a 100644 --- a/uffd/migrations/versions/e249233e2a31_remailer_mode_overwrite.py +++ b/uffd/migrations/versions/e249233e2a31_remailer_mode_overwrite.py @@ -26,14 +26,14 @@ def upgrade(): sa.PrimaryKeyConstraint('service_id', 'user_id', name=op.f('pk_service_user')) ) with op.batch_alter_table('service_user', copy_from=service_user) as batch_op: - batch_op.add_column(sa.Column('remailer_overwrite_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', name='remailermode'), nullable=True)) + batch_op.add_column(sa.Column('remailer_overwrite_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', create_constraint=True, name='remailermode'), nullable=True)) def downgrade(): meta = sa.MetaData(bind=op.get_bind()) service_user = sa.Table('service_user', meta, sa.Column('service_id', sa.Integer(), nullable=False), sa.Column('user_id', sa.Integer(), nullable=False), - sa.Column('remailer_overwrite_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', name='remailermode'), nullable=True), + sa.Column('remailer_overwrite_mode', sa.Enum('DISABLED', 'ENABLED_V1', 'ENABLED_V2', create_constraint=True, name='remailermode'), nullable=True), sa.Column('service_email_id', sa.Integer(), nullable=True), sa.ForeignKeyConstraint(['service_email_id'], ['user_email.id'], name=op.f('fk_service_user_service_email_id_user_email'), onupdate='CASCADE', ondelete='SET NULL'), sa.ForeignKeyConstraint(['service_id'], ['service.id'], name=op.f('fk_service_user_service_id_service'), onupdate='CASCADE', ondelete='CASCADE'), diff --git a/uffd/models/api.py b/uffd/models/api.py index c3dfd5e011ed9727663923cf6f4cf9ca44d17fbd..d57e36d34df82042aebe59c8533bb255d1c9e2e0 100644 --- a/uffd/models/api.py +++ b/uffd/models/api.py @@ -14,11 +14,11 @@ class APIClient(db.Model): auth_password = PasswordHashAttribute('_auth_password', HighEntropyPasswordHash) # Permissions are defined by adding an attribute named "perm_NAME" - perm_users = Column(Boolean(), default=False, nullable=False) - perm_checkpassword = Column(Boolean(), default=False, nullable=False) - perm_mail_aliases = Column(Boolean(), default=False, nullable=False) - perm_remailer = Column(Boolean(), default=False, nullable=False) - perm_metrics = Column(Boolean(), default=False, nullable=False) + perm_users = Column(Boolean(create_constraint=True), default=False, nullable=False) + perm_checkpassword = Column(Boolean(create_constraint=True), default=False, nullable=False) + perm_mail_aliases = Column(Boolean(create_constraint=True), default=False, nullable=False) + perm_remailer = Column(Boolean(create_constraint=True), default=False, nullable=False) + perm_metrics = Column(Boolean(create_constraint=True), default=False, nullable=False) @classmethod def permission_exists(cls, name): diff --git a/uffd/models/invite.py b/uffd/models/invite.py index ef8acc36f7f377c2a814f76882088ab37c8f47aa..793ade40650b9374e087e1cadeaa0650d1165317 100644 --- a/uffd/models/invite.py +++ b/uffd/models/invite.py @@ -23,10 +23,10 @@ class Invite(db.Model): creator_id = Column(Integer(), ForeignKey('user.id', onupdate='CASCADE'), nullable=True) creator = relationship('User') valid_until = Column(DateTime, nullable=False) - single_use = Column(Boolean, default=True, nullable=False) - allow_signup = Column(Boolean, default=True, nullable=False) - used = Column(Boolean, default=False, nullable=False) - disabled = Column(Boolean, default=False, nullable=False) + single_use = Column(Boolean(create_constraint=True), default=True, nullable=False) + allow_signup = Column(Boolean(create_constraint=True), default=True, nullable=False) + used = Column(Boolean(create_constraint=True), default=False, nullable=False) + disabled = Column(Boolean(create_constraint=True), default=False, nullable=False) roles = relationship('Role', secondary=invite_roles) signups = relationship('InviteSignup', back_populates='invite', lazy=True, cascade='all, delete-orphan') grants = relationship('InviteGrant', back_populates='invite', lazy=True, cascade='all, delete-orphan') diff --git a/uffd/models/mfa.py b/uffd/models/mfa.py index e6b34eaa45f6c3859a31b16f8dad35cd9676a8f8..0951fb5eae6484f300d66c4b3e44d7cbd67f1bbe 100644 --- a/uffd/models/mfa.py +++ b/uffd/models/mfa.py @@ -9,8 +9,7 @@ import hashlib import base64 import urllib.parse # imports for recovery codes -import crypt - +import crypt # pylint: disable=deprecated-module from flask import request, current_app from sqlalchemy import Column, Integer, Enum, String, DateTime, Text, ForeignKey from sqlalchemy.orm import relationship, backref @@ -29,7 +28,7 @@ class MFAType(enum.Enum): class MFAMethod(db.Model): __tablename__ = 'mfa_method' id = Column(Integer(), primary_key=True, autoincrement=True) - type = Column(Enum(MFAType), nullable=False) + type = Column(Enum(MFAType, create_constraint=True), nullable=False) created = Column(DateTime(), nullable=False, default=datetime.datetime.utcnow) name = Column(String(128)) user_id = Column(Integer(), ForeignKey('user.id', onupdate='CASCADE', ondelete='CASCADE'), nullable=False) diff --git a/uffd/models/role.py b/uffd/models/role.py index 27111b8c0524a7c6b335989b5a91b24b9a439e2d..cc0c931dcae606d4bea1eaaa900849d8721b4d18 100644 --- a/uffd/models/role.py +++ b/uffd/models/role.py @@ -11,7 +11,7 @@ class RoleGroup(db.Model): role = relationship('Role', back_populates='groups') group_id = Column(Integer(), ForeignKey('group.id', onupdate='CASCADE', ondelete='CASCADE'), primary_key=True) group = relationship('Group') - requires_mfa = Column(Boolean(), default=False, nullable=False) + requires_mfa = Column(Boolean(create_constraint=True), default=False, nullable=False) # pylint: disable=E1101 role_members = db.Table('role_members', @@ -99,9 +99,9 @@ class Role(db.Model): # Roles that are managed externally (e.g. by Ansible) can be locked to # prevent accidental editing of name, moderator group, included roles # and groups as well as deletion in the web interface. - locked = Column(Boolean(), default=False, nullable=False) + locked = Column(Boolean(create_constraint=True), default=False, nullable=False) - is_default = Column(Boolean(), default=False, nullable=False) + is_default = Column(Boolean(create_constraint=True), default=False, nullable=False) @property def members_effective(self): diff --git a/uffd/models/service.py b/uffd/models/service.py index 1817954c7a0deab79adc915be6ac30151cea50e9..7aa928d429b50ddf4b7facd2c50c9cec8ff8e111 100644 --- a/uffd/models/service.py +++ b/uffd/models/service.py @@ -26,16 +26,16 @@ class Service(db.Model): # parameter meant no access restrictions. Representing this state by # setting access_group_id to NULL would lead to a bad/unintuitive ondelete # behaviour. - limit_access = Column(Boolean(), default=True, nullable=False) + limit_access = Column(Boolean(create_constraint=True), default=True, nullable=False) access_group_id = Column(Integer(), ForeignKey('group.id', onupdate='CASCADE', ondelete='SET NULL'), nullable=True) access_group = relationship('Group') oauth2_clients = relationship('OAuth2Client', back_populates='service', cascade='all, delete-orphan') api_clients = relationship('APIClient', back_populates='service', cascade='all, delete-orphan') - remailer_mode = Column(Enum(RemailerMode), default=RemailerMode.DISABLED, nullable=False) - enable_email_preferences = Column(Boolean(), default=False, nullable=False) - hide_deactivated_users = Column(Boolean(), default=False, nullable=False) + remailer_mode = Column(Enum(RemailerMode, create_constraint=True), default=RemailerMode.DISABLED, nullable=False) + enable_email_preferences = Column(Boolean(create_constraint=True), default=False, nullable=False) + hide_deactivated_users = Column(Boolean(create_constraint=True), default=False, nullable=False) class ServiceUser(db.Model): '''Service-related configuration and state for a user @@ -63,7 +63,7 @@ class ServiceUser(db.Model): def has_email_preferences(self): return self.has_access and self.service.enable_email_preferences - remailer_overwrite_mode = Column(Enum(RemailerMode), default=None, nullable=True) + remailer_overwrite_mode = Column(Enum(RemailerMode, create_constraint=True), default=None, nullable=True) @property def effective_remailer_mode(self): diff --git a/uffd/models/session.py b/uffd/models/session.py index a594e2314745eef2e1a25559222ffdf761870925..8e5f847fe22ae42879476ab6e312bfe6c87d7581 100644 --- a/uffd/models/session.py +++ b/uffd/models/session.py @@ -74,7 +74,7 @@ class DeviceLoginInitiation(db.Model): __tablename__ = 'device_login_initiation' id = Column(Integer(), primary_key=True, autoincrement=True) - type = Column(Enum(DeviceLoginType), nullable=False) + type = Column(Enum(DeviceLoginType, create_constraint=True), nullable=False) code0 = Column(String(32), unique=True, nullable=False, default=lambda: token_typeable(3)) code1 = Column(String(32), unique=True, nullable=False, default=lambda: token_typeable(3)) secret = Column(String(128), nullable=False, default=lambda: secrets.token_hex(64)) diff --git a/uffd/models/user.py b/uffd/models/user.py index 2a9339079f0c9b864e40fd214ea619323a83ee97..48bd4cd9ebcf2402a1e2585448790337880afe04 100644 --- a/uffd/models/user.py +++ b/uffd/models/user.py @@ -167,8 +167,8 @@ class User(db.Model): _password = Column('pwhash', Text(), nullable=True) password = PasswordHashAttribute('_password', LowEntropyPasswordHash) - is_service_user = Column(Boolean(), default=False, nullable=False) - is_deactivated = Column(Boolean(), default=False, nullable=False) + is_service_user = Column(Boolean(create_constraint=True), default=False, nullable=False) + is_deactivated = Column(Boolean(create_constraint=True), default=False, nullable=False) groups = relationship('Group', secondary='user_groups', back_populates='members') roles = relationship('Role', secondary='role_members', back_populates='members') @@ -279,7 +279,7 @@ class UserEmail(db.Model): return value # True or None/NULL (not False, see constraints below) - _verified = Column('verified', Boolean(), nullable=True) + _verified = Column('verified', Boolean(create_constraint=True), nullable=True) @hybrid_property def verified(self): @@ -302,7 +302,7 @@ class UserEmail(db.Model): # on a per-row basis. # True or None/NULL if disabled (not False, see constraints below) enable_strict_constraints = Column( - Boolean(), + Boolean(create_constraint=True), nullable=True, default=db.select([db.case([(FeatureFlag.unique_email_addresses.expr, True)], else_=None)]) ) diff --git a/uffd/password_hash.py b/uffd/password_hash.py index 78d0da474ef3af295830a65e1fa53d092b5cd050..e2909064699dc5bb118d7910e7fa75afacc6e7d1 100644 --- a/uffd/password_hash.py +++ b/uffd/password_hash.py @@ -1,7 +1,7 @@ import secrets import hashlib import base64 -from crypt import crypt +from crypt import crypt # pylint: disable=deprecated-module import argon2 def build_value(method_name, data):