feat: Implement user and role management with repositories
- Added RoleRepository and UserRepository for managing roles and users. - Implemented methods for creating, retrieving, and assigning roles to users. - Introduced functions to ensure default roles and an admin user exist in the system. - Updated UnitOfWork to include user and role repositories. - Created new security module for password hashing and JWT token management. - Added tests for authentication flows, including registration, login, and password reset. - Enhanced HTML templates for user registration, login, and password management with error handling. - Added a logo image to the static assets.
This commit is contained in:
76
tests/test_security.py
Normal file
76
tests/test_security.py
Normal file
@@ -0,0 +1,76 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
|
||||
import pytest
|
||||
|
||||
from services.security import (
|
||||
JWTSettings,
|
||||
TokenDecodeError,
|
||||
TokenExpiredError,
|
||||
TokenTypeMismatchError,
|
||||
create_access_token,
|
||||
create_refresh_token,
|
||||
decode_access_token,
|
||||
decode_refresh_token,
|
||||
hash_password,
|
||||
verify_password,
|
||||
)
|
||||
|
||||
|
||||
def test_hash_password_round_trip() -> None:
|
||||
hashed = hash_password("super-secret")
|
||||
|
||||
assert hashed != "super-secret"
|
||||
assert verify_password("super-secret", hashed)
|
||||
assert not verify_password("incorrect", hashed)
|
||||
|
||||
|
||||
def test_verify_password_handles_malformed_hash() -> None:
|
||||
assert not verify_password("secret", "not-a-valid-hash")
|
||||
|
||||
|
||||
def test_access_token_roundtrip() -> None:
|
||||
settings = JWTSettings(secret_key="unit-test-secret")
|
||||
|
||||
token = create_access_token(
|
||||
"user-id-123",
|
||||
settings,
|
||||
scopes=("read", "write"),
|
||||
extra_claims={"custom": "value"},
|
||||
)
|
||||
|
||||
payload = decode_access_token(token, settings)
|
||||
|
||||
assert payload.sub == "user-id-123"
|
||||
assert payload.type == "access"
|
||||
assert payload.scopes == ["read", "write"]
|
||||
|
||||
|
||||
def test_refresh_token_type_mismatch() -> None:
|
||||
settings = JWTSettings(secret_key="unit-test-secret")
|
||||
token = create_refresh_token("user-id-456", settings)
|
||||
|
||||
with pytest.raises(TokenTypeMismatchError):
|
||||
decode_access_token(token, settings)
|
||||
|
||||
|
||||
def test_decode_expired_token() -> None:
|
||||
settings = JWTSettings(secret_key="unit-test-secret")
|
||||
expired_token = create_access_token(
|
||||
"user-id-789",
|
||||
settings,
|
||||
expires_delta=timedelta(seconds=-5),
|
||||
)
|
||||
|
||||
with pytest.raises(TokenExpiredError):
|
||||
decode_access_token(expired_token, settings)
|
||||
|
||||
|
||||
def test_decode_tampered_token() -> None:
|
||||
settings = JWTSettings(secret_key="unit-test-secret")
|
||||
token = create_access_token("user-id-321", settings)
|
||||
tampered = token[:-1] + ("a" if token[-1] != "a" else "b")
|
||||
|
||||
with pytest.raises(TokenDecodeError):
|
||||
decode_access_token(tampered, settings)
|
||||
Reference in New Issue
Block a user