Skip to content

Commit eff4ec8

Browse files
authored
Merge pull request #9 from IDTS-LAB/database-foreign-key-restoration-e7a15
Update from task 4c631340-f28c-44ee-a658-3d32babe7a15
2 parents e4349c7 + f488307 commit eff4ec8

14 files changed

Lines changed: 134 additions & 234 deletions

File tree

.gitignore

Lines changed: 35 additions & 191 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
# Byte-compiled / optimized / DLL files
1+
```
2+
# Python
23
__pycache__/
3-
*.py[codz]
4+
*.py[cod]
45
*$py.class
5-
6-
# C extensions
76
*.so
8-
9-
# Distribution / packaging
107
.Python
118
build/
129
develop-eggs/
@@ -20,204 +17,51 @@ parts/
2017
sdist/
2118
var/
2219
wheels/
23-
share/python-wheels/
2420
*.egg-info/
2521
.installed.cfg
2622
*.egg
2723
MANIFEST
2824

29-
# PyInstaller
30-
# Usually these files are written by a python script from a template
31-
# before PyInstaller builds the exe, so as to inject date/other infos into it.
32-
*.manifest
33-
*.spec
34-
35-
# Installer logs
36-
pip-log.txt
37-
pip-delete-this-directory.txt
38-
39-
# Unit test / coverage reports
40-
htmlcov/
41-
.tox/
42-
.nox/
43-
.coverage
44-
.coverage.*
45-
.cache
46-
nosetests.xml
47-
coverage.xml
48-
*.cover
49-
*.py.cover
50-
*.lcov
51-
.hypothesis/
52-
.pytest_cache/
53-
cover/
25+
# Virtual environments
26+
venv/
27+
ENV/
28+
env/
29+
.venv/
30+
.env/
5431

55-
# Translations
56-
*.mo
57-
*.pot
32+
# IDE
33+
.vscode/
34+
.idea/
35+
*.swp
36+
*.swo
5837

59-
# Django stuff:
38+
# Logs
6039
*.log
61-
local_settings.py
62-
db.sqlite3
63-
db.sqlite3-journal
64-
65-
# Flask stuff:
66-
instance/
67-
.webassets-cache
68-
69-
# Scrapy stuff:
70-
.scrapy
71-
72-
# Sphinx documentation
73-
docs/_build/
74-
75-
# PyBuilder
76-
.pybuilder/
77-
target/
78-
79-
# Jupyter Notebook
80-
.ipynb_checkpoints
81-
82-
# IPython
83-
profile_default/
84-
ipython_config.py
85-
86-
# pyenv
87-
# For a library or package, you might want to ignore these files since the code is
88-
# intended to run in multiple environments; otherwise, check them in:
89-
# .python-version
90-
91-
# pipenv
92-
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
93-
# However, in case of collaboration, if having platform-specific dependencies or dependencies
94-
# having no cross-platform support, pipenv may install dependencies that don't work, or not
95-
# install all needed dependencies.
96-
# Pipfile.lock
97-
98-
# UV
99-
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
100-
# This is especially recommended for binary packages to ensure reproducibility, and is more
101-
# commonly ignored for libraries.
102-
# uv.lock
103-
104-
# poetry
105-
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
106-
# This is especially recommended for binary packages to ensure reproducibility, and is more
107-
# commonly ignored for libraries.
108-
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
109-
# poetry.lock
110-
# poetry.toml
111-
112-
# pdm
113-
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
114-
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
115-
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
116-
# pdm.lock
117-
# pdm.toml
118-
.pdm-python
119-
.pdm-build/
120-
121-
# pixi
122-
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
123-
# pixi.lock
124-
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
125-
# in the .venv directory. It is recommended not to include this directory in version control.
126-
.pixi/*
127-
!.pixi/config.toml
12840

129-
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
130-
__pypackages__/
131-
132-
# Celery stuff
133-
celerybeat-schedule*
134-
celerybeat.pid
135-
136-
# Redis
137-
*.rdb
138-
*.aof
139-
*.pid
140-
141-
# RabbitMQ
142-
mnesia/
143-
rabbitmq/
144-
rabbitmq-data/
145-
146-
# ActiveMQ
147-
activemq-data/
148-
149-
# SageMath parsed files
150-
*.sage.py
151-
152-
# Environments
41+
# Environment variables
15342
.env
154-
.envrc
155-
.venv
156-
env/
157-
venv/
158-
ENV/
159-
env.bak/
160-
venv.bak/
43+
.env.local
44+
*.env.*
16145

162-
# Spyder project settings
163-
.spyderproject
164-
.spyproject
165-
166-
# Rope project settings
167-
.ropeproject
168-
169-
# mkdocs documentation
170-
/site
46+
# Coverage reports
47+
.coverage
48+
htmlcov/
49+
.coverage.*
50+
.coverage.xml
51+
coverage.xml
17152

172-
# mypy
53+
# Testing
54+
.pytest_cache/
17355
.mypy_cache/
174-
.dmypy.json
175-
dmypy.json
176-
177-
# Pyre type checker
178-
.pyre/
179-
180-
# pytype static type analyzer
181-
.pytype/
182-
183-
# Cython debug symbols
184-
cython_debug/
185-
186-
# PyCharm
187-
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
188-
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
189-
# and can be added to the global gitignore or merged into this file. For a more nuclear
190-
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
191-
# .idea/
192-
193-
# Abstra
194-
# Abstra is an AI-powered process automation framework.
195-
# Ignore directories containing user credentials, local state, and settings.
196-
# Learn more at https://abstra.io/docs
197-
.abstra/
198-
199-
# Visual Studio Code
200-
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
201-
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
202-
# and can be added to the global gitignore or merged into this file. However, if you prefer,
203-
# you could uncomment the following to ignore the entire vscode folder
204-
# .vscode/
205-
# Temporary file for partial code execution
206-
tempCodeRunnerFile.py
207-
208-
# Ruff stuff:
209-
.ruff_cache/
210-
211-
# PyPI configuration file
212-
.pypirc
21356

214-
# Marimo
215-
marimo/_static/
216-
marimo/_lsp/
217-
__marimo__/
57+
# Database
58+
*.sqlite
59+
*.db
21860

219-
# Streamlit
220-
.streamlit/secrets.toml
61+
# Alembic
62+
alembic/versions/*.py
22163

222-
# Isolated development worktrees
223-
.worktrees/
64+
# OS
65+
.DS_Store
66+
Thumbs.db
67+
```

alembic/env.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@
3636
UserHasRoleModel, # noqa: F401
3737
)
3838
from src.modules.todo.infrastructure.models.todo_model import TodoModel # noqa: F401
39-
from src.modules.user.infrastructure.models.refresh_token_model import (
40-
UserSessionModel, # noqa: F401
41-
)
42-
from src.modules.user.infrastructure.models.user_model import UserModel # noqa: F401
39+
from src.modules.user.infrastructure import models as user_models # noqa: F401
4340
from src.shared.database.model import Base
4441

4542
settings = get_settings()

src/modules/authorization/infrastructure/models/permission_model.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from uuid import UUID
22

3-
from sqlalchemy import Index, String, UniqueConstraint
3+
from sqlalchemy import ForeignKey, Index, String, UniqueConstraint
44
from sqlalchemy.orm import Mapped, mapped_column, relationship
55

66
from src.shared.database.mixin.timestamp import SoftDeleteMixin, TimeStampMixin
@@ -24,7 +24,10 @@ class PermissionModel(Base, TimeStampMixin, SoftDeleteMixin):
2424
)
2525

2626
key: Mapped[str] = mapped_column(String(255), unique=True, nullable=False)
27-
resource_id: Mapped[UUID] = mapped_column(nullable=False)
27+
resource_id: Mapped[UUID] = mapped_column(
28+
ForeignKey("authorization_resources.id"),
29+
nullable=False,
30+
)
2831
resource: Mapped[str] = mapped_column(String(100), nullable=False)
2932
action: Mapped[str] = mapped_column(String(100), nullable=False)
3033
description: Mapped[str | None] = mapped_column(String(255), nullable=True)

src/modules/authorization/infrastructure/models/role_permission_model.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from uuid import UUID
22

3-
from sqlalchemy import Index, UniqueConstraint
3+
from sqlalchemy import ForeignKey, Index, UniqueConstraint
44
from sqlalchemy.orm import Mapped, mapped_column, relationship
55

66
from src.shared.database.model import Base
@@ -23,8 +23,11 @@ class RolePermissionModel(Base):
2323
Index("ix_role_permissions_permission_id", "permission_id"),
2424
)
2525

26-
role_id: Mapped[UUID] = mapped_column(nullable=False)
27-
permission_id: Mapped[UUID] = mapped_column(nullable=False)
26+
role_id: Mapped[UUID] = mapped_column(ForeignKey("roles.id"), nullable=False)
27+
permission_id: Mapped[UUID] = mapped_column(
28+
ForeignKey("permissions.id"),
29+
nullable=False,
30+
)
2831

2932
# Relationships
3033
role: Mapped["RoleModel"] = relationship( # type: ignore[name-defined]

src/modules/authorization/infrastructure/models/user_has_role_model.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from uuid import UUID
22

3-
from sqlalchemy import Index, UniqueConstraint
3+
from sqlalchemy import ForeignKey, Index, UniqueConstraint
44
from sqlalchemy.orm import Mapped, mapped_column, relationship
55

66
from src.modules.user.infrastructure.models.user_model import UserModel
@@ -23,8 +23,8 @@ class UserHasRoleModel(Base):
2323
Index("ix_user_has_roles_role_id", "role_id"),
2424
)
2525

26-
user_id: Mapped[UUID] = mapped_column(nullable=False)
27-
role_id: Mapped[UUID] = mapped_column(nullable=False)
26+
user_id: Mapped[UUID] = mapped_column(ForeignKey("users.id"), nullable=False)
27+
role_id: Mapped[UUID] = mapped_column(ForeignKey("roles.id"), nullable=False)
2828

2929
# Relationships
3030
user: Mapped["UserModel"] = relationship( # type: ignore[name-defined]

src/modules/todo/infrastructure/models/todo_model.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import uuid
22

3-
from sqlalchemy import Boolean, String
3+
from sqlalchemy import Boolean, ForeignKey, String
44
from sqlalchemy.orm import Mapped, mapped_column
55

66
from src.shared.database.model import Base
@@ -13,4 +13,4 @@ class TodoModel(Base, TimeStampMixin, SoftDeleteMixin):
1313
title: Mapped[str] = mapped_column(String(255))
1414
description: Mapped[str | None] = mapped_column(String(500), nullable=True)
1515
is_completed: Mapped[bool] = mapped_column(Boolean, default=False)
16-
user_id: Mapped[uuid.UUID] = mapped_column()
16+
user_id: Mapped[uuid.UUID] = mapped_column(ForeignKey("users.id"))

src/modules/user/infrastructure/models/refresh_token_model.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from datetime import datetime
2+
from uuid import UUID
23

3-
from sqlalchemy import Boolean, DateTime, Index, String
4+
from sqlalchemy import Boolean, DateTime, ForeignKey, Index, String
45
from sqlalchemy.orm import Mapped, mapped_column, relationship
56

67
from src.shared.database.mixin.timestamp import SoftDeleteMixin, TimeStampMixin
@@ -23,10 +24,7 @@ class UserSessionModel(Base, TimeStampMixin, SoftDeleteMixin):
2324
Index("ix_user_sessions_device_info", "device_info"),
2425
)
2526

26-
user_id: Mapped[str] = mapped_column(
27-
String(36), # UUID as string for FK
28-
nullable=False,
29-
)
27+
user_id: Mapped[UUID] = mapped_column(ForeignKey("users.id"), nullable=False)
3028

3129
# Session Token (hashed for security)
3230
refresh_token_hash: Mapped[str] = mapped_column(String(255), nullable=False)

src/modules/user/infrastructure/models/user_address_model.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
from sqlalchemy import Boolean, Index, String
1+
from uuid import UUID
2+
3+
from sqlalchemy import Boolean, ForeignKey, Index, String
24
from sqlalchemy.orm import Mapped, mapped_column, relationship
35

46
from src.modules.user.infrastructure.models.user_model import UserModel
@@ -21,10 +23,7 @@ class UserAddressModel(Base, TimeStampMixin, SoftDeleteMixin):
2123
Index("ix_user_addresses_country", "country"),
2224
)
2325

24-
user_id: Mapped[str] = mapped_column(
25-
String(36), # UUID as string for FK
26-
nullable=False,
27-
)
26+
user_id: Mapped[UUID] = mapped_column(ForeignKey("users.id"), nullable=False)
2827

2928
# Address Label (home, billing, shipping, work, etc.)
3029
label: Mapped[str] = mapped_column(String(100), nullable=False)

0 commit comments

Comments
 (0)