Skip to content
This repository was archived by the owner on Jan 1, 2026. It is now read-only.

Commit d9c3b7e

Browse files
authored
Secure registration and add login with and without OTP (#7)
* Refactor user registration to use PostgreSQL stored procedure and sanitize username input * Refactor user registration to use UserRegister schema and remove UserCreate * Refactor username sanitization: move sanitize_username function to string_utils and remove username.py * Enhance user registration: add HTTPException for existing users and improve code structure * Add docstring to user registration endpoint for clarity * Fix attribute name in User model: update language_id to language_iso_code for clarity * Refactor language preference handling: rename language_iso_code to language_id in User model and registration schema for consistency * Implement email confirmation feature and login endpoint * Enhance login endpoint * Implement 2FA login flow and enhance user registration with OTP secret generation * Move in-memory store declaration for clarity * Bump version to 1.2.0 for API and 0.3.0 for application; update breaking change label in version bump workflow * Refactor tasks.json to improve structure and remove unnecessary runOptions * Add pyotp dependency for OTP functionality * Update default email configuration values in send_email.py for better clarity * Enhance documentation and restructure email utility modules for clarity and maintainability * Update linter configuration and clean up unused init files * Update permissions in super-linter.yml to allow write access for contents * Super-Linter: Fix linting issues * Refactor Super Linter configuration to simplify validation settings * Super-Linter: Fix linting issues * Cleanup: Remove obsolete Super Linter output files and update .gitignore * Update .gitignore to include Super Linter output files * docs: Update module docstring for clarity and formatting * Add email confirmation tests * Super-Linter: Fix linting issues * Update dependency installation to use requirements-dev.txt * Remove confirmation token from email response * Refactor security utility functions and enhance test coverage with new fixtures and tests for email and phone encryption, hashing, and verification token generation. * Add test for non-empty encrypted fields to ensure encryption integrity * Enhance OTP verification function to support HOTP counter parameter * Add test for hash field length to validate SHA-256 output * Add unit tests for OTP verification functionality * Refactor password verification function and add comprehensive tests for verification logic * Refactor password verification tests to use fixtures for hashed and wrong passwords * Refactor test client setup in API tests to use FastAPI app instances directly and remove utility functions for versioned requests. * Implement session and refresh token management in authentication endpoints; add utility functions for token creation and hashing. * Refactor authentication endpoints to improve device info handling and add payload generation fixtures for login and OTP tests * Refactor authentication endpoints to streamline device info handling and remove unnecessary fields from login payloads in schemas and tests. * Refactor login tests to simplify function signatures by removing unnecessary parameters. * Refactor device info extraction and session creation in login endpoint for improved clarity and reusability. * Add user agent handling to session token saving and login process * Remove unused TODO functions as the Database will handle the removal of old session and refresh tokens * Add user agent string to login OTP session and refresh token saving * Add greenlet dependency to requirements for improved concurrency support * Refactor session creation to include user agent string and update tests to remove user_id assertions * Refactor test_login_2fa_required_returns_2fa_token to simplify patching of dependencies * Update version constraints in requirements.txt for better dependency management * Add unit tests for sanitize_username function to validate username sanitization logic * Update version constraints in requirements-dev.txt for build and testing dependencies
1 parent 9fedd95 commit d9c3b7e

39 files changed

Lines changed: 1717 additions & 172 deletions

.devcontainer/devcontainer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
]
1515
}
1616
},
17+
"otherPortsAttributes": {
18+
"onAutoForward": "ignore"
19+
},
1720
"postStartCommand": "pip3 install --user -r requirements-dev.txt",
1821
"postAttachCommand": "python3 -m pytest tests",
1922
"remoteUser": "vscode"

.github/workflows/run-unit-tests.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ jobs:
4545

4646
- name: Install dependencies
4747
run: |
48-
pip install -r requirements.txt
49-
pip install pytest pytest-cov
48+
pip install -r requirements-dev.txt
49+
pip install pytest-cov
5050
5151
- name: Run Pytest (Linux/macOS)
5252
if: runner.os != 'Windows'

.github/workflows/suggest-version-bump.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
BUMP="patch"
5252
echo "$LABELS" | grep -q 'type: feature' && BUMP="minor"
5353
echo "$LABELS" | grep -q 'type: security' && BUMP="minor"
54-
echo "$LABELS" | grep -q 'type: breaking' && BUMP="major"
54+
echo "$LABELS" | grep -q 'special: breaking change' && BUMP="major"
5555
echo "bump=$BUMP" >> "$GITHUB_OUTPUT"
5656
5757
- name: Get latest tag

.github/workflows/super-linter.yml

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
name: Lint
33

44
permissions:
5-
contents: read
5+
contents: write
66
packages: read
77
statuses: write
88

@@ -27,10 +27,7 @@ jobs:
2727
uses: super-linter/super-linter/slim@v7
2828
env:
2929
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30-
VALIDATE_ALL_CODEBASE: false
31-
FILTER_REGEX_EXCLUDE: '(.devcontainer/Dockerfile|.github/pull_request_template.md|.github/ISSUE_TEMPLATE/*.md)'
32-
VALIDATE_PYTHON_ISORT: false
33-
VALIDATE_PYTHON_MYPY: false
30+
DISABLE_ERRORS: true
3431

