diff --git a/Makefile b/Makefile index dd78ff0c8..fa7fd3fa5 100644 --- a/Makefile +++ b/Makefile @@ -71,4 +71,4 @@ migrations: ## generate migration file docker compose run ldap_server alembic revision --autogenerate migrate: ## upgrade db - docker compose run ldap_server alembic upgrade head + docker compose run ldap_server alembic upgrade head \ No newline at end of file diff --git a/app/alembic/env.py b/app/alembic/env.py index fc5acfcc7..6c08a67bd 100644 --- a/app/alembic/env.py +++ b/app/alembic/env.py @@ -4,10 +4,18 @@ from logging.config import fileConfig from alembic import context +from dishka import AsyncContainer, make_async_container from sqlalchemy import Connection, text -from sqlalchemy.ext.asyncio import create_async_engine +from sqlalchemy.ext.asyncio import AsyncConnection from config import Settings +from ioc import ( + HTTPProvider, + MainProvider, + MFACredsProvider, + MFAProvider, + MigrationProvider, +) from repo.pg.tables import metadata # this is the Alembic Config object, which provides @@ -22,7 +30,11 @@ target_metadata = metadata -def run_sync_migrations(connection: Connection, schema_name: str) -> None: +def run_sync_migrations( + connection: Connection, + schema_name: str, + dishka_container: AsyncContainer, +) -> None: """Run sync migrations.""" if schema_name != "public": connection.execute(text(f"SET search_path = {schema_name}, public;")) @@ -35,18 +47,20 @@ def run_sync_migrations(connection: Connection, schema_name: str) -> None: ) with context.begin_transaction(): - context.run_migrations() + context.run_migrations(container=dishka_container) -async def run_async_migrations(settings: Settings) -> None: +async def run_async_migrations( + settings: Settings, + dishka_container: AsyncContainer, +) -> None: """Run async migrations.""" - engine = create_async_engine(str(settings.POSTGRES_URI)) - - async with engine.connect() as connection: - await connection.run_sync( - run_sync_migrations, - schema_name=settings.TEST_POSTGRES_SCHEMA, - ) + connection = await dishka_container.get(AsyncConnection) + await connection.run_sync( + run_sync_migrations, + schema_name=settings.TEST_POSTGRES_SCHEMA, + dishka_container=dishka_container, + ) def run_migrations_online() -> None: @@ -60,11 +74,25 @@ def run_migrations_online() -> None: "app_settings", Settings.from_os(), ) + dishka_container = context.config.attributes.get("dishka_container", None) + if not dishka_container: + dishka_container = make_async_container( + MainProvider(), + MFACredsProvider(), + MFAProvider(), + HTTPProvider(), + MigrationProvider(), + context={Settings: settings}, + ) if conn is None: - asyncio.run(run_async_migrations(settings)) + asyncio.run(run_async_migrations(settings, dishka_container)) else: - run_sync_migrations(conn, schema_name=settings.TEST_POSTGRES_SCHEMA) + run_sync_migrations( + conn, + schema_name=settings.TEST_POSTGRES_SCHEMA, + dishka_container=dishka_container, + ) run_migrations_online() diff --git a/app/alembic/script.py.mako b/app/alembic/script.py.mako index cc49f4c6c..b2cdf925a 100644 --- a/app/alembic/script.py.mako +++ b/app/alembic/script.py.mako @@ -7,6 +7,7 @@ Create Date: ${create_date} """ from alembic import op import sqlalchemy as sa +from dishka import AsyncContainer ${imports if imports else ""} # revision identifiers, used by Alembic. @@ -16,11 +17,11 @@ branch_labels: None | list[str] = ${repr(branch_labels)} depends_on: None | list[str] = ${repr(depends_on)} -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: """Upgrade.""" ${upgrades if upgrades else "pass"} -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: """Downgrade.""" ${downgrades if downgrades else "pass"} diff --git a/app/alembic/versions/01f3f05a5b11_add_primary_group_id.py b/app/alembic/versions/01f3f05a5b11_add_primary_group_id.py index a3146a444..83a07695d 100644 --- a/app/alembic/versions/01f3f05a5b11_add_primary_group_id.py +++ b/app/alembic/versions/01f3f05a5b11_add_primary_group_id.py @@ -7,6 +7,7 @@ """ from alembic import op +from dishka import AsyncContainer, Scope from sqlalchemy import delete, exists, select from sqlalchemy.exc import DBAPIError, IntegrityError from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession @@ -18,9 +19,6 @@ AttributeValueValidator, ) from ldap_protocol.ldap_schema.entity_type_dao import EntityTypeDAO -from ldap_protocol.ldap_schema.object_class_dao import ObjectClassDAO -from ldap_protocol.roles.ace_dao import AccessControlEntryDAO -from ldap_protocol.roles.role_dao import RoleDAO from ldap_protocol.roles.role_use_case import RoleUseCase from ldap_protocol.utils.queries import ( create_group, @@ -37,27 +35,19 @@ depends_on: None = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: """Upgrade.""" - async def _add_domain_computers_group(connection: AsyncConnection) -> None: - session = AsyncSession(connection) - await session.begin() + async def _add_domain_computers_group(connection: AsyncConnection) -> None: # noqa: ARG001 + async with container(scope=Scope.REQUEST) as cnt: + session = await cnt.get(AsyncSession) + entity_type_dao = await cnt.get(EntityTypeDAO) + role_use_case = await cnt.get(RoleUseCase) base_dn_list = await get_base_directories(session) if not base_dn_list: return - object_class_dao = ObjectClassDAO(session) - entity_type_dao = EntityTypeDAO( - session, - object_class_dao=object_class_dao, - attribute_value_validator=AttributeValueValidator(), - ) - role_dao = RoleDAO(session) - ace_dao = AccessControlEntryDAO(session) - role_use_case = RoleUseCase(role_dao, ace_dao) - try: group_dir_query = select( exists(Directory) @@ -126,7 +116,6 @@ async def _add_domain_computers_group(connection: AsyncConnection) -> None: async def _add_primary_group_id(connection: AsyncConnection) -> None: session = AsyncSession(connection) - await session.begin() base_dn_list = await get_base_directories(session) if not base_dn_list: @@ -172,12 +161,10 @@ async def _add_primary_group_id(connection: AsyncConnection) -> None: except (IntegrityError, DBAPIError): pass - await session.close() - op.run_async(_add_primary_group_id) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" bind = op.get_bind() session = Session(bind=bind) @@ -186,8 +173,6 @@ async def _delete_domain_computers_group( connection: AsyncConnection, ) -> None: session = AsyncSession(connection) - await session.begin() - base_dn_list = await get_base_directories(session) if not base_dn_list: return diff --git a/app/alembic/versions/05ddc0bd562a_add_roles.py b/app/alembic/versions/05ddc0bd562a_add_roles.py index dd1205544..5a4f83a50 100644 --- a/app/alembic/versions/05ddc0bd562a_add_roles.py +++ b/app/alembic/versions/05ddc0bd562a_add_roles.py @@ -7,6 +7,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession @@ -24,7 +25,7 @@ depends_on: None = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" op.create_table( "Roles", @@ -184,7 +185,7 @@ async def _create_system_roles(connection: AsyncConnection) -> None: op.run_async(_create_system_roles) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" op.create_table( "AccessPolicies", diff --git a/app/alembic/versions/16a9fa2c1f1e_rename_readonly_group.py b/app/alembic/versions/16a9fa2c1f1e_rename_readonly_group.py index 06af9c227..0f9ba47e0 100644 --- a/app/alembic/versions/16a9fa2c1f1e_rename_readonly_group.py +++ b/app/alembic/versions/16a9fa2c1f1e_rename_readonly_group.py @@ -7,6 +7,7 @@ """ from alembic import op +from dishka import AsyncContainer from sqlalchemy import select, update from sqlalchemy.exc import DBAPIError, IntegrityError from sqlalchemy.orm import Session, selectinload @@ -21,7 +22,7 @@ depends_on: None | list[str] = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" bind = op.get_bind() session = Session(bind=bind) @@ -72,7 +73,7 @@ def upgrade() -> None: session.close() -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" bind = op.get_bind() session = Session(bind=bind) diff --git a/app/alembic/versions/196f0d327c6a_.py b/app/alembic/versions/196f0d327c6a_.py index 4faf37682..877b27be6 100644 --- a/app/alembic/versions/196f0d327c6a_.py +++ b/app/alembic/versions/196f0d327c6a_.py @@ -7,6 +7,7 @@ """ from alembic import op +from dishka import AsyncContainer # revision identifiers, used by Alembic. revision = "196f0d327c6a" @@ -15,7 +16,7 @@ depends_on: None | str = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" op.drop_constraint( "AccessPolicyMemberships_policy_id_fkey", @@ -201,7 +202,7 @@ def upgrade() -> None: ) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" op.drop_constraint( "PolicyMemberships_policy_id_fkey", diff --git a/app/alembic/versions/275222846605_initial_ldap_schema.py b/app/alembic/versions/275222846605_initial_ldap_schema.py index 82957bf42..bbf8fe117 100644 --- a/app/alembic/versions/275222846605_initial_ldap_schema.py +++ b/app/alembic/versions/275222846605_initial_ldap_schema.py @@ -10,6 +10,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer, Scope from ldap3.protocol.schemas.ad2012R2 import ad_2012_r2_schema from sqlalchemy import delete, or_ from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession @@ -36,7 +37,7 @@ @temporary_stub_entity_type_name -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: """Upgrade.""" bind = op.get_bind() session = Session(bind=bind) @@ -371,8 +372,9 @@ async def _modify_object_classes(connection: AsyncConnection) -> None: session = AsyncSession(bind=connection) await session.begin() - at_dao = AttributeTypeDAO(session) - oc_dao = ObjectClassDAO(session) + async with container(scope=Scope.REQUEST) as cnt: + at_dao = await cnt.get(AttributeTypeDAO) + oc_dao = await cnt.get(ObjectClassDAO) for oc_name, at_names in ( ("user", ["nsAccountLock", "shadowExpire"]), @@ -393,7 +395,7 @@ async def _modify_object_classes(connection: AsyncConnection) -> None: session.commit() -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" op.drop_index( "idx_object_classes_name_gin_trgm", diff --git a/app/alembic/versions/35d1542d2505_add_entity_id.py b/app/alembic/versions/35d1542d2505_add_entity_id.py index 4a3d6009d..2e0c020bd 100644 --- a/app/alembic/versions/35d1542d2505_add_entity_id.py +++ b/app/alembic/versions/35d1542d2505_add_entity_id.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer from sqlalchemy.sql import text # revision identifiers, used by Alembic. @@ -17,7 +18,7 @@ depends_on: None = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" op.add_column( "EntityTypes", @@ -87,7 +88,7 @@ def upgrade() -> None: op.drop_column("Directory", "entity_type_name") -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" op.add_column( "Directory", diff --git a/app/alembic/versions/4334e2e871a4_add_sessions_ttl.py b/app/alembic/versions/4334e2e871a4_add_sessions_ttl.py index e656fd296..583a11afc 100644 --- a/app/alembic/versions/4334e2e871a4_add_sessions_ttl.py +++ b/app/alembic/versions/4334e2e871a4_add_sessions_ttl.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer # revision identifiers, used by Alembic. revision = "4334e2e871a4" @@ -16,7 +17,7 @@ depends_on: None | str = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" op.add_column( "Policies", @@ -38,7 +39,7 @@ def upgrade() -> None: ) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" op.drop_column("Policies", "http_session_ttl") op.drop_column("Policies", "ldap_session_ttl") diff --git a/app/alembic/versions/4442d1d982a4_remove_krb_policy.py b/app/alembic/versions/4442d1d982a4_remove_krb_policy.py index 92d706192..919b0e104 100644 --- a/app/alembic/versions/4442d1d982a4_remove_krb_policy.py +++ b/app/alembic/versions/4442d1d982a4_remove_krb_policy.py @@ -7,6 +7,7 @@ """ from alembic import op +from dishka import AsyncContainer from sqlalchemy import delete from sqlalchemy.orm import Session @@ -21,7 +22,7 @@ @temporary_stub_entity_type_name -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" bind = op.get_bind() session = Session(bind=bind) @@ -29,5 +30,5 @@ def upgrade() -> None: session.execute(delete(Attribute).filter_by(name="krbpwdpolicyreference")) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: """Downgrade.""" diff --git a/app/alembic/versions/4798b12b97aa_dedicated_servers.py b/app/alembic/versions/4798b12b97aa_dedicated_servers.py index 460e36d20..ae625df78 100644 --- a/app/alembic/versions/4798b12b97aa_dedicated_servers.py +++ b/app/alembic/versions/4798b12b97aa_dedicated_servers.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer from loguru import logger from sqlalchemy.orm import Session @@ -21,7 +22,7 @@ depends_on: None | str = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" op.create_table( "DedicatedServer", @@ -88,7 +89,7 @@ def upgrade() -> None: session.commit() -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" bind = op.get_bind() session = Session(bind=bind) diff --git a/app/alembic/versions/4e8772277cfe_add_web_permissions.py b/app/alembic/versions/4e8772277cfe_add_web_permissions.py index 437bcea4f..5381ad7e7 100644 --- a/app/alembic/versions/4e8772277cfe_add_web_permissions.py +++ b/app/alembic/versions/4e8772277cfe_add_web_permissions.py @@ -7,6 +7,7 @@ """ from alembic import op +from dishka import AsyncContainer from sqlalchemy import Column, select, text from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession @@ -21,7 +22,7 @@ depends_on: None | list[str] = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" async def _add_api_permissions(connection: AsyncConnection) -> None: @@ -48,6 +49,6 @@ async def _add_api_permissions(connection: AsyncConnection) -> None: op.run_async(_add_api_permissions) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" op.drop_column("Roles", "permissions") diff --git a/app/alembic/versions/56082d7ac0d4_remove_old_templates.py b/app/alembic/versions/56082d7ac0d4_remove_old_templates.py index b2dd56e0c..655ab9bc6 100644 --- a/app/alembic/versions/56082d7ac0d4_remove_old_templates.py +++ b/app/alembic/versions/56082d7ac0d4_remove_old_templates.py @@ -6,6 +6,8 @@ """ +from dishka import AsyncContainer + # revision identifiers, used by Alembic. revision: None | str = "56082d7ac0d4" down_revision: None | str = "16a9fa2c1f1e" @@ -13,9 +15,9 @@ depends_on: None | list[str] = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: """Upgrade.""" -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: """Downgrade.""" diff --git a/app/alembic/versions/59e98bbd8ad8_.py b/app/alembic/versions/59e98bbd8ad8_.py index 810ca7178..aa8ba7145 100644 --- a/app/alembic/versions/59e98bbd8ad8_.py +++ b/app/alembic/versions/59e98bbd8ad8_.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer from sqlalchemy.dialects import postgresql # revision identifiers, used by Alembic. @@ -17,7 +18,7 @@ depends_on: None | str = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" op.create_table( "AccessPolicies", @@ -331,7 +332,7 @@ def upgrade() -> None: ) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" op.drop_index("ix_directory_objectGUID", table_name="Directory") op.drop_index(op.f("ix_Directory_path"), table_name="Directory") diff --git a/app/alembic/versions/6303f5c706ec_update_krbadmin_useraccountcontrol_.py b/app/alembic/versions/6303f5c706ec_update_krbadmin_useraccountcontrol_.py index f01dd0b00..d71ea9c05 100644 --- a/app/alembic/versions/6303f5c706ec_update_krbadmin_useraccountcontrol_.py +++ b/app/alembic/versions/6303f5c706ec_update_krbadmin_useraccountcontrol_.py @@ -7,6 +7,7 @@ """ from alembic import op +from dishka import AsyncContainer from sqlalchemy import select, update from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession from sqlalchemy.orm import joinedload @@ -23,7 +24,7 @@ depends_on: None | list[str] = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" async def _update_krbadmin_uac(connection: AsyncConnection) -> None: @@ -89,7 +90,7 @@ async def _change_uid_admin(connection: AsyncConnection) -> None: op.run_async(_change_uid_admin) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" async def _downgrade_krbadmin_uac(connection: AsyncConnection) -> None: diff --git a/app/alembic/versions/692ae64e0cc5_.py b/app/alembic/versions/692ae64e0cc5_.py index fdc40696b..0e6ab434c 100755 --- a/app/alembic/versions/692ae64e0cc5_.py +++ b/app/alembic/versions/692ae64e0cc5_.py @@ -7,6 +7,7 @@ """ from alembic import op +from dishka import AsyncContainer # revision identifiers, used by Alembic. revision = "692ae64e0cc5" @@ -15,7 +16,7 @@ depends_on: None | str = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" op.create_unique_constraint( "group_policy_uc", @@ -24,7 +25,7 @@ def upgrade() -> None: ) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" op.drop_constraint( "group_policy_uc", diff --git a/app/alembic/versions/6f8fe2548893_fix_read_only.py b/app/alembic/versions/6f8fe2548893_fix_read_only.py index f190cb676..1717c0124 100644 --- a/app/alembic/versions/6f8fe2548893_fix_read_only.py +++ b/app/alembic/versions/6f8fe2548893_fix_read_only.py @@ -7,6 +7,7 @@ """ from alembic import op +from dishka import AsyncContainer from sqlalchemy import delete, select, update from sqlalchemy.orm import Session @@ -22,7 +23,7 @@ @temporary_stub_entity_type_name -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" bind = op.get_bind() session = Session(bind=bind) @@ -84,5 +85,5 @@ def upgrade() -> None: session.commit() -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: """Downgrade.""" diff --git a/app/alembic/versions/8164b4a9e1f1_add_ou_computers.py b/app/alembic/versions/8164b4a9e1f1_add_ou_computers.py index fc74bba3d..f53db528a 100644 --- a/app/alembic/versions/8164b4a9e1f1_add_ou_computers.py +++ b/app/alembic/versions/8164b4a9e1f1_add_ou_computers.py @@ -7,20 +7,13 @@ """ from alembic import op +from dishka import AsyncContainer, Scope from sqlalchemy import delete, exists, select from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession from entities import Directory -from ldap_protocol.ldap_schema.attribute_value_validator import ( - AttributeValueValidator, -) -from ldap_protocol.ldap_schema.entity_type_dao import EntityTypeDAO -from ldap_protocol.ldap_schema.object_class_dao import ObjectClassDAO -from ldap_protocol.roles.ace_dao import AccessControlEntryDAO -from ldap_protocol.roles.role_dao import RoleDAO from ldap_protocol.roles.role_use_case import RoleUseCase from ldap_protocol.utils.queries import get_base_directories -from password_utils import PasswordUtils from repo.pg.tables import queryable_attr as qa # revision identifiers, used by Alembic. @@ -38,26 +31,17 @@ } -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: """Upgrade.""" from ldap_protocol.auth.setup_gateway import SetupGateway async def _create_ou_computers(connection: AsyncConnection) -> None: session = AsyncSession(bind=connection) await session.begin() - object_class_dao = ObjectClassDAO(session) - attribute_value_validator = AttributeValueValidator() - entity_type_dao = EntityTypeDAO( - session, - object_class_dao, - attribute_value_validator=attribute_value_validator, - ) - setup_gateway = SetupGateway( - session, - PasswordUtils(), - entity_type_dao, - attribute_value_validator=attribute_value_validator, - ) + + async with container(scope=Scope.REQUEST) as cnt: + setup_gateway = await cnt.get(SetupGateway) + role_use_case = await cnt.get(RoleUseCase) base_directories = await get_base_directories(session) if not base_directories: @@ -86,9 +70,6 @@ async def _create_ou_computers(connection: AsyncConnection) -> None: if not ou_computers_dir: raise Exception("Directory 'ou=computers' not found.") - role_dao = RoleDAO(session) - ace_dao = AccessControlEntryDAO(session) - role_use_case = RoleUseCase(role_dao, ace_dao) await role_use_case.inherit_parent_aces( parent_directory=domain_dir, directory=ou_computers_dir, @@ -99,7 +80,7 @@ async def _create_ou_computers(connection: AsyncConnection) -> None: op.run_async(_create_ou_computers) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" async def _delete_ou_computers(connection: AsyncConnection) -> None: diff --git a/app/alembic/versions/8c2bd40dd809_add_protocols_attr.py b/app/alembic/versions/8c2bd40dd809_add_protocols_attr.py index 8d83c9170..b18a512ea 100644 --- a/app/alembic/versions/8c2bd40dd809_add_protocols_attr.py +++ b/app/alembic/versions/8c2bd40dd809_add_protocols_attr.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer # revision identifiers, used by Alembic. revision = "8c2bd40dd809" @@ -16,7 +17,7 @@ depends_on: None = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" for protocol_field in ("is_http", "is_ldap", "is_kerberos"): op.add_column( @@ -30,7 +31,7 @@ def upgrade() -> None: ) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" for protocol_field in ("is_http", "is_ldap", "is_kerberos"): op.drop_column("Policies", protocol_field) diff --git a/app/alembic/versions/93ba193c6a53_add_hash_index_on_dir_path.py b/app/alembic/versions/93ba193c6a53_add_hash_index_on_dir_path.py index 37baac07c..5610e4661 100644 --- a/app/alembic/versions/93ba193c6a53_add_hash_index_on_dir_path.py +++ b/app/alembic/versions/93ba193c6a53_add_hash_index_on_dir_path.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer # revision identifiers, used by Alembic. revision: None | str = "93ba193c6a53" @@ -16,7 +17,7 @@ depends_on: None | list[str] = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" op.execute( sa.text( @@ -26,6 +27,6 @@ def upgrade() -> None: ) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" op.execute(sa.text("DROP INDEX idx_directory_path_hash")) diff --git a/app/alembic/versions/a7971f00ba4d_index_single_level.py b/app/alembic/versions/a7971f00ba4d_index_single_level.py index 611594085..0a147ea98 100644 --- a/app/alembic/versions/a7971f00ba4d_index_single_level.py +++ b/app/alembic/versions/a7971f00ba4d_index_single_level.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer # revision identifiers, used by Alembic. revision = "a7971f00ba4d" @@ -16,7 +17,7 @@ depends_on: None | str = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Create index for Directory depth field.""" op.execute( sa.text( @@ -89,7 +90,7 @@ def upgrade() -> None: ) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Remove indexes for Directory depth field and Attributes table.""" op.drop_index("idx_User_san_gin", "Users") op.drop_index("idx_User_upn_gin", "Users") diff --git a/app/alembic/versions/ad52bc16b87d_extend_password_policy_for_api.py b/app/alembic/versions/ad52bc16b87d_extend_password_policy_for_api.py index 5246e47c3..26b592787 100644 --- a/app/alembic/versions/ad52bc16b87d_extend_password_policy_for_api.py +++ b/app/alembic/versions/ad52bc16b87d_extend_password_policy_for_api.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer from sqlalchemy import update from sqlalchemy.orm import Session @@ -23,7 +24,7 @@ depends_on: None | list[str] = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" bind = op.get_bind() session = Session(bind=bind) @@ -101,7 +102,7 @@ def upgrade() -> None: ) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" op.drop_table("GroupPasswordPolicyMemberships") diff --git a/app/alembic/versions/ba78cef9700a_initial_entity_type.py b/app/alembic/versions/ba78cef9700a_initial_entity_type.py index e31c3958c..c4beb59d2 100644 --- a/app/alembic/versions/ba78cef9700a_initial_entity_type.py +++ b/app/alembic/versions/ba78cef9700a_initial_entity_type.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer, Scope from sqlalchemy import exists, or_, select from sqlalchemy.dialects import postgresql from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession @@ -15,13 +16,9 @@ from constants import ENTITY_TYPE_DATAS from entities import Attribute, Directory, User from extra.alembic_utils import temporary_stub_entity_type_name -from ldap_protocol.ldap_schema.attribute_value_validator import ( - AttributeValueValidator, -) from ldap_protocol.ldap_schema.dto import EntityTypeDTO from ldap_protocol.ldap_schema.entity_type_dao import EntityTypeDAO from ldap_protocol.ldap_schema.entity_type_use_case import EntityTypeUseCase -from ldap_protocol.ldap_schema.object_class_dao import ObjectClassDAO from ldap_protocol.utils.queries import get_base_directories from repo.pg.tables import queryable_attr as qa @@ -33,7 +30,7 @@ @temporary_stub_entity_type_name -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: """Upgrade database schema and data, creating Entity Types.""" op.create_table( "EntityTypes", @@ -106,16 +103,8 @@ async def _create_entity_types(connection: AsyncConnection) -> None: if not await get_base_directories(session): return - object_class_dao = ObjectClassDAO(session) - entity_type_dao = EntityTypeDAO( - session, - object_class_dao=object_class_dao, - attribute_value_validator=AttributeValueValidator(), - ) - entity_type_use_case = EntityTypeUseCase( - entity_type_dao, - object_class_dao, - ) + async with container(scope=Scope.REQUEST) as cnt: + entity_type_use_case = await cnt.get(EntityTypeUseCase) for entity_type_data in ENTITY_TYPE_DATAS: await entity_type_use_case.create( @@ -175,12 +164,8 @@ async def _attach_entity_type_to_directories( if not await get_base_directories(session): return - object_class_dao = ObjectClassDAO(session) - entity_type_dao = EntityTypeDAO( - session, - object_class_dao=object_class_dao, - attribute_value_validator=AttributeValueValidator(), - ) + async with container(scope=Scope.REQUEST) as cnt: + entity_type_dao = await cnt.get(EntityTypeDAO) await entity_type_dao.attach_entity_type_to_directories() @@ -192,7 +177,7 @@ async def _attach_entity_type_to_directories( op.drop_column("EntityTypes", "id") -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade database schema and data back to the previous state.""" op.drop_index( "idx_entity_types_name_gin_trgm", diff --git a/app/alembic/versions/bf435bbd95ff_add_rdn_attr_name.py b/app/alembic/versions/bf435bbd95ff_add_rdn_attr_name.py index c0a1342f9..3ba82ea7d 100644 --- a/app/alembic/versions/bf435bbd95ff_add_rdn_attr_name.py +++ b/app/alembic/versions/bf435bbd95ff_add_rdn_attr_name.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer from sqlalchemy.orm import Session from entities import Attribute, Directory @@ -22,7 +23,7 @@ @temporary_stub_entity_type_name -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" op.add_column("Directory", sa.Column("rdname", sa.String(length=64))) @@ -57,7 +58,7 @@ def upgrade() -> None: @temporary_stub_entity_type_name -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" bind = op.get_bind() session = Session(bind=bind) diff --git a/app/alembic/versions/bv546ccd35fa_fix_krbadmin_attrs.py b/app/alembic/versions/bv546ccd35fa_fix_krbadmin_attrs.py index 1f4c7ac0f..53979d701 100644 --- a/app/alembic/versions/bv546ccd35fa_fix_krbadmin_attrs.py +++ b/app/alembic/versions/bv546ccd35fa_fix_krbadmin_attrs.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer from sqlalchemy.orm import Session from entities import Attribute, Directory @@ -22,7 +23,7 @@ @temporary_stub_entity_type_name -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" bind = op.get_bind() session = Session(bind=bind) @@ -79,5 +80,5 @@ def upgrade() -> None: session.commit() -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: """Downgrade.""" diff --git a/app/alembic/versions/c007129b7973_renew_sls_gpos_rsops.py b/app/alembic/versions/c007129b7973_renew_sls_gpos_rsops.py index 1e3b7c40c..bc6bb3701 100644 --- a/app/alembic/versions/c007129b7973_renew_sls_gpos_rsops.py +++ b/app/alembic/versions/c007129b7973_renew_sls_gpos_rsops.py @@ -6,6 +6,8 @@ """ +from dishka import AsyncContainer + # revision identifiers, used by Alembic. revision: None | str = "c007129b7973" down_revision: None | str = "8164b4a9e1f1" @@ -13,9 +15,9 @@ depends_on: None | list[str] = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: """Upgrade.""" -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: """Downgrade.""" diff --git a/app/alembic/versions/c4888c68e221_fix_admin_attr_and_policy.py b/app/alembic/versions/c4888c68e221_fix_admin_attr_and_policy.py index ce182452a..d8b0d0256 100644 --- a/app/alembic/versions/c4888c68e221_fix_admin_attr_and_policy.py +++ b/app/alembic/versions/c4888c68e221_fix_admin_attr_and_policy.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession from sqlalchemy.orm import joinedload @@ -28,7 +29,7 @@ depends_on: None | list[str] = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" async def _attach_entity_type_to_directories( @@ -105,5 +106,5 @@ async def _change_ldap_session_ttl(connection: AsyncConnection) -> None: op.run_async(_attach_entity_type_to_directories) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: """Downgrade.""" diff --git a/app/alembic/versions/dafg3a4b22ab_add_preauth_princ.py b/app/alembic/versions/dafg3a4b22ab_add_preauth_princ.py index 06731ae67..e7b426043 100644 --- a/app/alembic/versions/dafg3a4b22ab_add_preauth_princ.py +++ b/app/alembic/versions/dafg3a4b22ab_add_preauth_princ.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer from sqlalchemy.orm import Session from entities import Attribute, CatalogueSetting, User @@ -23,7 +24,7 @@ @temporary_stub_entity_type_name -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" bind = op.get_bind() session = Session(bind=bind) @@ -76,7 +77,7 @@ def upgrade() -> None: ) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" op.drop_index(op.f("ix_Settings_name"), table_name="Settings") op.create_index( diff --git a/app/alembic/versions/df4c52a613e5_migrate_password_prop_from_E.py b/app/alembic/versions/df4c52a613e5_migrate_password_prop_from_E.py index d1c078db1..6fef5b0bc 100644 --- a/app/alembic/versions/df4c52a613e5_migrate_password_prop_from_E.py +++ b/app/alembic/versions/df4c52a613e5_migrate_password_prop_from_E.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer, Scope from sqlalchemy import update from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession from sqlalchemy.orm import Session @@ -27,7 +28,7 @@ _BAN_WORDS = set(f.read().split("\n")) -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: """Upgrade.""" bind = op.get_bind() session = Session(bind=bind) @@ -49,7 +50,9 @@ async def _create_common_passwords(connection: AsyncConnection) -> None: session = AsyncSession(bind=connection) await session.begin() - password_ban_word_repo = PasswordBanWordRepository(session) + async with container(scope=Scope.REQUEST) as cnt: + password_ban_word_repo = await cnt.get(PasswordBanWordRepository) + await password_ban_word_repo.replace(_BAN_WORDS) await session.commit() @@ -256,7 +259,7 @@ async def _create_common_passwords(connection: AsyncConnection) -> None: ) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" op.execute( sa.text("DROP INDEX IF EXISTS idx_password_ban_words_word_gin_trgm"), diff --git a/app/alembic/versions/e4d6d99d32bd_add_audit_policies.py b/app/alembic/versions/e4d6d99d32bd_add_audit_policies.py index 77ad0f091..9fdd83900 100644 --- a/app/alembic/versions/e4d6d99d32bd_add_audit_policies.py +++ b/app/alembic/versions/e4d6d99d32bd_add_audit_policies.py @@ -10,6 +10,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer, Scope from sqlalchemy.dialects import postgresql from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession @@ -26,7 +27,7 @@ depends_on: None | str = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: """Upgrade.""" async def _create_audit_policies(connection: AsyncConnection) -> None: @@ -34,8 +35,10 @@ async def _create_audit_policies(connection: AsyncConnection) -> None: if not await get_base_directories(session): return - audit_dao = AuditPoliciesDAO(session) - dest_dao = AuditDestinationDAO(session) + + async with container(scope=Scope.REQUEST) as cnt: + audit_dao = await cnt.get(AuditPoliciesDAO) + dest_dao = await cnt.get(AuditDestinationDAO) manager = Mock(spec=RawAuditManager) use_case = AuditUseCase(audit_dao, dest_dao, manager) await use_case.create_policies() @@ -139,7 +142,7 @@ async def _create_audit_policies(connection: AsyncConnection) -> None: op.run_async(_create_audit_policies) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" op.drop_table("AuditPolicyTriggers") op.drop_table("AuditPolicies") diff --git a/app/alembic/versions/eeaed5989eb0_group_policies.py b/app/alembic/versions/eeaed5989eb0_group_policies.py index 49b46fed6..de76492b8 100644 --- a/app/alembic/versions/eeaed5989eb0_group_policies.py +++ b/app/alembic/versions/eeaed5989eb0_group_policies.py @@ -6,6 +6,8 @@ """ +from dishka import AsyncContainer + # revision identifiers, used by Alembic. revision = "eeaed5989eb0" down_revision = "e4d6d99d32bd" @@ -13,9 +15,9 @@ depends_on: None | str = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: """Upgrade.""" -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: """Downgrade.""" diff --git a/app/alembic/versions/f1abf7ef2443_add_container_object_class.py b/app/alembic/versions/f1abf7ef2443_add_container_object_class.py index fa9ef428c..318cb3417 100644 --- a/app/alembic/versions/f1abf7ef2443_add_container_object_class.py +++ b/app/alembic/versions/f1abf7ef2443_add_container_object_class.py @@ -7,6 +7,7 @@ """ from alembic import op +from dishka import AsyncContainer from sqlalchemy import delete, func, insert, select, update from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession @@ -21,7 +22,7 @@ depends_on: None | str = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" async def _migrate_ou_to_cn_containers( @@ -106,7 +107,7 @@ async def _migrate_ou_to_cn_containers( op.run_async(_migrate_ou_to_cn_containers) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" async def _migrate_cn_to_ou_containers( diff --git a/app/alembic/versions/f24ed0e49df2_add_filter_anr.py b/app/alembic/versions/f24ed0e49df2_add_filter_anr.py index 991da67c7..b6ec3ee1a 100644 --- a/app/alembic/versions/f24ed0e49df2_add_filter_anr.py +++ b/app/alembic/versions/f24ed0e49df2_add_filter_anr.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer from sqlalchemy.dialects import postgresql from sqlalchemy.orm import Session @@ -34,7 +35,7 @@ ) -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" bind = op.get_bind() session = Session(bind=bind) @@ -67,7 +68,7 @@ def upgrade() -> None: session.commit() -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" op.alter_column( "EntityTypes", diff --git a/app/alembic/versions/f68a134a3685_add_bypass.py b/app/alembic/versions/f68a134a3685_add_bypass.py index c39e0136d..fe8b90e23 100644 --- a/app/alembic/versions/f68a134a3685_add_bypass.py +++ b/app/alembic/versions/f68a134a3685_add_bypass.py @@ -8,6 +8,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer # revision identifiers, used by Alembic. revision = "f68a134a3685" @@ -16,7 +17,7 @@ depends_on: None | str = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" op.add_column( "Policies", @@ -38,7 +39,7 @@ def upgrade() -> None: ) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" op.drop_column("Policies", "bypass_service_failure") op.drop_column("Policies", "bypass_no_connection") diff --git a/app/alembic/versions/fafc3d0b11ec_.py b/app/alembic/versions/fafc3d0b11ec_.py index ba9c04b39..b08247a75 100644 --- a/app/alembic/versions/fafc3d0b11ec_.py +++ b/app/alembic/versions/fafc3d0b11ec_.py @@ -7,6 +7,7 @@ """ from alembic import op +from dishka import AsyncContainer from sqlalchemy import delete, exists, select from sqlalchemy.exc import DBAPIError, IntegrityError from sqlalchemy.ext.asyncio import AsyncConnection, AsyncSession @@ -31,7 +32,7 @@ @temporary_stub_entity_type_name -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Upgrade.""" async def _create_readonly_grp_and_plcy( @@ -70,7 +71,7 @@ async def _create_readonly_grp_and_plcy( @temporary_stub_entity_type_name -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Downgrade.""" async def _delete_readonly_grp_and_plcy( diff --git a/app/alembic/versions/fc8b7617c60a_attr_index.py b/app/alembic/versions/fc8b7617c60a_attr_index.py index 4ce948f4c..ced401ee1 100644 --- a/app/alembic/versions/fc8b7617c60a_attr_index.py +++ b/app/alembic/versions/fc8b7617c60a_attr_index.py @@ -7,6 +7,7 @@ import sqlalchemy as sa from alembic import op +from dishka import AsyncContainer # revision identifiers, used by Alembic. revision = "fc8b7617c60a" @@ -15,7 +16,7 @@ depends_on: str | None = None -def upgrade() -> None: +def upgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Create index for Attribute name field.""" op.execute( sa.text( @@ -31,7 +32,7 @@ def upgrade() -> None: ) -def downgrade() -> None: +def downgrade(container: AsyncContainer) -> None: # noqa: ARG001 """Drop index for Attribute name field.""" op.execute(sa.text("DROP INDEX idx_attributes_lw_name_btree")) op.execute(sa.text("DROP INDEX idx_attributes_name_gin_trgm")) diff --git a/app/ioc.py b/app/ioc.py index cd74d77f3..c1a1d7e93 100644 --- a/app/ioc.py +++ b/app/ioc.py @@ -12,6 +12,7 @@ from fastapi import Request from loguru import logger from sqlalchemy.ext.asyncio import ( + AsyncConnection, AsyncEngine, AsyncSession, async_sessionmaker, @@ -790,3 +791,26 @@ async def get_ldap_mfa( settings, ), ) + + +class MigrationProvider(Provider): + """Provider for migrations.""" + + scope = Scope.APP + + @provide(scope=Scope.APP) + def get_session_factory( + self, + connection: AsyncConnection, + ) -> AsyncSession: + """Create session factory.""" + return AsyncSession(connection) + + @provide(scope=Scope.APP) + async def get_conn_factory( + self, + engine: AsyncEngine, + ) -> AsyncIterator[AsyncConnection]: + """Create session factory.""" + async with engine.connect() as connection: + yield connection diff --git a/app/ldap_protocol/session_storage/base.py b/app/ldap_protocol/session_storage/base.py index cc5724159..f4f9b3ac7 100644 --- a/app/ldap_protocol/session_storage/base.py +++ b/app/ldap_protocol/session_storage/base.py @@ -9,8 +9,6 @@ from secrets import token_hex from typing import Literal, Self -from loguru import logger - from config import Settings from .exceptions import ( @@ -175,9 +173,6 @@ async def get_user_id( raise SessionStorageInvalidKeyError("Invalid payload key") try: - logger.debug( - f"Retrieving session data for session_id: {session_id}", - ) data = await self.get(session_id) except KeyError: raise SessionStorageInvalidKeyError("Invalid session key") diff --git a/interface b/interface index bef67d7cb..242c01f0f 160000 --- a/interface +++ b/interface @@ -1 +1 @@ -Subproject commit bef67d7cbfcb16648a4c4ebc5a870f97bdda0856 +Subproject commit 242c01f0f26a5080beef14523f9dd9dfab3c89ec diff --git a/tests/conftest.py b/tests/conftest.py index 4906ccc1d..1a41b3783 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -824,6 +824,20 @@ async def add_schema( ) +class TestMigrationProvider(Provider): + """Provider for migrations.""" + + async_conn = from_context(provides=AsyncConnection, scope=Scope.RUNTIME) + + @provide(scope=Scope.APP, cache=False) + def get_session_factory( + self, + async_conn: AsyncConnection, + ) -> AsyncSession: + """Create session factory.""" + return AsyncSession(async_conn) + + @pytest_asyncio.fixture(scope="session", autouse=True) async def _migrations( add_schema: None, # noqa: ARG001 @@ -844,13 +858,26 @@ def downgrade(conn: AsyncConnection) -> None: config.attributes["connection"] = conn command.downgrade(config, "base") + test_migration_provider = TestMigrationProvider() async with engine.begin() as conn: config.attributes["connection"] = conn + config.attributes["dishka_container"] = make_async_container( + TestProvider(), + test_migration_provider, + context={Settings: settings, AsyncConnection: conn}, + start_scope=Scope.RUNTIME, + ) await conn.run_sync(upgrade) # type: ignore yield async with engine.begin() as conn: + config.attributes["dishka_container"] = make_async_container( + TestProvider(), + test_migration_provider, + context={Settings: settings, AsyncConnection: conn}, + start_scope=Scope.RUNTIME, + ) await conn.run_sync(downgrade) # type: ignore