Skip to content

Commit 567858c

Browse files
fiqrikm18qwen-intl
andauthored
Development (#11)
* fix: login response * feat: add email verification on register * feat: add import boundary * refactor: move authentication app to auth * feat: implement sync commumication * feat: implement sync commumication * feat: implement sync commumication * fix: import path * refactor: restructure authorization module to follow DDD + Clean Architecture + CQRS - Move authorization from core to dedicated module with full layer separation - Create application layer with CQRS pattern (commands, queries, handlers) - Rename 'presenter' to 'presentation' for consistency - Organize domain services and infrastructure repositories properly - Fix directory structure to match standard DDD boundaries - Update imports and dependencies accordingly * Add authorization infrastructure with Casbin policy management - New SQLAlchemy models for authorization including CasbinRuleModel, PermissionModel, AuthorizationResourceModel, RoleModel, RolePermissionModel, and UserHasRoleModel with proper relationships and constraints - Implementation of SQLAlchemyCasbinPolicyRepository with full CRUD operations for roles, permissions, and policies including cursor-based pagination - CasbinAuthorizationService integrating with the repository layer and providing dynamic enforcer building for access control decisions - Infrastructure setup for authorization module with proper domain entities, services, and repository patterns following the application architecture This commit establishes a comprehensive authorization system backend with database persistence, supporting role-based access control through Casbin policies and efficient data management through SQLAlchemy ORM. * fix: invalid import path * docs: update readme * Title: Refactor authorization infrastructure and update imports Key features implemented: - Updated import paths in CasbinAuthorizationService to reflect new core infrastructure location - Updated import paths in GetRoleQueryHandler to reflect new core infrastructure location - Updated import paths in dependency injection module to reflect new core infrastructure location - Updated import paths in permission router to reflect new core infrastructure location - Updated import paths in role router to reflect new core infrastructure location - Removed old authorization infrastructure modules and models from src/modules/authorization/infrastructure/ - Streamlined .gitignore file with consolidated ignore patterns The changes consolidate the authorization infrastructure under the core module and update all relevant imports across the application, removing redundant legacy infrastructure files. * refactor: move infrastructure to module from core * Title: Implement Normalized User Domain with DDD Structure and Update Handlers Key features implemented: - New docs/NORMALIZED_USER_DOMAIN.md detailing normalized schema design rationale and structure - New src/modules/user/infrastructure/models/__init__.py aggregating all user domain models - New src/modules/user/infrastructure/models/user_*_model.py files for normalized user entities (address, contact, profile, security, settings, verification) - Updated src/modules/authorization/infrastructure/models/*_model.py with indexing optimizations - Updated src/modules/user/application/auth/login_user/handler.py to reference password_hash correctly - Updated src/modules/user/application/auth/register_user/handler.py to use password_hash in User.create - Updated src/modules/user/application/detail_user/handler.py to fetch user with relations via get_by_id_with_relations - Updated src/modules/user/domain/entities/user.py with normalized entity structure including profile, settings, security - Updated src/modules/user/domain/repositories/user_repository.py interface for relation handling - Updated src/modules/user/infrastructure/models/user_model.py to reflect normalized structure and relationships - Updated src/modules/user/infrastructure/repositories/user_repository.py implementation for normalized data access The changes implement a fully normalized user domain following DDD principles, separating concerns into distinct bounded contexts while updating application handlers to utilize the new structure. The repository layer now supports fetching related user data efficiently. * fix: import path * Refactor authorization models to remove circular imports and update gitignore - Updated .gitignore with standard Python project exclusions and removed redundant entries - Modified PermissionModel to remove direct imports and use string references for relationships - Modified AuthorizationResourceModel to remove direct imports and use string references for relationships - Modified RolePermissionModel to remove direct imports and use string references for relationships - Modified UserHasRoleModel to remove direct imports and use string references for relationships This change eliminates circular import dependencies between authorization models while maintaining all existing functionality and relationships. The gitignore file now follows standard conventions for Python projects. * update branch * update branch * chore: remove all __pycache__ * chore: update gitignore * chore: update gitignore * fix: update migration * docs: design normalized database seed update * docs: plan normalized database seed update * chore: ignore local worktrees * test: cover normalized user seeding * fix: align user seed with normalized schema * docs: explain normalized database seeding * Title: Restore Database Foreign Keys and Normalize User Identifiers Key features implemented: - Added comprehensive ORM relationship and foreign key metadata regression tests in test_database_relationships.py - Restored missing foreign key constraints in authorization models (permission, role_permission, user_has_role) and todo model - Converted normalized user identifier columns across 7 user models to UUID type with proper foreign key references - Updated Alembic environment to load complete user model package for accurate metadata reflection - Created corrective Alembic migration to convert string user IDs to UUID and create all missing foreign key constraints - Added contract tests for the corrective migration covering both upgrade and downgrade operations The implementation restores all 13 intended foreign keys while ensuring normalized user identifiers use UUID consistently, enabling successful database seeding without SQLAlchemy mapper errors. * docs: design foreign key restoration * docs: plan foreign key restoration * fix: table data type * fix: todo owner * chore: update initial schemas * fix: update detail /me endpoint * Implement user account lockout and multi-method 2FA - Added TwoFactorAuthService supporting TOTP (Google Authenticator) and email-based 2FA with backup codes - Implemented 2FA setup, verification, disabling, and regeneration commands with corresponding handlers - Created new API router and request/response schemas for 2FA endpoints - Updated LoginUserCommandHandler to integrate 2FA verification and temporary token generation - Enhanced account lockout mechanism to prevent brute force login attempts - Added dependency injection for new 2FA handlers and integrated with existing auth flow * feat: 2fa implementation --------- Co-authored-by: qwen.ai[bot] <qwenlm-intl@service.alibaba.com>
1 parent b0910d7 commit 567858c

190 files changed

Lines changed: 6015 additions & 3370 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,81 @@
1+
# Application metadata and runtime environment.
12
APP_NAME=Todo Modulith API
23
APP_ENV=production
4+
FRONTEND_URL=http://localhost:3000
35

6+
# Local service credentials used by Docker Compose.
47
POSTGRES_USER=postgres
58
POSTGRES_PASSWORD=
69
POSTGRES_DB=todo_db
710
REDIS_PASSWORD=
811

12+
# Database connection string and SQLAlchemy pool tuning.
913
DATABASE_URL=
1014
DATABASE_POOL_SIZE=20
1115
DATABASE_MAX_OVERFLOW=10
1216
DATABASE_POOL_TIMEOUT=30
1317
DATABASE_POOL_RECYCLE=3600
1418

19+
# Redis connection used by shared infrastructure such as rate limiting or caching.
1520
REDIS_URL=
1621

22+
# JWT signing secret. Change this in every deployed environment.
1723
SECRET_KEY=
1824

25+
# Maximum request body size in bytes.
1926
MAX_REQUEST_SIZE_MB=5242880 #5mb
2027

28+
# JWT signing, validation, and token lifetime settings.
2129
ALGORITHM=HS256
2230
JWT_ISSUER=todo-modulith-api
2331
JWT_AUDIENCE=todo-modulith-client
2432
ACCESS_TOKEN_EXPIRE_MINUTES=30
2533
REFRESH_TOKEN_EXPIRE_MINUTES=10080
2634

35+
# API rate limit rule.
2736
RATE_LIMIT="100/minute"
2837

38+
# CORS settings for browser clients.
2939
CORS_ALLOW_ORIGINS=http://localhost:3000
3040
CORS_ALLOW_METHODS=*
3141
CORS_ALLOW_HEADERS=*
3242

43+
# Content Security Policy header value.
3344
SECURITY_CONTENT_SECURITY_POLICY=default-src 'self'; frame-ancestors 'none'
3445

46+
# Idempotency key retention time in seconds.
3547
IDEMPOTENCY_TTL_SECONDS=86400
3648

49+
# Account lockout thresholds used to slow repeated failed login attempts.
3750
ACCOUNT_LOCKOUT_MAX_ATTEMPTS=5
3851
ACCOUNT_LOCKOUT_WINDOW_MINUTES=15
3952
ACCOUNT_LOCKOUT_DURATION_MINUTES=15
4053

54+
# Logging output format for application logs.
4155
LOG_FORMAT=json
4256

57+
# Email provider selection. Options: ses, sendgrid, smtp.
58+
EMAIL_PROVIDER=ses
59+
60+
# AWS SES configuration.
61+
AWS_REGION=us-east-1
62+
AWS_ACCESS_KEY_ID=
63+
AWS_SECRET_ACCESS_KEY=
64+
SES_FROM_EMAIL=noreply@example.com
65+
66+
# SendGrid configuration.
67+
SENDGRID_API_KEY=
68+
SENDGRID_FROM_EMAIL=noreply@example.com
69+
70+
# SMTP configuration for Gmail or other SMTP providers.
71+
SMTP_HOST=
72+
SMTP_PORT=587
73+
SMTP_USERNAME=
74+
SMTP_PASSWORD=
75+
SMTP_FROM_EMAIL=noreply@example.com
76+
SMTP_USE_TLS=true
77+
78+
# Optional admin and development users created by database seeders.
4379
SEED_ADMIN_EMAIL=
4480
SEED_ADMIN_PASSWORD=
4581
SEED_ADMIN_USERNAME=admin

.gitignore

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,23 @@
1-
# Poetry specific files
2-
.venv/
3-
/dist/
4-
/poetry.toml
5-
6-
# Python bytecode and caches
7-
__pycache__/
1+
```
82
*.pyc
9-
*.pyo
10-
*.pyd
11-
.pytest_cache/
12-
.mypy_cache/
13-
.ruff_cache/
14-
.cache/
15-
16-
# Environment variables (secret keys)
3+
__pycache__/
4+
*.log
5+
*.tmp
6+
*.swp
177
.env
18-
19-
# IDE settings
8+
.env.local
9+
.env.*
2010
.vscode/
2111
.idea/
12+
dist/
13+
build/
14+
target/
15+
.venv/
16+
venv/
17+
node_modules/
18+
.mypy_cache/
19+
.pytest_cache/
20+
.coverage
21+
coverage/
22+
htmlcov/
23+
```

.idea/.gitignore

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/fastapi-modulith.iml

Lines changed: 13 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/inspectionProfiles/Project_Default.xml

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/inspectionProfiles/profiles_settings.xml

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/misc.xml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/modules.xml

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.importlinter

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
[importlinter]
2+
root_package = src
3+
4+
[importlinter:contract:todo-cross-module-boundary]
5+
name = Todo module only imports public contracts from other modules
6+
type = forbidden
7+
allow_indirect_imports = True
8+
source_modules =
9+
src.modules.todo
10+
forbidden_modules =
11+
src.modules.user.application
12+
src.modules.user.domain
13+
src.modules.user.infrastructure
14+
src.modules.user.presentation
15+
src.modules.authorization.application
16+
src.modules.authorization.domain
17+
src.modules.authorization.infrastructure
18+
src.modules.authorization.presenter
19+
20+
[importlinter:contract:user-cross-module-boundary]
21+
name = User module only imports public contracts from other modules
22+
type = forbidden
23+
allow_indirect_imports = True
24+
source_modules =
25+
src.modules.user
26+
forbidden_modules =
27+
src.modules.todo.application
28+
src.modules.todo.domain
29+
src.modules.todo.infrastructure
30+
src.modules.todo.presentation
31+
src.modules.authorization.application
32+
src.modules.authorization.domain
33+
src.modules.authorization.infrastructure
34+
src.modules.authorization.presenter
35+
36+
[importlinter:contract:authorization-cross-module-boundary]
37+
name = Authorization module only imports public contracts from other modules
38+
type = forbidden
39+
allow_indirect_imports = True
40+
source_modules =
41+
src.modules.authorization
42+
forbidden_modules =
43+
src.modules.todo.application
44+
src.modules.todo.domain
45+
src.modules.todo.infrastructure
46+
src.modules.todo.presentation
47+
src.modules.user.application
48+
src.modules.user.domain
49+
src.modules.user.infrastructure
50+
src.modules.user.presentation

.pre-commit-config.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
repos:
2+
- repo: local
3+
hooks:
4+
- id: import-linter
5+
name: import-linter
6+
entry: poetry run lint-imports
7+
language: system
8+
pass_filenames: false

0 commit comments

Comments
 (0)