mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-16 08:25:18 +02:00
feat: add authentication for OSS (#167)
* feat: add authentication for OSS Fixes #157 and #156 * fix: fix token generation * fix: limit fastapi workers to 1
This commit is contained in:
parent
0791975864
commit
642cc34e8c
48 changed files with 994 additions and 303 deletions
97
api/routes/auth.py
Normal file
97
api/routes/auth.py
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from loguru import logger
|
||||
|
||||
from api.db import db_client
|
||||
from api.db.models import UserModel
|
||||
from api.schemas.auth import AuthResponse, LoginRequest, SignupRequest, UserResponse
|
||||
from api.services.auth.depends import create_user_configuration_with_mps_key, get_user
|
||||
from api.utils.auth import create_jwt_token, hash_password, verify_password
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/auth",
|
||||
tags=["auth"],
|
||||
)
|
||||
|
||||
|
||||
@router.post("/signup", response_model=AuthResponse)
|
||||
async def signup(request: SignupRequest):
|
||||
# Check if email is already taken
|
||||
existing_user = await db_client.get_user_by_email(request.email)
|
||||
if existing_user:
|
||||
raise HTTPException(status_code=409, detail="Email already registered")
|
||||
|
||||
# Hash password and create user
|
||||
hashed = hash_password(request.password)
|
||||
user = await db_client.create_user_with_email(
|
||||
email=request.email,
|
||||
password_hash=hashed,
|
||||
name=request.name,
|
||||
)
|
||||
|
||||
# Create organization for the user
|
||||
org_provider_id = f"org_{user.provider_id}"
|
||||
organization, _ = await db_client.get_or_create_organization_by_provider_id(
|
||||
org_provider_id=org_provider_id, user_id=user.id
|
||||
)
|
||||
|
||||
# Link user to organization
|
||||
await db_client.add_user_to_organization(user.id, organization.id)
|
||||
await db_client.update_user_selected_organization(user.id, organization.id)
|
||||
|
||||
# Create default service configuration
|
||||
try:
|
||||
mps_config = await create_user_configuration_with_mps_key(
|
||||
user.id, organization.id, user.provider_id
|
||||
)
|
||||
if mps_config:
|
||||
await db_client.update_user_configuration(user.id, mps_config)
|
||||
except Exception:
|
||||
logger.warning(
|
||||
"Failed to create default configuration for OSS user", exc_info=True
|
||||
)
|
||||
|
||||
# Create JWT token
|
||||
token = create_jwt_token(user.id, request.email)
|
||||
|
||||
return AuthResponse(
|
||||
token=token,
|
||||
user=UserResponse(
|
||||
id=user.id,
|
||||
email=user.email,
|
||||
name=request.name,
|
||||
organization_id=organization.id,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@router.post("/login", response_model=AuthResponse)
|
||||
async def login(request: LoginRequest):
|
||||
# Look up user by email
|
||||
user = await db_client.get_user_by_email(request.email)
|
||||
if not user or not user.password_hash:
|
||||
raise HTTPException(status_code=401, detail="Invalid email or password")
|
||||
|
||||
# Verify password
|
||||
if not verify_password(request.password, user.password_hash):
|
||||
raise HTTPException(status_code=401, detail="Invalid email or password")
|
||||
|
||||
# Create JWT token
|
||||
token = create_jwt_token(user.id, user.email)
|
||||
|
||||
return AuthResponse(
|
||||
token=token,
|
||||
user=UserResponse(
|
||||
id=user.id,
|
||||
email=user.email,
|
||||
organization_id=user.selected_organization_id,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@router.get("/me", response_model=UserResponse)
|
||||
async def get_current_user(user: UserModel = Depends(get_user)):
|
||||
return UserResponse(
|
||||
id=user.id,
|
||||
email=user.email,
|
||||
organization_id=user.selected_organization_id,
|
||||
)
|
||||
|
|
@ -2,6 +2,7 @@ from fastapi import APIRouter
|
|||
from loguru import logger
|
||||
from pydantic import BaseModel
|
||||
|
||||
from api.routes.auth import router as auth_router
|
||||
from api.routes.campaign import router as campaign_router
|
||||
from api.routes.credentials import router as credentials_router
|
||||
from api.routes.integration import router as integration_router
|
||||
|
|
@ -50,17 +51,20 @@ router.include_router(public_agent_router)
|
|||
router.include_router(public_download_router)
|
||||
router.include_router(workflow_embed_router)
|
||||
router.include_router(knowledge_base_router)
|
||||
router.include_router(auth_router)
|
||||
|
||||
|
||||
class HealthResponse(BaseModel):
|
||||
status: str
|
||||
version: str
|
||||
backend_api_endpoint: str
|
||||
deployment_mode: str
|
||||
auth_provider: str
|
||||
|
||||
|
||||
@router.get("/health", response_model=HealthResponse)
|
||||
async def health() -> HealthResponse:
|
||||
from api.constants import APP_VERSION
|
||||
from api.constants import APP_VERSION, AUTH_PROVIDER, DEPLOYMENT_MODE
|
||||
from api.utils.common import get_backend_endpoints
|
||||
|
||||
logger.debug("Health endpoint called")
|
||||
|
|
@ -69,4 +73,6 @@ async def health() -> HealthResponse:
|
|||
status="ok",
|
||||
version=APP_VERSION,
|
||||
backend_api_endpoint=backend_endpoint,
|
||||
deployment_mode=DEPLOYMENT_MODE,
|
||||
auth_provider=AUTH_PROVIDER,
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue