first commit
This commit is contained in:
0
app/api/v1/__init__.py
Normal file
0
app/api/v1/__init__.py
Normal file
54
app/api/v1/auth.py
Normal file
54
app/api/v1/auth.py
Normal file
@@ -0,0 +1,54 @@
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.database import get_db
|
||||
from app.core.dependencies import get_current_user
|
||||
from app.models import User
|
||||
from app.services.auth_service import AuthService
|
||||
from app.datamodels.schemas import (
|
||||
RegisterRequest, LoginRequest, TokenResponse, RefreshRequest,
|
||||
ForgotPasswordRequest, ResetPasswordRequest, UserResponse, MessageResponse,
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/auth", tags=["auth"])
|
||||
|
||||
|
||||
@router.post("/register", response_model=UserResponse)
|
||||
async def register(body: RegisterRequest, db: AsyncSession = Depends(get_db)):
|
||||
user = await AuthService.register(db, body.email, body.password)
|
||||
return user
|
||||
|
||||
|
||||
@router.post("/login", response_model=TokenResponse)
|
||||
async def login(body: LoginRequest, db: AsyncSession = Depends(get_db)):
|
||||
return await AuthService.login(db, body.email, body.password)
|
||||
|
||||
|
||||
@router.post("/refresh", response_model=TokenResponse)
|
||||
async def refresh(body: RefreshRequest, db: AsyncSession = Depends(get_db)):
|
||||
return await AuthService.refresh(db, body.refresh_token)
|
||||
|
||||
|
||||
@router.post("/logout", response_model=MessageResponse)
|
||||
async def logout():
|
||||
return {"message": "Logged out successfully"}
|
||||
|
||||
|
||||
@router.post("/forgot-password", response_model=MessageResponse)
|
||||
async def forgot_password(body: ForgotPasswordRequest, db: AsyncSession = Depends(get_db)):
|
||||
token = await AuthService.forgot_password(db, body.email)
|
||||
if token:
|
||||
# MVP: print token to console; production: send email
|
||||
print(f"[Password Reset] email={body.email} token={token}")
|
||||
return {"message": "If the email exists, a reset link has been sent"}
|
||||
|
||||
|
||||
@router.post("/reset-password", response_model=MessageResponse)
|
||||
async def reset_password(body: ResetPasswordRequest, db: AsyncSession = Depends(get_db)):
|
||||
await AuthService.reset_password(db, body.token, body.new_password)
|
||||
return {"message": "Password reset successfully"}
|
||||
|
||||
|
||||
@router.get("/me", response_model=UserResponse)
|
||||
async def me(user: User = Depends(get_current_user)):
|
||||
return user
|
||||
20
app/api/v1/example.py
Normal file
20
app/api/v1/example.py
Normal file
@@ -0,0 +1,20 @@
|
||||
from fastapi import APIRouter
|
||||
from app.services.example_service import ExampleService
|
||||
|
||||
router = APIRouter()
|
||||
service = ExampleService()
|
||||
|
||||
|
||||
@router.get("/examples")
|
||||
async def list_examples():
|
||||
return await service.list_all()
|
||||
|
||||
|
||||
@router.get("/examples/{example_id}")
|
||||
async def get_example(example_id: str):
|
||||
return await service.get_by_id(example_id)
|
||||
|
||||
|
||||
@router.post("/examples")
|
||||
async def create_example(data: dict):
|
||||
return await service.create(data)
|
||||
8
app/api/v1/health.py
Normal file
8
app/api/v1/health.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from fastapi import APIRouter
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
@router.get("/health")
|
||||
async def health_check():
|
||||
return {"status": "ok", "service": "SuperDream"}
|
||||
39
app/api/v1/keys.py
Normal file
39
app/api/v1/keys.py
Normal file
@@ -0,0 +1,39 @@
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.database import get_db
|
||||
from app.core.dependencies import get_current_user
|
||||
from app.models import User
|
||||
from app.services.key_service import KeyService
|
||||
from app.datamodels.schemas import CreateKeyRequest, ApiKeyResponse, ApiKeyCreatedResponse, MessageResponse
|
||||
|
||||
router = APIRouter(prefix="/keys", tags=["keys"])
|
||||
|
||||
|
||||
@router.get("", response_model=List[ApiKeyResponse])
|
||||
async def list_keys(
|
||||
user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
return await KeyService.list_keys(db, user.id)
|
||||
|
||||
|
||||
@router.post("", response_model=ApiKeyCreatedResponse)
|
||||
async def create_key(
|
||||
body: CreateKeyRequest,
|
||||
user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
return await KeyService.create_key(db, user.id, body.name)
|
||||
|
||||
|
||||
@router.delete("/{key_id}", response_model=MessageResponse)
|
||||
async def delete_key(
|
||||
key_id: str,
|
||||
user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
await KeyService.delete_key(db, user.id, key_id)
|
||||
return {"message": "Key deleted"}
|
||||
16
app/api/v1/models.py
Normal file
16
app/api/v1/models.py
Normal file
@@ -0,0 +1,16 @@
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter, Depends
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.database import get_db
|
||||
from app.services.model_service import ModelService
|
||||
from app.datamodels.schemas import ModelPricingResponse
|
||||
|
||||
router = APIRouter(prefix="/models", tags=["models"])
|
||||
|
||||
|
||||
@router.get("", response_model=List[ModelPricingResponse])
|
||||
async def list_models(db: AsyncSession = Depends(get_db)):
|
||||
"""Public endpoint: list available models and pricing."""
|
||||
return await ModelService.list_models(db)
|
||||
64
app/api/v1/usage.py
Normal file
64
app/api/v1/usage.py
Normal file
@@ -0,0 +1,64 @@
|
||||
from datetime import date
|
||||
from typing import List, Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.database import get_db
|
||||
from app.core.dependencies import get_current_user
|
||||
from app.models import User
|
||||
from app.services.usage_service import UsageService
|
||||
from app.datamodels.schemas import (
|
||||
UsageSummaryResponse, DailyUsageResponse,
|
||||
ModelUsageResponse, KeyUsageResponse, UsageLogResponse,
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/usage", tags=["usage"])
|
||||
|
||||
|
||||
@router.get("/summary", response_model=UsageSummaryResponse)
|
||||
async def usage_summary(
|
||||
user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
return await UsageService.summary(db, user.id)
|
||||
|
||||
|
||||
@router.get("/daily", response_model=List[DailyUsageResponse])
|
||||
async def usage_daily(
|
||||
start: Optional[date] = Query(None),
|
||||
end: Optional[date] = Query(None),
|
||||
user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
return await UsageService.daily(db, user.id, start, end)
|
||||
|
||||
|
||||
@router.get("/by-model", response_model=List[ModelUsageResponse])
|
||||
async def usage_by_model(
|
||||
user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
return await UsageService.by_model(db, user.id)
|
||||
|
||||
|
||||
@router.get("/by-key", response_model=List[KeyUsageResponse])
|
||||
async def usage_by_key(
|
||||
user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
return await UsageService.by_key(db, user.id)
|
||||
|
||||
|
||||
@router.get("/logs", response_model=List[UsageLogResponse])
|
||||
async def usage_logs(
|
||||
page: int = Query(1, ge=1),
|
||||
size: int = Query(20, ge=1, le=100),
|
||||
model: Optional[str] = Query(None),
|
||||
key_id: Optional[str] = Query(None),
|
||||
start: Optional[date] = Query(None),
|
||||
end: Optional[date] = Query(None),
|
||||
user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
return await UsageService.logs(db, user.id, page, size, model, key_id, start, end)
|
||||
42
app/api/v1/wallet.py
Normal file
42
app/api/v1/wallet.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from typing import List
|
||||
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
from app.core.database import get_db
|
||||
from app.core.dependencies import get_current_user
|
||||
from app.models import User
|
||||
from app.services.wallet_service import WalletService
|
||||
from app.datamodels.schemas import (
|
||||
BalanceResponse, RedeemCodeRequest, TransactionResponse,
|
||||
)
|
||||
|
||||
router = APIRouter(prefix="/wallet", tags=["wallet"])
|
||||
|
||||
|
||||
@router.get("/balance", response_model=BalanceResponse)
|
||||
async def get_balance(
|
||||
user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
balance = await WalletService.get_balance(db, user.id)
|
||||
return {"balance": balance}
|
||||
|
||||
|
||||
@router.post("/redeem", response_model=TransactionResponse)
|
||||
async def redeem_code(
|
||||
body: RedeemCodeRequest,
|
||||
user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
return await WalletService.redeem_code(db, user.id, body.code)
|
||||
|
||||
|
||||
@router.get("/transactions", response_model=List[TransactionResponse])
|
||||
async def list_transactions(
|
||||
page: int = Query(1, ge=1),
|
||||
size: int = Query(20, ge=1, le=100),
|
||||
user: User = Depends(get_current_user),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
):
|
||||
return await WalletService.list_transactions(db, user.id, page, size)
|
||||
Reference in New Issue
Block a user