diff options
| author | 2026-09-04 17:09:24 +0200 | |
|---|---|---|
| committer | 2026-09-04 17:09:24 +0200 | |
| commit | 6b6f20a032eb31d747366c8bc270ca81731eaf6a (patch) | |
| tree | ada48080495267bebde4ee1251bbbe77d629745f /db | |
| parent | 2d22158dd95f76399f5716d556be60c77da04a46 (diff) | |
| download | server-6b6f20a032eb31d747366c8bc270ca81731eaf6a.tar.gz server-6b6f20a032eb31d747366c8bc270ca81731eaf6a.tar.bz2 server-6b6f20a032eb31d747366c8bc270ca81731eaf6a.zip | |
Fixed pre-commit issuesv3
Diffstat (limited to 'db')
| -rw-r--r-- | db/migrations/README | 2 | ||||
| -rw-r--r-- | db/migrations/env.py | 10 | ||||
| -rw-r--r-- | db/migrations/versions/202607021719-115caa5a76d0_added_user_model.py | 33 | ||||
| -rw-r--r-- | db/migrations/versions/202607021740-fc6608d3f9cc_added_oauth_models.py | 160 | ||||
| -rw-r--r-- | db/migrations/versions/202607021803-ac4fbf1fea31_added_password.py | 21 | ||||
| -rw-r--r-- | db/migrations/versions/202607031440-69d8b4938a12_added_more_fields_and_session.py | 113 | ||||
| -rw-r--r-- | db/models.py | 21 | ||||
| -rw-r--r-- | db/session.py | 17 |
8 files changed, 228 insertions, 149 deletions
diff --git a/db/migrations/README b/db/migrations/README index 98e4f9c..2500aa1 100644 --- a/db/migrations/README +++ b/db/migrations/README | |||
| @@ -1 +1 @@ | |||
| Generic single-database configuration. \ No newline at end of file | Generic single-database configuration. | ||
diff --git a/db/migrations/env.py b/db/migrations/env.py index f1b3156..9c901da 100644 --- a/db/migrations/env.py +++ b/db/migrations/env.py | |||
| @@ -1,9 +1,7 @@ | |||
| 1 | from logging.config import fileConfig | 1 | from logging.config import fileConfig |
| 2 | 2 | ||
| 3 | from sqlalchemy import engine_from_config | ||
| 4 | from sqlalchemy import pool | ||
| 5 | |||
| 6 | from alembic import context | 3 | from alembic import context |
| 4 | from sqlalchemy import engine_from_config, pool | ||
| 7 | 5 | ||
| 8 | from conf import DATABASE_URL | 6 | from conf import DATABASE_URL |
| 9 | from db.models import * | 7 | from db.models import * |
| @@ -27,7 +25,7 @@ target_metadata = SQLModel.metadata | |||
| 27 | # can be acquired: | 25 | # can be acquired: |
| 28 | # my_important_option = config.get_main_option("my_important_option") | 26 | # my_important_option = config.get_main_option("my_important_option") |
| 29 | # ... etc. | 27 | # ... etc. |
| 30 | config.set_main_option('sqlalchemy.url', DATABASE_URL) | 28 | config.set_main_option("sqlalchemy.url", DATABASE_URL) |
| 31 | 29 | ||
| 32 | 30 | ||
| 33 | def run_migrations_offline() -> None: | 31 | def run_migrations_offline() -> None: |
| @@ -68,9 +66,7 @@ def run_migrations_online() -> None: | |||
| 68 | ) | 66 | ) |
| 69 | 67 | ||
| 70 | with connectable.connect() as connection: | 68 | with connectable.connect() as connection: |
| 71 | context.configure( | 69 | context.configure(connection=connection, target_metadata=target_metadata) |
| 72 | connection=connection, target_metadata=target_metadata | ||
| 73 | ) | ||
| 74 | 70 | ||
| 75 | with context.begin_transaction(): | 71 | with context.begin_transaction(): |
| 76 | context.run_migrations() | 72 | context.run_migrations() |
diff --git a/db/migrations/versions/202607021719-115caa5a76d0_added_user_model.py b/db/migrations/versions/202607021719-115caa5a76d0_added_user_model.py index 3ccb92d..0bb3076 100644 --- a/db/migrations/versions/202607021719-115caa5a76d0_added_user_model.py +++ b/db/migrations/versions/202607021719-115caa5a76d0_added_user_model.py | |||
| @@ -1,40 +1,41 @@ | |||
| 1 | """Added user model | 1 | """Added user model |
| 2 | 2 | ||
| 3 | Revision ID: 115caa5a76d0 | 3 | Revision ID: 115caa5a76d0 |
| 4 | Revises: | 4 | Revises: |
| 5 | Create Date: 2026-07-02 17:19:07.082841 | 5 | Create Date: 2026-07-02 17:19:07.082841 |
| 6 | 6 | ||
| 7 | """ | 7 | """ |
| 8 | from typing import Sequence, Union | ||
| 9 | 8 | ||
| 10 | from alembic import op | 9 | from collections.abc import Sequence |
| 10 | |||
| 11 | import sqlalchemy as sa | 11 | import sqlalchemy as sa |
| 12 | import sqlmodel | 12 | import sqlmodel |
| 13 | 13 | from alembic import op | |
| 14 | 14 | ||
| 15 | # revision identifiers, used by Alembic. | 15 | # revision identifiers, used by Alembic. |
| 16 | revision: str = '115caa5a76d0' | 16 | revision: str = "115caa5a76d0" |
| 17 | down_revision: Union[str, Sequence[str], None] = None | 17 | down_revision: str | Sequence[str] | None = None |
| 18 | branch_labels: Union[str, Sequence[str], None] = None | 18 | branch_labels: str | Sequence[str] | None = None |
| 19 | depends_on: Union[str, Sequence[str], None] = None | 19 | depends_on: str | Sequence[str] | None = None |
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | def upgrade() -> None: | 22 | def upgrade() -> None: |
| 23 | """Upgrade schema.""" | 23 | """Upgrade schema.""" |
| 24 | # ### commands auto generated by Alembic - please adjust! ### | 24 | # ### commands auto generated by Alembic - please adjust! ### |
| 25 | op.create_table('user', | 25 | op.create_table( |
| 26 | sa.Column('id', sa.Uuid(), nullable=False), | 26 | "user", |
| 27 | sa.Column('username', sqlmodel.sql.sqltypes.AutoString(), nullable=False), | 27 | sa.Column("id", sa.Uuid(), nullable=False), |
| 28 | sa.Column('email', sqlmodel.sql.sqltypes.AutoString(), nullable=False), | 28 | sa.Column("username", sqlmodel.sql.sqltypes.AutoString(), nullable=False), |
| 29 | sa.PrimaryKeyConstraint('id') | 29 | sa.Column("email", sqlmodel.sql.sqltypes.AutoString(), nullable=False), |
| 30 | sa.PrimaryKeyConstraint("id"), | ||
| 30 | ) | 31 | ) |
| 31 | op.create_index(op.f('ix_user_username'), 'user', ['username'], unique=True) | 32 | op.create_index(op.f("ix_user_username"), "user", ["username"], unique=True) |
| 32 | # ### end Alembic commands ### | 33 | # ### end Alembic commands ### |
| 33 | 34 | ||
| 34 | 35 | ||
| 35 | def downgrade() -> None: | 36 | def downgrade() -> None: |
| 36 | """Downgrade schema.""" | 37 | """Downgrade schema.""" |
| 37 | # ### commands auto generated by Alembic - please adjust! ### | 38 | # ### commands auto generated by Alembic - please adjust! ### |
| 38 | op.drop_index(op.f('ix_user_username'), table_name='user') | 39 | op.drop_index(op.f("ix_user_username"), table_name="user") |
| 39 | op.drop_table('user') | 40 | op.drop_table("user") |
| 40 | # ### end Alembic commands ### | 41 | # ### end Alembic commands ### |
diff --git a/db/migrations/versions/202607021740-fc6608d3f9cc_added_oauth_models.py b/db/migrations/versions/202607021740-fc6608d3f9cc_added_oauth_models.py index 5498291..b94ffb8 100644 --- a/db/migrations/versions/202607021740-fc6608d3f9cc_added_oauth_models.py +++ b/db/migrations/versions/202607021740-fc6608d3f9cc_added_oauth_models.py | |||
| @@ -5,100 +5,116 @@ Revises: 115caa5a76d0 | |||
| 5 | Create Date: 2026-07-02 17:40:58.968553 | 5 | Create Date: 2026-07-02 17:40:58.968553 |
| 6 | 6 | ||
| 7 | """ | 7 | """ |
| 8 | |||
| 8 | import json | 9 | import json |
| 9 | import os | 10 | import os |
| 10 | from datetime import datetime, UTC | 11 | from collections.abc import Sequence |
| 12 | from datetime import UTC, datetime | ||
| 11 | from secrets import token_hex | 13 | from secrets import token_hex |
| 12 | from random import randbytes | ||
| 13 | from typing import Sequence, Union | ||
| 14 | from uuid import uuid4, uuid7 | 14 | from uuid import uuid4, uuid7 |
| 15 | 15 | ||
| 16 | from alembic import op | ||
| 17 | import sqlalchemy as sa | 16 | import sqlalchemy as sa |
| 18 | import sqlmodel | 17 | import sqlmodel |
| 19 | from authlib.integrations.sqla_oauth2 import OAuth2ClientMixin | 18 | from alembic import op |
| 20 | 19 | ||
| 21 | # revision identifiers, used by Alembic. | 20 | # revision identifiers, used by Alembic. |
| 22 | revision: str = 'fc6608d3f9cc' | 21 | revision: str = "fc6608d3f9cc" |
| 23 | down_revision: Union[str, Sequence[str], None] = '115caa5a76d0' | 22 | down_revision: str | Sequence[str] | None = "115caa5a76d0" |
| 24 | branch_labels: Union[str, Sequence[str], None] = None | 23 | branch_labels: str | Sequence[str] | None = None |
| 25 | depends_on: Union[str, Sequence[str], None] = None | 24 | depends_on: str | Sequence[str] | None = None |
| 26 | 25 | ||
| 27 | 26 | ||
| 28 | def upgrade() -> None: | 27 | def upgrade() -> None: |
| 29 | """Upgrade schema.""" | 28 | """Upgrade schema.""" |
| 30 | # ### commands auto generated by Alembic - please adjust! ### | 29 | # ### commands auto generated by Alembic - please adjust! ### |
| 31 | client_application = op.create_table('clientapplication', | 30 | client_application = op.create_table( |
| 32 | sa.Column('id', sa.Uuid(), nullable=False), | 31 | "clientapplication", |
| 33 | sa.Column('name', sqlmodel.sql.sqltypes.AutoString(), nullable=False), | 32 | sa.Column("id", sa.Uuid(), nullable=False), |
| 34 | sa.Column('client_id', sa.String(length=48), nullable=True), | 33 | sa.Column("name", sqlmodel.sql.sqltypes.AutoString(), nullable=False), |
| 35 | sa.Column('client_secret', sa.String(length=120), nullable=True), | 34 | sa.Column("client_id", sa.String(length=48), nullable=True), |
| 36 | sa.Column('client_id_issued_at', sa.Integer(), nullable=False), | 35 | sa.Column("client_secret", sa.String(length=120), nullable=True), |
| 37 | sa.Column('client_secret_expires_at', sa.Integer(), nullable=False), | 36 | sa.Column("client_id_issued_at", sa.Integer(), nullable=False), |
| 38 | sa.Column('client_metadata', sa.Text(), nullable=True), | 37 | sa.Column("client_secret_expires_at", sa.Integer(), nullable=False), |
| 39 | sa.PrimaryKeyConstraint('id') | 38 | sa.Column("client_metadata", sa.Text(), nullable=True), |
| 39 | sa.PrimaryKeyConstraint("id"), | ||
| 40 | ) | ||
| 41 | op.create_index( | ||
| 42 | op.f("ix_clientapplication_client_id"), | ||
| 43 | "clientapplication", | ||
| 44 | ["client_id"], | ||
| 45 | unique=False, | ||
| 40 | ) | 46 | ) |
| 41 | op.create_index(op.f('ix_clientapplication_client_id'), 'clientapplication', ['client_id'], unique=False) | 47 | op.create_table( |
| 42 | op.create_table('authcode', | 48 | "authcode", |
| 43 | sa.Column('id', sa.Uuid(), nullable=False), | 49 | sa.Column("id", sa.Uuid(), nullable=False), |
| 44 | sa.Column('user_id', sa.Uuid(), nullable=False), | 50 | sa.Column("user_id", sa.Uuid(), nullable=False), |
| 45 | sa.Column('code', sa.String(length=120), nullable=False), | 51 | sa.Column("code", sa.String(length=120), nullable=False), |
| 46 | sa.Column('client_id', sa.String(length=48), nullable=True), | 52 | sa.Column("client_id", sa.String(length=48), nullable=True), |
| 47 | sa.Column('redirect_uri', sa.Text(), nullable=True), | 53 | sa.Column("redirect_uri", sa.Text(), nullable=True), |
| 48 | sa.Column('response_type', sa.Text(), nullable=True), | 54 | sa.Column("response_type", sa.Text(), nullable=True), |
| 49 | sa.Column('scope', sa.Text(), nullable=True), | 55 | sa.Column("scope", sa.Text(), nullable=True), |
| 50 | sa.Column('nonce', sa.Text(), nullable=True), | 56 | sa.Column("nonce", sa.Text(), nullable=True), |
| 51 | sa.Column('auth_time', sa.Integer(), nullable=False), | 57 | sa.Column("auth_time", sa.Integer(), nullable=False), |
| 52 | sa.Column('acr', sa.Text(), nullable=True), | 58 | sa.Column("acr", sa.Text(), nullable=True), |
| 53 | sa.Column('amr', sa.Text(), nullable=True), | 59 | sa.Column("amr", sa.Text(), nullable=True), |
| 54 | sa.Column('code_challenge', sa.Text(), nullable=True), | 60 | sa.Column("code_challenge", sa.Text(), nullable=True), |
| 55 | sa.Column('code_challenge_method', sa.String(length=48), nullable=True), | 61 | sa.Column("code_challenge_method", sa.String(length=48), nullable=True), |
| 56 | sa.ForeignKeyConstraint(['user_id'], ['user.id'], ondelete='CASCADE'), | 62 | sa.ForeignKeyConstraint(["user_id"], ["user.id"], ondelete="CASCADE"), |
| 57 | sa.PrimaryKeyConstraint('id'), | 63 | sa.PrimaryKeyConstraint("id"), |
| 58 | sa.UniqueConstraint('code') | 64 | sa.UniqueConstraint("code"), |
| 59 | ) | 65 | ) |
| 60 | op.create_table('authtoken', | 66 | op.create_table( |
| 61 | sa.Column('id', sa.Uuid(), nullable=False), | 67 | "authtoken", |
| 62 | sa.Column('user_id', sa.Uuid(), nullable=False), | 68 | sa.Column("id", sa.Uuid(), nullable=False), |
| 63 | sa.Column('client_id', sa.String(length=48), nullable=True), | 69 | sa.Column("user_id", sa.Uuid(), nullable=False), |
| 64 | sa.Column('token_type', sa.String(length=40), nullable=True), | 70 | sa.Column("client_id", sa.String(length=48), nullable=True), |
| 65 | sa.Column('access_token', sa.String(length=255), nullable=False), | 71 | sa.Column("token_type", sa.String(length=40), nullable=True), |
| 66 | sa.Column('refresh_token', sa.String(length=255), nullable=True), | 72 | sa.Column("access_token", sa.String(length=255), nullable=False), |
| 67 | sa.Column('scope', sa.Text(), nullable=True), | 73 | sa.Column("refresh_token", sa.String(length=255), nullable=True), |
| 68 | sa.Column('issued_at', sa.Integer(), nullable=False), | 74 | sa.Column("scope", sa.Text(), nullable=True), |
| 69 | sa.Column('access_token_revoked_at', sa.Integer(), nullable=False), | 75 | sa.Column("issued_at", sa.Integer(), nullable=False), |
| 70 | sa.Column('refresh_token_revoked_at', sa.Integer(), nullable=False), | 76 | sa.Column("access_token_revoked_at", sa.Integer(), nullable=False), |
| 71 | sa.Column('expires_in', sa.Integer(), nullable=False), | 77 | sa.Column("refresh_token_revoked_at", sa.Integer(), nullable=False), |
| 72 | sa.ForeignKeyConstraint(['user_id'], ['user.id'], ondelete='CASCADE'), | 78 | sa.Column("expires_in", sa.Integer(), nullable=False), |
| 73 | sa.PrimaryKeyConstraint('id'), | 79 | sa.ForeignKeyConstraint(["user_id"], ["user.id"], ondelete="CASCADE"), |
| 74 | sa.UniqueConstraint('access_token') | 80 | sa.PrimaryKeyConstraint("id"), |
| 81 | sa.UniqueConstraint("access_token"), | ||
| 82 | ) | ||
| 83 | op.create_index( | ||
| 84 | op.f("ix_authtoken_refresh_token"), "authtoken", ["refresh_token"], unique=False | ||
| 75 | ) | 85 | ) |
| 76 | op.create_index(op.f('ix_authtoken_refresh_token'), 'authtoken', ['refresh_token'], unique=False) | ||
| 77 | 86 | ||
| 78 | op.bulk_insert(client_application, [ | 87 | op.bulk_insert( |
| 79 | { | 88 | client_application, |
| 80 | 'id': uuid7(), | 89 | [ |
| 81 | 'name': 'TTUN', | 90 | { |
| 82 | 'client_id': uuid4().hex, | 91 | "id": uuid7(), |
| 83 | 'client_secret': token_hex(32), | 92 | "name": "TTUN", |
| 84 | 'client_id_issued_at': datetime.now(tz=UTC).timestamp(), | 93 | "client_id": uuid4().hex, |
| 85 | 'client_secret_expires_at': datetime.now(tz=UTC).timestamp() + 3600, | 94 | "client_secret": token_hex(32), |
| 86 | 'client_metadata': json.dumps({ | 95 | "client_id_issued_at": datetime.now(tz=UTC).timestamp(), |
| 87 | 'redirect_uris': [ | 96 | "client_secret_expires_at": datetime.now(tz=UTC).timestamp() + 3600, |
| 88 | f'//{os.environ['TUNNEL_DOMAIN']}/oauth/callback' | 97 | "client_metadata": json.dumps( |
| 89 | ], | 98 | { |
| 90 | }) | 99 | "redirect_uris": [ |
| 91 | } | 100 | f"//{os.environ['TUNNEL_DOMAIN']}/oauth/callback" |
| 92 | ]) | 101 | ], |
| 102 | } | ||
| 103 | ), | ||
| 104 | } | ||
| 105 | ], | ||
| 106 | ) | ||
| 93 | # ### end Alembic commands ### | 107 | # ### end Alembic commands ### |
| 94 | 108 | ||
| 95 | 109 | ||
| 96 | def downgrade() -> None: | 110 | def downgrade() -> None: |
| 97 | """Downgrade schema.""" | 111 | """Downgrade schema.""" |
| 98 | # ### commands auto generated by Alembic - please adjust! ### | 112 | # ### commands auto generated by Alembic - please adjust! ### |
| 99 | op.drop_index(op.f('ix_authtoken_refresh_token'), table_name='authtoken') | 113 | op.drop_index(op.f("ix_authtoken_refresh_token"), table_name="authtoken") |
| 100 | op.drop_table('authtoken') | 114 | op.drop_table("authtoken") |
| 101 | op.drop_table('authcode') | 115 | op.drop_table("authcode") |
| 102 | op.drop_index(op.f('ix_clientapplication_client_id'), table_name='clientapplication') | 116 | op.drop_index( |
| 103 | op.drop_table('clientapplication') | 117 | op.f("ix_clientapplication_client_id"), table_name="clientapplication" |
| 118 | ) | ||
| 119 | op.drop_table("clientapplication") | ||
| 104 | # ### end Alembic commands ### | 120 | # ### end Alembic commands ### |
diff --git a/db/migrations/versions/202607021803-ac4fbf1fea31_added_password.py b/db/migrations/versions/202607021803-ac4fbf1fea31_added_password.py index 116d27e..5ad10c9 100644 --- a/db/migrations/versions/202607021803-ac4fbf1fea31_added_password.py +++ b/db/migrations/versions/202607021803-ac4fbf1fea31_added_password.py | |||
| @@ -5,29 +5,32 @@ Revises: fc6608d3f9cc | |||
| 5 | Create Date: 2026-07-02 18:03:17.190700 | 5 | Create Date: 2026-07-02 18:03:17.190700 |
| 6 | 6 | ||
| 7 | """ | 7 | """ |
| 8 | from typing import Sequence, Union | ||
| 9 | 8 | ||
| 10 | from alembic import op | 9 | from collections.abc import Sequence |
| 10 | |||
| 11 | import sqlalchemy as sa | 11 | import sqlalchemy as sa |
| 12 | import sqlmodel | 12 | import sqlmodel |
| 13 | 13 | from alembic import op | |
| 14 | 14 | ||
| 15 | # revision identifiers, used by Alembic. | 15 | # revision identifiers, used by Alembic. |
| 16 | revision: str = 'ac4fbf1fea31' | 16 | revision: str = "ac4fbf1fea31" |
| 17 | down_revision: Union[str, Sequence[str], None] = 'fc6608d3f9cc' | 17 | down_revision: str | Sequence[str] | None = "fc6608d3f9cc" |
| 18 | branch_labels: Union[str, Sequence[str], None] = None | 18 | branch_labels: str | Sequence[str] | None = None |
| 19 | depends_on: Union[str, Sequence[str], None] = None | 19 | depends_on: str | Sequence[str] | None = None |
| 20 | 20 | ||
| 21 | 21 | ||
| 22 | def upgrade() -> None: | 22 | def upgrade() -> None: |
| 23 | """Upgrade schema.""" | 23 | """Upgrade schema.""" |
| 24 | # ### commands auto generated by Alembic - please adjust! ### | 24 | # ### commands auto generated by Alembic - please adjust! ### |
| 25 | op.add_column('user', sa.Column('password', sqlmodel.sql.sqltypes.AutoString(), nullable=False)) | 25 | op.add_column( |
| 26 | "user", | ||
| 27 | sa.Column("password", sqlmodel.sql.sqltypes.AutoString(), nullable=False), | ||
| 28 | ) | ||
| 26 | # ### end Alembic commands ### | 29 | # ### end Alembic commands ### |
| 27 | 30 | ||
| 28 | 31 | ||
| 29 | def downgrade() -> None: | 32 | def downgrade() -> None: |
| 30 | """Downgrade schema.""" | 33 | """Downgrade schema.""" |
| 31 | # ### commands auto generated by Alembic - please adjust! ### | 34 | # ### commands auto generated by Alembic - please adjust! ### |
| 32 | op.drop_column('user', 'password') | 35 | op.drop_column("user", "password") |
| 33 | # ### end Alembic commands ### | 36 | # ### end Alembic commands ### |
diff --git a/db/migrations/versions/202607031440-69d8b4938a12_added_more_fields_and_session.py b/db/migrations/versions/202607031440-69d8b4938a12_added_more_fields_and_session.py index ec5031b..40b8a70 100644 --- a/db/migrations/versions/202607031440-69d8b4938a12_added_more_fields_and_session.py +++ b/db/migrations/versions/202607031440-69d8b4938a12_added_more_fields_and_session.py | |||
| @@ -5,52 +5,101 @@ Revises: ac4fbf1fea31 | |||
| 5 | Create Date: 2026-07-03 14:40:55.628816 | 5 | Create Date: 2026-07-03 14:40:55.628816 |
| 6 | 6 | ||
| 7 | """ | 7 | """ |
| 8 | from typing import Sequence, Union | ||
| 9 | 8 | ||
| 10 | from alembic import op | 9 | from collections.abc import Sequence |
| 11 | import sqlalchemy as sa | ||
| 12 | import sqlmodel | ||
| 13 | 10 | ||
| 11 | import sqlalchemy as sa | ||
| 12 | from alembic import op | ||
| 14 | 13 | ||
| 15 | # revision identifiers, used by Alembic. | 14 | # revision identifiers, used by Alembic. |
| 16 | revision: str = '69d8b4938a12' | 15 | revision: str = "69d8b4938a12" |
| 17 | down_revision: Union[str, Sequence[str], None] = 'ac4fbf1fea31' | 16 | down_revision: str | Sequence[str] | None = "ac4fbf1fea31" |
| 18 | branch_labels: Union[str, Sequence[str], None] = None | 17 | branch_labels: str | Sequence[str] | None = None |
| 19 | depends_on: Union[str, Sequence[str], None] = None | 18 | depends_on: str | Sequence[str] | None = None |
| 20 | 19 | ||
| 21 | 20 | ||
| 22 | def upgrade() -> None: | 21 | def upgrade() -> None: |
| 23 | """Upgrade schema.""" | 22 | """Upgrade schema.""" |
| 24 | # ### commands auto generated by Alembic - please adjust! ### | 23 | # ### commands auto generated by Alembic - please adjust! ### |
| 25 | op.create_table('session', | 24 | op.create_table( |
| 26 | sa.Column('id', sa.Uuid(), nullable=False), | 25 | "session", |
| 27 | sa.Column('created', sa.DateTime(timezone=True), nullable=False, server_default=sa.text('now()')), | 26 | sa.Column("id", sa.Uuid(), nullable=False), |
| 28 | sa.Column('updated', sa.DateTime(timezone=True), nullable=True), | 27 | sa.Column( |
| 29 | sa.Column('user_id', sa.Uuid(), nullable=False), | 28 | "created", |
| 30 | sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), | 29 | sa.DateTime(timezone=True), |
| 31 | sa.PrimaryKeyConstraint('id') | 30 | nullable=False, |
| 31 | server_default=sa.text("now()"), | ||
| 32 | ), | ||
| 33 | sa.Column("updated", sa.DateTime(timezone=True), nullable=True), | ||
| 34 | sa.Column("user_id", sa.Uuid(), nullable=False), | ||
| 35 | sa.ForeignKeyConstraint( | ||
| 36 | ["user_id"], | ||
| 37 | ["user.id"], | ||
| 38 | ), | ||
| 39 | sa.PrimaryKeyConstraint("id"), | ||
| 40 | ) | ||
| 41 | op.add_column( | ||
| 42 | "authcode", | ||
| 43 | sa.Column( | ||
| 44 | "created", | ||
| 45 | sa.DateTime(timezone=True), | ||
| 46 | nullable=False, | ||
| 47 | server_default=sa.text("now()"), | ||
| 48 | ), | ||
| 49 | ) | ||
| 50 | op.add_column( | ||
| 51 | "authcode", sa.Column("updated", sa.DateTime(timezone=True), nullable=True) | ||
| 52 | ) | ||
| 53 | op.add_column( | ||
| 54 | "authtoken", | ||
| 55 | sa.Column( | ||
| 56 | "created", | ||
| 57 | sa.DateTime(timezone=True), | ||
| 58 | nullable=False, | ||
| 59 | server_default=sa.text("now()"), | ||
| 60 | ), | ||
| 61 | ) | ||
| 62 | op.add_column( | ||
| 63 | "authtoken", sa.Column("updated", sa.DateTime(timezone=True), nullable=True) | ||
| 64 | ) | ||
| 65 | op.add_column( | ||
| 66 | "clientapplication", | ||
| 67 | sa.Column( | ||
| 68 | "created", | ||
| 69 | sa.DateTime(timezone=True), | ||
| 70 | nullable=False, | ||
| 71 | server_default=sa.text("now()"), | ||
| 72 | ), | ||
| 73 | ) | ||
| 74 | op.add_column( | ||
| 75 | "clientapplication", | ||
| 76 | sa.Column("updated", sa.DateTime(timezone=True), nullable=True), | ||
| 77 | ) | ||
| 78 | op.add_column( | ||
| 79 | "user", | ||
| 80 | sa.Column( | ||
| 81 | "created", | ||
| 82 | sa.DateTime(timezone=True), | ||
| 83 | nullable=False, | ||
| 84 | server_default=sa.text("now()"), | ||
| 85 | ), | ||
| 86 | ) | ||
| 87 | op.add_column( | ||
| 88 | "user", sa.Column("updated", sa.DateTime(timezone=True), nullable=True) | ||
| 32 | ) | 89 | ) |
| 33 | op.add_column('authcode', sa.Column('created', sa.DateTime(timezone=True), nullable=False, server_default=sa.text('now()'))) | ||
| 34 | op.add_column('authcode', sa.Column('updated', sa.DateTime(timezone=True), nullable=True)) | ||
| 35 | op.add_column('authtoken', sa.Column('created', sa.DateTime(timezone=True), nullable=False, server_default=sa.text('now()'))) | ||
| 36 | op.add_column('authtoken', sa.Column('updated', sa.DateTime(timezone=True), nullable=True)) | ||
| 37 | op.add_column('clientapplication', sa.Column('created', sa.DateTime(timezone=True), nullable=False, server_default=sa.text('now()'))) | ||
| 38 | op.add_column('clientapplication', sa.Column('updated', sa.DateTime(timezone=True), nullable=True)) | ||
| 39 | op.add_column('user', sa.Column('created', sa.DateTime(timezone=True), nullable=False, server_default=sa.text('now()'))) | ||
| 40 | op.add_column('user', sa.Column('updated', sa.DateTime(timezone=True), nullable=True)) | ||
| 41 | # ### end Alembic commands ### | 90 | # ### end Alembic commands ### |
| 42 | 91 | ||
| 43 | 92 | ||
| 44 | def downgrade() -> None: | 93 | def downgrade() -> None: |
| 45 | """Downgrade schema.""" | 94 | """Downgrade schema.""" |
| 46 | # ### commands auto generated by Alembic - please adjust! ### | 95 | # ### commands auto generated by Alembic - please adjust! ### |
| 47 | op.drop_column('user', 'updated') | 96 | op.drop_column("user", "updated") |
| 48 | op.drop_column('user', 'created') | 97 | op.drop_column("user", "created") |
| 49 | op.drop_column('clientapplication', 'updated') | 98 | op.drop_column("clientapplication", "updated") |
| 50 | op.drop_column('clientapplication', 'created') | 99 | op.drop_column("clientapplication", "created") |
| 51 | op.drop_column('authtoken', 'updated') | 100 | op.drop_column("authtoken", "updated") |
| 52 | op.drop_column('authtoken', 'created') | 101 | op.drop_column("authtoken", "created") |
| 53 | op.drop_column('authcode', 'updated') | 102 | op.drop_column("authcode", "updated") |
| 54 | op.drop_column('authcode', 'created') | 103 | op.drop_column("authcode", "created") |
| 55 | op.drop_table('session') | 104 | op.drop_table("session") |
| 56 | # ### end Alembic commands ### | 105 | # ### end Alembic commands ### |
diff --git a/db/models.py b/db/models.py index 8a01c8c..8946bd2 100644 --- a/db/models.py +++ b/db/models.py | |||
| @@ -1,13 +1,16 @@ | |||
| 1 | import re | 1 | import re |
| 2 | from datetime import datetime, UTC | 2 | from datetime import UTC, datetime |
| 3 | from urllib.parse import urlsplit | 3 | from uuid import UUID, uuid7 |
| 4 | from uuid import uuid4, UUID, uuid7 | ||
| 5 | 4 | ||
| 6 | from sqlalchemy import DateTime | 5 | from sqlalchemy import DateTime |
| 7 | from sqlmodel import SQLModel, Field, Relationship | 6 | from sqlmodel import Field, Relationship, SQLModel |
| 8 | from starlette.authentication import BaseUser | 7 | from starlette.authentication import BaseUser |
| 9 | 8 | ||
| 10 | from authentication.mixins import OAuth2ClientMixin, OAuth2AuthorizationCodeMixin, OAuth2TokenMixin | 9 | from authentication.mixins import ( |
| 10 | OAuth2AuthorizationCodeMixin, | ||
| 11 | OAuth2ClientMixin, | ||
| 12 | OAuth2TokenMixin, | ||
| 13 | ) | ||
| 11 | from authentication.utils import bcrypt_sha256_hash | 14 | from authentication.utils import bcrypt_sha256_hash |
| 12 | 15 | ||
| 13 | 16 | ||
| @@ -21,7 +24,7 @@ class BaseModel(SQLModel): | |||
| 21 | default=None, | 24 | default=None, |
| 22 | nullable=True, | 25 | nullable=True, |
| 23 | sa_column_kwargs={ | 26 | sa_column_kwargs={ |
| 24 | 'onupdate': lambda: datetime.now(tz=UTC), | 27 | "onupdate": lambda: datetime.now(tz=UTC), |
| 25 | }, | 28 | }, |
| 26 | sa_type=DateTime(timezone=True), | 29 | sa_type=DateTime(timezone=True), |
| 27 | ) | 30 | ) |
| @@ -39,10 +42,12 @@ class User(BaseModel, BaseUser, table=True): | |||
| 39 | def is_authenticated(self) -> bool: | 42 | def is_authenticated(self) -> bool: |
| 40 | return True | 43 | return True |
| 41 | 44 | ||
| 45 | |||
| 42 | class Session(BaseModel, table=True): | 46 | class Session(BaseModel, table=True): |
| 43 | user_id: UUID = Field(foreign_key='user.id', exclude=True) | 47 | user_id: UUID = Field(foreign_key="user.id", exclude=True) |
| 44 | user: User = Relationship() | 48 | user: User = Relationship() |
| 45 | 49 | ||
| 50 | |||
| 46 | class ClientApplication(BaseModel, OAuth2ClientMixin, table=True): | 51 | class ClientApplication(BaseModel, OAuth2ClientMixin, table=True): |
| 47 | name: str | 52 | name: str |
| 48 | 53 | ||
| @@ -52,10 +57,12 @@ class ClientApplication(BaseModel, OAuth2ClientMixin, table=True): | |||
| 52 | for pattern in self.redirect_uris | 57 | for pattern in self.redirect_uris |
| 53 | ) | 58 | ) |
| 54 | 59 | ||
| 60 | |||
| 55 | class AuthCode(BaseModel, OAuth2AuthorizationCodeMixin, table=True): | 61 | class AuthCode(BaseModel, OAuth2AuthorizationCodeMixin, table=True): |
| 56 | user_id: UUID = Field(foreign_key="user.id", ondelete="CASCADE") | 62 | user_id: UUID = Field(foreign_key="user.id", ondelete="CASCADE") |
| 57 | user: User = Relationship() | 63 | user: User = Relationship() |
| 58 | 64 | ||
| 65 | |||
| 59 | class AuthToken(BaseModel, OAuth2TokenMixin, table=True): | 66 | class AuthToken(BaseModel, OAuth2TokenMixin, table=True): |
| 60 | user_id: UUID = Field(foreign_key="user.id", ondelete="CASCADE") | 67 | user_id: UUID = Field(foreign_key="user.id", ondelete="CASCADE") |
| 61 | user: User = Relationship() | 68 | user: User = Relationship() |
diff --git a/db/session.py b/db/session.py index 82c0211..48ef3b6 100644 --- a/db/session.py +++ b/db/session.py | |||
| @@ -1,21 +1,28 @@ | |||
| 1 | from contextlib import contextmanager | 1 | from contextlib import contextmanager |
| 2 | 2 | ||
| 3 | from sqlalchemy.orm import sessionmaker, scoped_session | 3 | from sqlalchemy.orm import scoped_session, sessionmaker |
| 4 | from sqlmodel import create_engine | 4 | from sqlmodel import Session, create_engine |
| 5 | from sqlmodel import Session | ||
| 6 | 5 | ||
| 7 | from conf import DATABASE_URL | 6 | from conf import DATABASE_URL |
| 8 | from utils.json import json_serializer | 7 | from utils.json import json_serializer |
| 9 | 8 | ||
| 10 | 9 | engine = create_engine( | |
| 11 | engine = create_engine(DATABASE_URL, echo=True, future=True, json_serializer=json_serializer, pool_size=100, pool_recycle=3600) | 10 | DATABASE_URL, |
| 11 | echo=True, | ||
| 12 | future=True, | ||
| 13 | json_serializer=json_serializer, | ||
| 14 | pool_size=100, | ||
| 15 | pool_recycle=3600, | ||
| 16 | ) | ||
| 12 | session_factory = sessionmaker(engine, class_=Session) | 17 | session_factory = sessionmaker(engine, class_=Session) |
| 13 | ScopedSession = scoped_session(session_factory=session_factory) | 18 | ScopedSession = scoped_session(session_factory=session_factory) |
| 14 | 19 | ||
| 20 | |||
| 15 | def get_session(): | 21 | def get_session(): |
| 16 | with ScopedSession() as session: | 22 | with ScopedSession() as session: |
| 17 | yield session | 23 | yield session |
| 18 | 24 | ||
| 25 | |||
| 19 | @contextmanager | 26 | @contextmanager |
| 20 | def get_session_context(autocommit=True): | 27 | def get_session_context(autocommit=True): |
| 21 | session = next(get_session()) | 28 | session = next(get_session()) |
