diff --git a/.gitignore b/.gitignore index 1f7286a..ab1616a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +**/UserDB + # Byte-compiled / optimized / DLL files __pycache__/ *.py[codz] diff --git a/Makefile b/Makefile index d4147ca..f6b34ec 100644 --- a/Makefile +++ b/Makefile @@ -15,4 +15,5 @@ clean-build: clean-package find . -name "*.pyo" -exec rm -f {} + # Alias to clean everything -clean: clean-build \ No newline at end of file +clean: clean-build + find . -name "UserDB" -exec rm -f {} + \ No newline at end of file diff --git a/README.md b/README.md index a2e2c76..5a9cf6b 100644 --- a/README.md +++ b/README.md @@ -75,17 +75,18 @@ This example configures myauth to use MongoDB as its backend. ```Python from fastapi import FastAPI -from myauth import create_app_router_for_mongoDB + +from myauth import create_auth_app_for_mongodb # 1. Initialize FastAPI app app = FastAPI() # 2. Configure repositories for MongoDB -auth_router = create_app_router_for_mongoDB(mongodb_url="mongodb://localhost:27017", - jwt_secret="THIS_NEEDS_TO_BE_CHANGED") +auth_app = create_auth_app_for_mongodb(mongodb_url="mongodb://localhost:27017", + jwt_secret="THIS_NEEDS_TO_BE_CHANGED") # 3. Include the authentication routes -app.include_router(auth_router) +app.mount("/auth", auth_app) @app.get("/") @@ -100,19 +101,20 @@ This example configures myauth to use PostgreSQL as its backend. ```Python from fastapi import FastAPI -from myauth import create_app_router_for_postgreSQL + +from myauth import create_auth_app_for_postgresql # 1. Initialize FastAPI app app = FastAPI() -# 2. Configure repositories for MongoDB -auth_router = create_app_router_for_mongoDB(postgresql_url="mongodb://localhost:27017", - username="admin", - password="password", - jwt_secret="THIS_NEEDS_TO_BE_CHANGED") +# 2. Configure repositories for PostgreSQL +auth_app = create_auth_app_for_postgresql(postgresql_url="mongodb://localhost:27017", + username="admin", + password="password", + jwt_secret="THIS_NEEDS_TO_BE_CHANGED") # 3. Include the authentication routes -app.include_router(auth_router) +app.mount("/auth", auth_app) @app.get("/") @@ -127,16 +129,17 @@ This example configures myauth to use SQLite, which is ideal for development or ```Python from fastapi import FastAPI -from myauth import create_app_router_for_sqlite + +from myauth import create_auth_app_for_sqlite # 1. Initialize FastAPI app app = FastAPI() # 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 -app.include_router(auth_router) +app.mount("/auth", auth_app) @app.get("/") @@ -159,8 +162,9 @@ pip install "myauth[email]" ```Python from fastapi import FastAPI + +from myauth import create_auth_app_for_sqlite from myauth.emailing.smtp import SMTPEmailService -from myauth import create_app_router_for_sqlite # 1. Initialize FastAPI app app = FastAPI() @@ -175,11 +179,11 @@ email_service = SMTPEmailService( ) # 3. Configure repositories for MongoDB -auth_router = create_app_router_for_sqlite(db_path="./UserDB", jwt_secret="THIS_NEEDS_TO_BE_CHANGED", - email_service=email_service) +auth_app = create_auth_app_for_sqlite(db_path="./UserDB", jwt_secret="THIS_NEEDS_TO_BE_CHANGED", + email_service=email_service) # 4. Include the authentication routes -app.include_router(auth_router) +app.mount("/auth", auth_app) ``` ### 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 from fastapi import FastAPI + +from myauth import create_auth_app_for_sqlite from myauth.emailing.base import EmailService -from myauth import create_app_router_for_sqlite # 1. Initialize FastAPI app app = FastAPI() @@ -220,11 +225,11 @@ class CustomEmailService(EmailService): email_service = CustomEmailService(api_key="YOUR_API_KEY_HERE") # 3. Pass your custom service to AuthService -auth_router = create_app_router_for_sqlite(db_path="./UserDB", jwt_secret="THIS_NEEDS_TO_BE_CHANGED", - email_service=email_service) +auth_app = create_auth_app_for_sqlite(db_path="./UserDB", jwt_secret="THIS_NEEDS_TO_BE_CHANGED", + email_service=email_service) # 4. Include the authentication routes -app.include_router(auth_router) +app.mount("/auth", auth_app) ``` diff --git a/pyproject.toml b/pyproject.toml index 7ca5cb3..81ee0ec 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta" [project] name = "myauth" -version = "0.5.0" +version = "0.1.0" description = "A reusable, modular authentication system for FastAPI applications with pluggable database backends." readme = "README.md" authors = [ diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..14a6497 --- /dev/null +++ b/src/main.py @@ -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) diff --git a/src/myauth/__init__.py b/src/myauth/__init__.py index d7c98f9..0fccef0 100644 --- a/src/myauth/__init__.py +++ b/src/myauth/__init__.py @@ -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__ = [ 'create_sqlite_auth_service', - 'create_app_router_for_sqlite', + 'create_auth_app_for_sqlite', + 'create_auth_app_for_mongodb', + 'create_auth_app_for_postgresql' ] diff --git a/src/myauth/api/__init__.py b/src/myauth/api/__init__.py index 17d4842..58d5fc0 100644 --- a/src/myauth/api/__init__.py +++ b/src/myauth/api/__init__.py @@ -1,3 +1,3 @@ -from .routes import create_auth_router +from .routes import create_auth_app -__all__ = ["create_auth_router"] \ No newline at end of file +__all__ = ["create_auth_app"] \ No newline at end of file diff --git a/src/myauth/api/routes.py b/src/myauth/api/routes.py index 292eeae..9de8485 100644 --- a/src/myauth/api/routes.py +++ b/src/myauth/api/routes.py @@ -7,7 +7,7 @@ operations. Routes are organized in an APIRouter with /auth prefix. 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 ..core.auth import AuthService @@ -24,7 +24,7 @@ from ..models.user import UserCreate, UserResponse 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. @@ -40,13 +40,13 @@ def create_auth_router(auth_service: AuthService) -> APIRouter: Example: >>> from fastapi import FastAPI - >>> from auth_module.api.routes import create_auth_router + >>> from myauth.api.routes import create_auth_app >>> >>> app = FastAPI() - >>> auth_router = create_auth_router(auth_service) - >>> app.include_router(auth_router) + >>> auth_api = create_auth_app(auth_service) + >>> 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: """ @@ -65,7 +65,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter: HTTPException: 401 if token is invalid or expired. Example: - >>> @app.get("/protected") + >>> @auth_app.get("/protected") >>> def protected_route(user: UserResponse = Depends(get_current_user)): >>> return {"user_id": user.id} """ @@ -86,7 +86,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter: detail=e.message ) - @router.post( + @auth_app.post( "/register", response_model=UserResponse, status_code=status.HTTP_201_CREATED, @@ -128,7 +128,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter: detail=e.message ) - @router.post( + @auth_app.post( "/login", response_model=AccessTokenResponse, summary="Login with email and password", @@ -163,7 +163,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter: detail=e.message ) - @router.post( + @auth_app.post( "/logout", status_code=status.HTTP_204_NO_CONTENT, summary="Logout user", @@ -185,7 +185,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter: auth_service.logout(request.refresh_token) return None - @router.post( + @auth_app.post( "/refresh", response_model=AccessTokenResponse, summary="Refresh access token", @@ -217,7 +217,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter: detail=e.message ) - @router.post( + @auth_app.post( "/password-reset-request", status_code=status.HTTP_200_OK, summary="Request password reset", @@ -252,7 +252,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter: detail=e.message ) - @router.post( + @auth_app.post( "/password-reset", status_code=status.HTTP_200_OK, summary="Reset password with token", @@ -284,7 +284,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter: detail=e.message ) - @router.post( + @auth_app.post( "/verify-email-request", status_code=status.HTTP_200_OK, summary="Request email verification", @@ -320,7 +320,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter: detail=e.message ) - @router.get( + @auth_app.get( "/verify-email", status_code=status.HTTP_200_OK, summary="Verify email with token", @@ -352,7 +352,7 @@ def create_auth_router(auth_service: AuthService) -> APIRouter: detail=e.message ) - @router.get( + @auth_app.get( "/me", response_model=UserResponse, summary="Get current user", @@ -376,4 +376,4 @@ def create_auth_router(auth_service: AuthService) -> APIRouter: """ return current_user - return router + return auth_app diff --git a/src/myauth/factory.py b/src/myauth/factory.py index 31c512c..c10ace0 100644 --- a/src/myauth/factory.py +++ b/src/myauth/factory.py @@ -57,9 +57,9 @@ def create_sqlite_auth_service(db_path: str, return auth_service -def create_app_router_for_sqlite(db_path: str, - jwt_secret: str, - email_service: Optional[EmailService] = None): +def create_auth_app_for_sqlite(db_path: str, + jwt_secret: str, + email_service: Optional[EmailService] = None): """ Creates an application router designed to use with an SQLite database backend. 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. """ auth_service = create_sqlite_auth_service(db_path, jwt_secret, email_service) - from .api.routes import create_auth_router - return create_auth_router(auth_service) + from .api.routes import create_auth_app + 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.") diff --git a/tests/api/test_api_routes.py b/tests/api/test_api_routes.py index 009af3a..af75640 100644 --- a/tests/api/test_api_routes.py +++ b/tests/api/test_api_routes.py @@ -12,7 +12,7 @@ import pytest from fastapi import FastAPI 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.exceptions import ( UserAlreadyExistsError, @@ -51,8 +51,8 @@ def test_app(mock_auth_service): FastAPI application configured for testing. """ app = FastAPI() - auth_router = create_auth_router(mock_auth_service) - app.include_router(auth_router) + auth_app = create_auth_app(mock_auth_service) + app.mount("/auth", auth_app) return app