Compare commits

...

2 Commits

Author SHA1 Message Date
Felipe Cardoso
d49f819469 Expand OAuth documentation and roadmap details
- Updated `README.md` to include OAuth/Social Login (Google, GitHub) with PKCE support under Authentication section.
- Adjusted roadmap and status sections in documentation to reflect completed OAuth/social login implementation.
- Clarified future plans by replacing "Additional authentication methods (OAuth, SSO)" with "SSO/SAML authentication".
2025-11-25 22:28:53 +01:00
Felipe Cardoso
507f2e9c00 Refactor E2E tests and fixtures for improved readability and consistency
- Reformatted assertions in `test_database_workflows.py` for better readability.
- Refactored `postgres_url` transformation logic in `conftest.py` for improved clarity.
- Adjusted import handling in `test_api_contracts.py` to streamline usage of Hypothesis and Schemathesis libraries.
2025-11-25 22:27:11 +01:00
5 changed files with 16 additions and 10 deletions

View File

@@ -60,6 +60,7 @@ Default superuser (change in production):
### Authentication Flow ### Authentication Flow
- **JWT-based**: Access tokens (15 min) + refresh tokens (7 days) - **JWT-based**: Access tokens (15 min) + refresh tokens (7 days)
- **OAuth/Social Login**: Google and GitHub with PKCE support
- **Session tracking**: Database-backed with device info, IP, user agent - **Session tracking**: Database-backed with device info, IP, user agent
- **Token refresh**: Validates JTI in database, not just JWT signature - **Token refresh**: Validates JTI in database, not just JWT signature
- **Authorization**: FastAPI dependencies in `api/dependencies/auth.py` - **Authorization**: FastAPI dependencies in `api/dependencies/auth.py`
@@ -236,7 +237,7 @@ docker-compose exec backend python -c "from app.init_db import init_db; import a
## Current Status (Nov 2025) ## Current Status (Nov 2025)
### Completed Features ✅ ### Completed Features ✅
- Authentication system (JWT with refresh tokens) - Authentication system (JWT with refresh tokens, OAuth/social login)
- Session management (device tracking, revocation) - Session management (device tracking, revocation)
- User management (CRUD, password change) - User management (CRUD, password change)
- Organization system (multi-tenant with RBAC) - Organization system (multi-tenant with RBAC)
@@ -257,7 +258,7 @@ docker-compose exec backend python -c "from app.init_db import init_db; import a
### Planned 🔮 ### Planned 🔮
- GitHub Actions CI/CD - GitHub Actions CI/CD
- Additional languages (Spanish, French, German, etc.) - Additional languages (Spanish, French, German, etc.)
- Additional authentication methods (OAuth, SSO) - SSO/SAML authentication
- Real-time notifications (WebSockets) - Real-time notifications (WebSockets)
- Webhook system - Webhook system
- Background job processing - Background job processing

View File

@@ -52,6 +52,7 @@ Whether you're building a SaaS, an internal tool, or a side project, PragmaStack
### 🔐 **Authentication & Security** ### 🔐 **Authentication & Security**
- JWT-based authentication with access + refresh tokens - JWT-based authentication with access + refresh tokens
- **OAuth/Social Login** (Google, GitHub) with PKCE support
- Session management with device tracking and revocation - Session management with device tracking and revocation
- Password reset flow (email integration ready) - Password reset flow (email integration ready)
- Secure password hashing (bcrypt) - Secure password hashing (bcrypt)
@@ -511,7 +512,7 @@ docker-compose down
## 🛣️ Roadmap & Status ## 🛣️ Roadmap & Status
### ✅ Completed ### ✅ Completed
- [x] Authentication system (JWT, refresh tokens, session management) - [x] Authentication system (JWT, refresh tokens, session management, OAuth)
- [x] User management (CRUD, profile, password change) - [x] User management (CRUD, profile, password change)
- [x] Organization system with RBAC (Owner, Admin, Member) - [x] Organization system with RBAC (Owner, Admin, Member)
- [x] Admin panel (users, organizations, sessions, statistics) - [x] Admin panel (users, organizations, sessions, statistics)
@@ -539,7 +540,7 @@ docker-compose down
- [ ] Dynamic test coverage badges from CI - [ ] Dynamic test coverage badges from CI
- [ ] E2E test coverage reporting - [ ] E2E test coverage reporting
- [ ] Additional languages (Spanish, French, German, etc.) - [ ] Additional languages (Spanish, French, German, etc.)
- [ ] Additional authentication methods (OAuth, SSO) - [ ] SSO/SAML authentication
- [ ] Real-time notifications with WebSockets - [ ] Real-time notifications with WebSockets
- [ ] Webhook system - [ ] Webhook system
- [ ] File upload/storage (S3-compatible) - [ ] File upload/storage (S3-compatible)

View File

@@ -122,9 +122,9 @@ def async_postgres_url(postgres_url) -> str:
Testcontainers returns postgresql+psycopg2:// format. Testcontainers returns postgresql+psycopg2:// format.
""" """
# Testcontainers uses psycopg2 by default, convert to asyncpg # Testcontainers uses psycopg2 by default, convert to asyncpg
return postgres_url.replace("postgresql+psycopg2://", "postgresql+asyncpg://").replace( return postgres_url.replace(
"postgresql://", "postgresql+asyncpg://" "postgresql+psycopg2://", "postgresql+asyncpg://"
) ).replace("postgresql://", "postgresql+asyncpg://")
@pytest_asyncio.fixture @pytest_asyncio.fixture

View File

@@ -15,8 +15,8 @@ Note: Schemathesis v4.x API - filtering is done via include/exclude methods.
import pytest import pytest
try: try:
from hypothesis import settings
from schemathesis import openapi from schemathesis import openapi
from hypothesis import Phase, settings
SCHEMATHESIS_AVAILABLE = True SCHEMATHESIS_AVAILABLE = True
except ImportError: except ImportError:

View File

@@ -40,7 +40,9 @@ class TestUserRegistrationWorkflow:
}, },
) )
assert response.status_code in [200, 201], f"Registration failed: {response.text}" assert response.status_code in [200, 201], (
f"Registration failed: {response.text}"
)
data = response.json() data = response.json()
assert data["email"] == email assert data["email"] == email
assert "id" in data assert "id" in data
@@ -93,7 +95,9 @@ class TestAuthenticationWorkflow:
"last_name": "Test", "last_name": "Test",
}, },
) )
assert reg_resp.status_code in [200, 201], f"Registration failed: {reg_resp.text}" assert reg_resp.status_code in [200, 201], (
f"Registration failed: {reg_resp.text}"
)
# 2. Login # 2. Login
login_resp = await e2e_client.post( login_resp = await e2e_client.post(