3532
fix-lint:
3633
name: Fix Lint
@@ -48,13 +45,18 @@ jobs:
4845
VALIDATE_ALL_CODEBASE: false
4946
FILTER_REGEX_EXCLUDE: '(.github/pull_request_template.md|.github/ISSUE_TEMPLATE/*.md)'
5047
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
48+
VALIDATE_DOCKERFILE_HADOLINT: false
5149
VALIDATE_PYTHON_ISORT: false
5250
VALIDATE_PYTHON_MYPY: false
51+
VALIDATE_PYTHON_PYLINT: false
52+
FIX_HTML_PRETTIER: true
53+
FIX_JSON: true
5354
FIX_JSON_PRETTIER: true
5455
FIX_MARKDOWN: true
5556
FIX_MARKDOWN_PRETTIER: true
57+
FIX_PYTHON_BLACK: true
58+
FIX_PYTHON_RUFF: true
5659
FIX_YAML_PRETTIER: true
57-
VALIDATE_DOCKERFILE_HADOLINT: false
5860

5961
- name: Commit and push linting fixes
6062
if: >

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,3 +187,7 @@ cython_debug/
187187
# refer to https://docs.cursor.com/context/ignore-files
188188
.cursorignore
189189
.cursorindexingignore
190+
191+
# # Super Linter output
192+
github_conf/branch_protection_rules.json
193+
super-linter-output/super-linter-summary.md

.prettierrc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77
"singleQuote": true,
88
"overrides": [
99
{
10-
"files": ["*.yml", "*.yaml", "*.md"],
10+
"files": [
11+
"*.yml",
12+
"*.yaml",
13+
"*.md"
14+
],
1115
"options": {
1216
"tabWidth": 2
1317
}

.vscode/settings.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,19 @@
77
"files.trimTrailingWhitespace": true,
88
"files.exclude": {
99
"**/__pycache__": true,
10-
"**/.pytest_cache": true
10+
"**/.pytest_cache": true,
11+
"**/*.egg-info": true
1112
},
1213
"[python]": {
13-
"editor.rulers": [88],
14+
"editor.rulers": [80],
1415
"editor.defaultFormatter": "ms-python.black-formatter",
15-
"editor.formatOnSave": true,
1616
"editor.codeActionsOnSave": {
17-
"source.organizeImports": "explicit"
17+
"source.organizeImports": "always"
1818
}
1919
},
2020
"isort.args": ["--profile", "black"],
2121
"triggerTaskOnSave.tasks": {
22-
"Run on test file": ["tests/**/test_*.py"],
22+
"Run file tests": ["tests/**/test_*.py"],
2323
"Run all tests": ["app/**/*.py", "!tests/**"]
2424
},
2525
"python.testing.unittestEnabled": false,

.vscode/tasks.json

Lines changed: 15 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -5,64 +5,52 @@
55
"label": "Delete old Git branches",
66
"type": "shell",
77
"command": "git fetch --prune && git fetch -p ; git branch -r | awk '{print $1}' | egrep -v -f /dev/fd/0 <(git branch -vv | grep origin) | awk '{print $1}' | xargs git branch -D",
8-
"problemMatcher": [],
98
"presentation": {
109
"showReuseMessage": false
11-
}
10+
},
11+
"problemMatcher": []
1212
},
1313
{
1414
"label": "Package app",
1515
"type": "shell",
1616
"command": "rm -rf build dist *.egg-info && python -m build",
17-
"problemMatcher": [],
18-
"runOptions": {
19-
"runOn": "default"
17+
"group": {
18+
"kind": "build",
19+
"isDefault": true
2020
},
2121
"presentation": {
2222
"panel": "dedicated"
2323
},
24-
"group": {
25-
"kind": "build",
26-
"isDefault": true
27-
}
24+
"problemMatcher": []
2825
},
2926
{
3027
"label": "Run all tests",
3128
"type": "shell",
3229
"command": "python3 -m pytest tests",
3330
"group": "build",
34-
"problemMatcher": [],
35-
"runOptions": {
36-
"runOn": "default"
37-
}
31+
"presentation": {
32+
"close": true
33+
},
34+
"problemMatcher": []
3835
},
3936
{
40-
"label": "Run on test file",
37+
"label": "Run file tests",
4138
"type": "shell",
42-
"command": "python3 -m pytest '${relativeFile}' -v -x",
39+
"command": "python3 -m pytest '${file}' -v -x",
4340
"group": {
4441
"kind": "test"
4542
},
46-
"presentation": {
47-
"close": true
48-
},
49-
"problemMatcher": [],
50-
"runOptions": {
51-
"runOn": "default",
52-
}
43+
"problemMatcher": []
5344
},
5445
{
5546
"label": "Start FastAPI server",
5647
"type": "shell",
5748
"command": "uvicorn app.main:app --reload",
58-
"problemMatcher": [],
59-
"runOptions": {
60-
"runOn": "default"
61-
},
6249
"presentation": {
6350
"panel": "dedicated",
6451
"close": true
65-
}
52+
},
53+
"problemMatcher": []
6654
}
6755
]
6856
}

app/routes/v1/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
from fastapi import FastAPI
66

77
from .endpoints.authentication import router as auth_router
8+
from .endpoints.email import router as email_router
89
from .endpoints.orders import router as order_router
910
from .endpoints.products import router as product_router
1011

11-
__version__ = "1.1.0"
12+
__version__ = "1.2.0"
1213

1314
api = FastAPI(title="ChocoMax Shop API", version=__version__)
1415

1516
api.include_router(auth_router, prefix="/auth", tags=["Authentication"])
17+
api.include_router(email_router, prefix="/email", tags=["Email"])
1618
api.include_router(product_router, prefix="/products", tags=["Products"])
1719
api.include_router(order_router, prefix="/orders", tags=["Orders"])

0 commit comments

Comments
 (0)