From 0d870ee101980ac72fd3fe9538687ec789333ead Mon Sep 17 00:00:00 2001 From: Julian Rother <julian@cccv.de> Date: Sun, 22 Oct 2023 22:18:31 +0200 Subject: [PATCH] Debian Bookworm support - Add CI tests for Bookworm - Disable pylint deprecation warnings for crypt - Mitigate Flask changes that broke a few tests - Set create_constraint=True for Booleans/Enums to mitigate SQLAlchemy changes - Mitigate new Alembic CHECK constraint behaviour in batch mode --- .gitlab-ci.yml | 99 +++++++++++++++---- README.md | 4 +- tests/views/test_selfservice.py | 50 +++++----- .../versions/23293f32b503_deactivate_users.py | 28 +++--- .../versions/2b68f688bec1_remailer_v2.py | 26 ++--- .../468995a9c9ee_unique_email_addresses.py | 14 +-- .../versions/54b2413586fd_invite_pk_change.py | 16 +-- ...31c_remailer_setting_and_api_permission.py | 28 +++--- .../versions/878b25c4fae7_ldap_to_db.py | 36 +++---- .../a29870f95175_initial_migration.py | 10 +- .../a594d3b3e05b_added_role_locked.py | 16 ++- ...14_fix_not_null_on_role_groups_group_id.py | 4 +- .../versions/a8c6b6e91c28_device_login.py | 2 +- ...07202a6c8_locking_and_new_id_allocation.py | 4 +- ...ed_password_hashing_for_user_and_signup.py | 4 +- .../aff5f350dcdf_added_role_is_default.py | 18 +++- .../b273d7fdaa25_multiple_email_addresses.py | 8 +- ...ca3675_added_api_permission_for_metrics.py | 20 ++-- ...ac9db_move_api_and_oauth2_clients_to_db.py | 12 +-- ...dded_rolegroup_requires_mfa_and_cleanup.py | 4 +- .../cbca20cf64d9_constraint_name_fixes.py | 10 +- ...b733ec856_per_service_email_preferences.py | 8 +- .../e249233e2a31_remailer_mode_overwrite.py | 4 +- uffd/models/api.py | 10 +- uffd/models/invite.py | 8 +- uffd/models/mfa.py | 5 +- uffd/models/role.py | 6 +- uffd/models/service.py | 10 +- uffd/models/session.py | 2 +- uffd/models/user.py | 8 +- uffd/password_hash.py | 2 +- 31 files changed, 279 insertions(+), 197 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d70dc575..b11a4c23 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 f9e79f31..f1cd4f30 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 b5b20241..2396b77f 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 c25dbf6c..d6b9c9c2 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 bdf95ccc..d48c3af1 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 2c776195..b9bc7058 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 a59e2ca6..75d60783 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 8933610d..3e63561b 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 2249f759..d8d63136 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 828fee28..156d03c1 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 5ca1b89a..18f54212 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 3f97f8c1..d131db68 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 efdbc301..e4b3a337 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 204cad29..69fc5e1d 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 58fb2f48..55bbf485 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 b903fbd7..909b15d0 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 ca83799f..adb8e107 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 ca86b66a..326e8231 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 34c1a4fd..0fd1230c 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 c9786185..bd0dc72f 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 541e1dbf..db84513f 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 e7afe43e..1652358f 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 10c617ee..12ebc6ce 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 c3dfd5e0..d57e36d3 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 ef8acc36..793ade40 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 e6b34eaa..0951fb5e 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 27111b8c..cc0c931d 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 1817954c..7aa928d4 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 a594e231..8e5f847f 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 2a933907..48bd4cd9 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 78d0da47..e2909064 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): -- GitLab