auth.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. """
  2. Authentication endpoints: register, login, refresh, logout.
  3. """
  4. from typing import Annotated
  5. from fastapi import APIRouter, Depends
  6. from fastapi.security import OAuth2PasswordRequestForm
  7. from sqlalchemy.ext.asyncio import AsyncSession
  8. from app.api.deps import get_current_user
  9. from app.core.database import get_db
  10. from app.models.user import User
  11. from app.schemas.auth import (
  12. AuthResponse,
  13. LogoutRequest,
  14. RefreshRequest,
  15. RegisterRequest,
  16. UserInfo,
  17. )
  18. from app.services import auth_service
  19. router = APIRouter(prefix="/auth", tags=["Authentication"])
  20. @router.post("/register", status_code=201)
  21. async def register(
  22. data: RegisterRequest,
  23. db: Annotated[AsyncSession, Depends(get_db)],
  24. ):
  25. """
  26. Register new user with organization.
  27. Creates organization (status=pending) and user (role=owner).
  28. Admin must activate the organization before user can access products.
  29. """
  30. return await auth_service.register_user(
  31. db=db,
  32. email=data.email,
  33. password=data.password,
  34. full_name=data.full_name,
  35. phone=data.phone,
  36. organization_name=data.organization_name,
  37. )
  38. @router.post("/login", response_model=AuthResponse)
  39. async def login(
  40. form_data: Annotated[OAuth2PasswordRequestForm, Depends()],
  41. db: Annotated[AsyncSession, Depends(get_db)],
  42. ):
  43. """
  44. Authenticate user and return JWT tokens.
  45. Returns:
  46. - access_token: Short-lived token for API access (15 min)
  47. - refresh_token: Long-lived token for refreshing access token (30 days)
  48. - user: User information
  49. - organization: Organization information (if applicable)
  50. """
  51. return await auth_service.login_user(
  52. db=db,
  53. email=form_data.username,
  54. password=form_data.password,
  55. )
  56. @router.post("/refresh", response_model=AuthResponse)
  57. async def refresh(
  58. data: RefreshRequest,
  59. db: Annotated[AsyncSession, Depends(get_db)],
  60. ):
  61. """
  62. Refresh access token using refresh token.
  63. Returns new access_token and refresh_token.
  64. Old refresh_token is revoked.
  65. """
  66. return await auth_service.refresh_access_token(
  67. db=db,
  68. refresh_token_str=data.refresh_token,
  69. )
  70. @router.post("/logout")
  71. async def logout(
  72. data: LogoutRequest,
  73. db: Annotated[AsyncSession, Depends(get_db)],
  74. ):
  75. """
  76. Logout user by revoking refresh token.
  77. """
  78. return await auth_service.logout_user(
  79. db=db,
  80. refresh_token_str=data.refresh_token,
  81. )
  82. @router.get("/me", response_model=UserInfo)
  83. async def get_me(
  84. current_user: Annotated[User, Depends(get_current_user)],
  85. ):
  86. """
  87. Get current user information.
  88. Requires: Valid access token in Authorization header.
  89. """
  90. return UserInfo.model_validate(current_user)