Updated to expose auth_app instead of app_route

This commit is contained in:
2025-10-28 20:32:30 +01:00
parent 0138ac247a
commit 5d869e3793
10 changed files with 98 additions and 53 deletions

2
.gitignore vendored
View File

@@ -1,3 +1,5 @@
**/UserDB
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/
*.py[codz] *.py[codz]

View File

@@ -15,4 +15,5 @@ clean-build: clean-package
find . -name "*.pyo" -exec rm -f {} + find . -name "*.pyo" -exec rm -f {} +
# Alias to clean everything # Alias to clean everything
clean: clean-build clean: clean-build
find . -name "UserDB" -exec rm -f {} +

View File

@@ -75,17 +75,18 @@ This example configures myauth to use MongoDB as its backend.
```Python ```Python
from fastapi import FastAPI from fastapi import FastAPI
from myauth import create_app_router_for_mongoDB
from myauth import create_auth_app_for_mongodb
# 1. Initialize FastAPI app # 1. Initialize FastAPI app
app = FastAPI() app = FastAPI()
# 2. Configure repositories for MongoDB # 2. Configure repositories for MongoDB
auth_router = create_app_router_for_mongoDB(mongodb_url="mongodb://localhost:27017", auth_app = create_auth_app_for_mongodb(mongodb_url="mongodb://localhost:27017",
jwt_secret="THIS_NEEDS_TO_BE_CHANGED") jwt_secret="THIS_NEEDS_TO_BE_CHANGED")
# 3. Include the authentication routes # 3. Include the authentication routes
app.include_router(auth_router) app.mount("/auth", auth_app)
@app.get("/") @app.get("/")
@@ -100,19 +101,20 @@ This example configures myauth to use PostgreSQL as its backend.
```Python ```Python
from fastapi import FastAPI from fastapi import FastAPI
from myauth import create_app_router_for_postgreSQL
from myauth import create_auth_app_for_postgresql
# 1. Initialize FastAPI app # 1. Initialize FastAPI app
app = FastAPI() app = FastAPI()
# 2. Configure repositories for MongoDB # 2. Configure repositories for PostgreSQL
auth_router = create_app_router_for_mongoDB(postgresql_url="mongodb://localhost:27017", auth_app = create_auth_app_for_postgresql(postgresql_url="mongodb://localhost:27017",
username="admin", username="admin",
password="password", password="password",
jwt_secret="THIS_NEEDS_TO_BE_CHANGED") jwt_secret="THIS_NEEDS_TO_BE_CHANGED")
# 3. Include the authentication routes # 3. Include the authentication routes
app.include_router(auth_router) app.mount("/auth", auth_app)
@app.get("/") @app.get("/")
@@ -127,16 +129,17 @@ This example configures myauth to use SQLite, which is ideal for development or
```Python ```Python
from fastapi import FastAPI from fastapi import FastAPI
from myauth import create_app_router_for_sqlite
from myauth import create_auth_app_for_sqlite
# 1. Initialize FastAPI app # 1. Initialize FastAPI app
app = FastAPI() app = FastAPI()
# 2. Configure repositories for MongoDB # 2. Configure repositories for MongoDB
auth_router = create_app_router_for_sqlite(db_path="./UserDB", jwt_secret="THIS_NEEDS_TO_BE_CHANGED") auth_app = create_auth_app_for_sqlite(db_path="./UserDB", jwt_secret="THIS_NEEDS_TO_BE_CHANGED")
# 3. Include the authentication routes # 3. Include the authentication routes
app.include_router(auth_router) app.mount("/auth", auth_app)
@app.get("/") @app.get("/")
@@ -159,8 +162,9 @@ pip install "myauth[email]"
```Python ```Python
from fastapi import FastAPI from fastapi import FastAPI
from myauth import create_auth_app_for_sqlite
from myauth.emailing.smtp import SMTPEmailService from myauth.emailing.smtp import SMTPEmailService
from myauth import create_app_router_for_sqlite
# 1. Initialize FastAPI app # 1. Initialize FastAPI app
app = FastAPI() app = FastAPI()
@@ -175,11 +179,11 @@ email_service = SMTPEmailService(
) )
# 3. Configure repositories for MongoDB # 3. Configure repositories for MongoDB
auth_router = create_app_router_for_sqlite(db_path="./UserDB", jwt_secret="THIS_NEEDS_TO_BE_CHANGED", auth_app = create_auth_app_for_sqlite(db_path="./UserDB", jwt_secret="THIS_NEEDS_TO_BE_CHANGED",
email_service=email_service) email_service=email_service)
# 4. Include the authentication routes # 4. Include the authentication routes
app.include_router(auth_router) app.mount("/auth", auth_app)
``` ```
### Option 2: Create a Custom Email Service ### Option 2: Create a Custom Email Service
@@ -189,8 +193,9 @@ If you use a third-party service (like AWS SES, Mailgun) that requires an API, y
```Python ```Python
from fastapi import FastAPI from fastapi import FastAPI
from myauth import create_auth_app_for_sqlite
from myauth.emailing.base import EmailService from myauth.emailing.base import EmailService
from myauth import create_app_router_for_sqlite
# 1. Initialize FastAPI app # 1. Initialize FastAPI app
app = FastAPI() app = FastAPI()
@@ -220,11 +225,11 @@ class CustomEmailService(EmailService):
email_service = CustomEmailService(api_key="YOUR_API_KEY_HERE") email_service = CustomEmailService(api_key="YOUR_API_KEY_HERE")
# 3. Pass your custom service to AuthService # 3. Pass your custom service to AuthService
auth_router = create_app_router_for_sqlite(db_path="./UserDB", jwt_secret="THIS_NEEDS_TO_BE_CHANGED", auth_app = create_auth_app_for_sqlite(db_path="./UserDB", jwt_secret="THIS_NEEDS_TO_BE_CHANGED",
email_service=email_service) email_service=email_service)
# 4. Include the authentication routes # 4. Include the authentication routes
app.include_router(auth_router) app.mount("/auth", auth_app)
``` ```

View File

@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
[project] [project]
name = "myauth" name = "myauth"
version = "0.5.0" version = "0.1.0"
description = "A reusable, modular authentication system for FastAPI applications with pluggable database backends." description = "A reusable, modular authentication system for FastAPI applications with pluggable database backends."
readme = "README.md" readme = "README.md"
authors = [ authors = [

22
src/main.py Normal file
View File

@@ -0,0 +1,22 @@
import uvicorn
from fastapi import FastAPI
from myauth import create_auth_app_for_sqlite
# 1. Initialize FastAPI app
app = FastAPI()
# 2. Configure repositories for MongoDB
auth_app = create_auth_app_for_sqlite(db_path="./UserDB", jwt_secret="THIS_NEEDS_TO_BE_CHANGED")
# 3. Include the authentication routes
app.mount("/auth", auth_app)
@app.get("/")
def read_root():
return {"message": "Application running with MyAuth (SQLite)"}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)

View File

@@ -1,6 +1,9 @@
from .factory import create_sqlite_auth_service, create_app_router_for_sqlite from .factory import create_sqlite_auth_service, create_auth_app_for_sqlite, create_auth_app_for_mongodb, \
create_auth_app_for_postgresql
__all__ = [ __all__ = [
'create_sqlite_auth_service', 'create_sqlite_auth_service',
'create_app_router_for_sqlite', 'create_auth_app_for_sqlite',
'create_auth_app_for_mongodb',
'create_auth_app_for_postgresql'
] ]

View File

@@ -1,3 +1,3 @@
from .routes import create_auth_router from .routes import create_auth_app
__all__ = ["create_auth_router"] __all__ = ["create_auth_app"]

View File

@@ -7,7 +7,7 @@ operations. Routes are organized in an APIRouter with /auth prefix.
from typing import Annotated from typing import Annotated
from fastapi import APIRouter, Depends, HTTPException, status from fastapi import Depends, HTTPException, status, FastAPI
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from ..core.auth import AuthService from ..core.auth import AuthService
@@ -24,7 +24,7 @@ from ..models.user import UserCreate, UserResponse
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/login") oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/login")
def create_auth_router(auth_service: AuthService) -> APIRouter: def create_auth_app(auth_service: AuthService) -> FastAPI:
""" """
Create and configure the authentication router. Create and configure the authentication router.
@@ -40,13 +40,13 @@ def create_auth_router(auth_service: AuthService) -> APIRouter:
Example: Example:
>>> from fastapi import FastAPI >>> from fastapi import FastAPI
>>> from auth_module.api.routes import create_auth_router >>> from myauth.api.routes import create_auth_app
>>> >>>
>>> app = FastAPI() >>> app = FastAPI()
>>> auth_router = create_auth_router(auth_service) >>> auth_api = create_auth_app(auth_service)
>>> app.include_router(auth_router) >>> app.mount(auth_api)
""" """
router = APIRouter(prefix="/auth", tags=["authentication"]) auth_app = FastAPI(prefix="/auth", tags=["authentication"])
def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]) -> UserResponse: def get_current_user(token: Annotated[str, Depends(oauth2_scheme)]) -> UserResponse:
""" """
@@ -65,7 +65,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter:
HTTPException: 401 if token is invalid or expired. HTTPException: 401 if token is invalid or expired.
Example: Example:
>>> @app.get("/protected") >>> @auth_app.get("/protected")
>>> def protected_route(user: UserResponse = Depends(get_current_user)): >>> def protected_route(user: UserResponse = Depends(get_current_user)):
>>> return {"user_id": user.id} >>> return {"user_id": user.id}
""" """
@@ -86,7 +86,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter:
detail=e.message detail=e.message
) )
@router.post( @auth_app.post(
"/register", "/register",
response_model=UserResponse, response_model=UserResponse,
status_code=status.HTTP_201_CREATED, status_code=status.HTTP_201_CREATED,
@@ -128,7 +128,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter:
detail=e.message detail=e.message
) )
@router.post( @auth_app.post(
"/login", "/login",
response_model=AccessTokenResponse, response_model=AccessTokenResponse,
summary="Login with email and password", summary="Login with email and password",
@@ -163,7 +163,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter:
detail=e.message detail=e.message
) )
@router.post( @auth_app.post(
"/logout", "/logout",
status_code=status.HTTP_204_NO_CONTENT, status_code=status.HTTP_204_NO_CONTENT,
summary="Logout user", summary="Logout user",
@@ -185,7 +185,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter:
auth_service.logout(request.refresh_token) auth_service.logout(request.refresh_token)
return None return None
@router.post( @auth_app.post(
"/refresh", "/refresh",
response_model=AccessTokenResponse, response_model=AccessTokenResponse,
summary="Refresh access token", summary="Refresh access token",
@@ -217,7 +217,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter:
detail=e.message detail=e.message
) )
@router.post( @auth_app.post(
"/password-reset-request", "/password-reset-request",
status_code=status.HTTP_200_OK, status_code=status.HTTP_200_OK,
summary="Request password reset", summary="Request password reset",
@@ -252,7 +252,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter:
detail=e.message detail=e.message
) )
@router.post( @auth_app.post(
"/password-reset", "/password-reset",
status_code=status.HTTP_200_OK, status_code=status.HTTP_200_OK,
summary="Reset password with token", summary="Reset password with token",
@@ -284,7 +284,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter:
detail=e.message detail=e.message
) )
@router.post( @auth_app.post(
"/verify-email-request", "/verify-email-request",
status_code=status.HTTP_200_OK, status_code=status.HTTP_200_OK,
summary="Request email verification", summary="Request email verification",
@@ -320,7 +320,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter:
detail=e.message detail=e.message
) )
@router.get( @auth_app.get(
"/verify-email", "/verify-email",
status_code=status.HTTP_200_OK, status_code=status.HTTP_200_OK,
summary="Verify email with token", summary="Verify email with token",
@@ -352,7 +352,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter:
detail=e.message detail=e.message
) )
@router.get( @auth_app.get(
"/me", "/me",
response_model=UserResponse, response_model=UserResponse,
summary="Get current user", summary="Get current user",
@@ -376,4 +376,4 @@ def create_auth_router(auth_service: AuthService) -> APIRouter:
""" """
return current_user return current_user
return router return auth_app

View File

@@ -57,9 +57,9 @@ def create_sqlite_auth_service(db_path: str,
return auth_service return auth_service
def create_app_router_for_sqlite(db_path: str, def create_auth_app_for_sqlite(db_path: str,
jwt_secret: str, jwt_secret: str,
email_service: Optional[EmailService] = None): email_service: Optional[EmailService] = None):
""" """
Creates an application router designed to use with an SQLite database backend. Creates an application router designed to use with an SQLite database backend.
This function initializes an authentication service using the provided database This function initializes an authentication service using the provided database
@@ -74,5 +74,17 @@ def create_app_router_for_sqlite(db_path: str,
:return: An application router configured for handling authentication API routes. :return: An application router configured for handling authentication API routes.
""" """
auth_service = create_sqlite_auth_service(db_path, jwt_secret, email_service) auth_service = create_sqlite_auth_service(db_path, jwt_secret, email_service)
from .api.routes import create_auth_router from .api.routes import create_auth_app
return create_auth_router(auth_service) return create_auth_app(auth_service)
def create_auth_app_for_mongodb(mongodb_url="mongodb://localhost:27017",
jwt_secret="THIS_NEEDS_TO_BE_CHANGED"):
raise NotImplementedError("MongoDB support is not yet implemented.")
def create_auth_app_for_postgresql(postgresql_url="mongodb://localhost:27017",
username="admin",
password="password",
jwt_secret="THIS_NEEDS_TO_BE_CHANGED"):
raise NotImplementedError("PostgreSQL support is not yet implemented.")

View File

@@ -12,7 +12,7 @@ import pytest
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.testclient import TestClient from fastapi.testclient import TestClient
from myauth.api.routes import create_auth_router from myauth.api import create_auth_app
from myauth.core.auth import AuthService from myauth.core.auth import AuthService
from myauth.exceptions import ( from myauth.exceptions import (
UserAlreadyExistsError, UserAlreadyExistsError,
@@ -51,8 +51,8 @@ def test_app(mock_auth_service):
FastAPI application configured for testing. FastAPI application configured for testing.
""" """
app = FastAPI() app = FastAPI()
auth_router = create_auth_router(mock_auth_service) auth_app = create_auth_app(mock_auth_service)
app.include_router(auth_router) app.mount("/auth", auth_app)
return app return app