189 lines
6.0 KiB
Python
189 lines
6.0 KiB
Python
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
from fastapi.openapi.utils import get_openapi
|
|
from fastapi.staticfiles import StaticFiles
|
|
from scalar_fastapi import get_scalar_api_reference
|
|
|
|
from app.admin_manager import init_admin
|
|
from app.core.common import lifespan
|
|
from app.database.session import engine
|
|
|
|
# User 모델 import (테이블 메타데이터 등록용)
|
|
from app.user.models import User, RefreshToken # noqa: F401
|
|
|
|
from app.home.api.routers.v1.home import router as home_router
|
|
from app.user.api.routers.v1.auth import router as auth_router, test_router as auth_test_router
|
|
from app.lyric.api.routers.v1.lyric import router as lyric_router
|
|
from app.song.api.routers.v1.song import router as song_router
|
|
from app.video.api.routers.v1.video import router as video_router
|
|
from app.utils.cors import CustomCORSMiddleware
|
|
from config import prj_settings
|
|
|
|
tags_metadata = [
|
|
{
|
|
"name": "Auth",
|
|
"description": """카카오 소셜 로그인 및 JWT 토큰 관리 API
|
|
|
|
## 인증 흐름
|
|
|
|
1. `GET /api/v1/user/auth/kakao/login` - 카카오 로그인 URL 획득
|
|
2. 사용자를 auth_url로 리다이렉트 → 카카오 로그인
|
|
3. 카카오에서 인가 코드(code) 발급
|
|
4. `POST /api/v1/user/auth/kakao/callback` - 인가 코드로 JWT 토큰 발급
|
|
5. 이후 API 호출 시 `Authorization: Bearer {access_token}` 헤더 사용
|
|
|
|
## 토큰 관리
|
|
|
|
- **Access Token**: 1시간 유효, API 호출 시 사용
|
|
- **Refresh Token**: 7일 유효, Access Token 갱신 시 사용
|
|
""",
|
|
},
|
|
# {
|
|
# "name": "Home",
|
|
# "description": "홈 화면 및 프로젝트 관리 API",
|
|
# },
|
|
{
|
|
"name": "Crawling",
|
|
"description": "네이버 지도 크롤링 API - 장소 정보 및 이미지 수집",
|
|
},
|
|
{
|
|
"name": "Image-Blob",
|
|
"description": "이미지 업로드 API - Azure Blob Storage",
|
|
},
|
|
{
|
|
"name": "Lyric",
|
|
"description": """가사 생성 및 관리 API
|
|
|
|
## 가사 생성 흐름
|
|
|
|
1. `POST /api/v1/lyric/generate` - 가사 생성 요청 (백그라운드 처리)
|
|
2. `GET /api/v1/lyric/status/{task_id}` - 생성 상태 확인
|
|
3. `GET /api/v1/lyric/{task_id}` - 생성된 가사 조회
|
|
""",
|
|
},
|
|
{
|
|
"name": "Song",
|
|
"description": """노래 생성 및 관리 API (Suno AI)
|
|
|
|
## 노래 생성 흐름
|
|
|
|
1. `POST /api/v1/song/generate/{task_id}` - 노래 생성 요청
|
|
2. `GET /api/v1/song/status/{song_id}` - Suno API 상태 확인
|
|
""",
|
|
},
|
|
{
|
|
"name": "Video",
|
|
"description": """영상 생성 및 관리 API (Creatomate)
|
|
|
|
## 영상 생성 흐름
|
|
|
|
1. `GET /api/v1/video/generate/{task_id}` - 영상 생성 요청
|
|
2. `GET /api/v1/video/status/{creatomate_render_id}` - Creatomate 상태 확인
|
|
3. `GET /api/v1/video/download/{task_id}` - 영상 다운로드 URL 조회
|
|
""",
|
|
},
|
|
]
|
|
|
|
# DEBUG 모드에서만 Test Auth 태그 추가
|
|
if prj_settings.DEBUG:
|
|
tags_metadata.append(
|
|
{
|
|
"name": "Test Auth",
|
|
"description": """테스트용 인증 API (DEBUG 모드 전용)
|
|
|
|
**주의: 이 API는 DEBUG 모드에서만 사용 가능합니다.**
|
|
|
|
카카오 로그인 없이 테스트용 사용자 생성 및 토큰 발급이 가능합니다.
|
|
|
|
## 테스트 흐름
|
|
|
|
1. `POST /api/v1/user/auth/test/create-user` - 테스트 사용자 생성
|
|
2. `POST /api/v1/user/auth/test/generate-token` - JWT 토큰 발급
|
|
""",
|
|
}
|
|
)
|
|
|
|
app = FastAPI(
|
|
title=prj_settings.PROJECT_NAME,
|
|
version=prj_settings.VERSION,
|
|
description=prj_settings.DESCRIPTION,
|
|
lifespan=lifespan,
|
|
docs_url=None, # 기본 Swagger UI 비활성화
|
|
redoc_url=None, # 기본 ReDoc 비활성화
|
|
openapi_tags=tags_metadata,
|
|
)
|
|
|
|
|
|
def custom_openapi():
|
|
"""커스텀 OpenAPI 스키마 생성 (Bearer 인증 추가)"""
|
|
if app.openapi_schema:
|
|
return app.openapi_schema
|
|
|
|
openapi_schema = get_openapi(
|
|
title=app.title,
|
|
version=app.version,
|
|
description=app.description,
|
|
routes=app.routes,
|
|
tags=tags_metadata,
|
|
)
|
|
|
|
# Bearer 토큰 인증 스키마 추가
|
|
openapi_schema["components"]["securitySchemes"] = {
|
|
"BearerAuth": {
|
|
"type": "http",
|
|
"scheme": "bearer",
|
|
"bearerFormat": "JWT",
|
|
"description": "JWT 액세스 토큰을 입력하세요. 카카오 로그인 후 발급받은 access_token을 사용합니다.",
|
|
}
|
|
}
|
|
|
|
# 보안이 필요한 엔드포인트에 security 적용
|
|
for path, path_item in openapi_schema["paths"].items():
|
|
for method, operation in path_item.items():
|
|
if method in ["get", "post", "put", "patch", "delete"]:
|
|
# /auth/me, /auth/logout 등 인증이 필요한 엔드포인트
|
|
if any(auth_path in path for auth_path in ["/auth/me", "/auth/logout"]):
|
|
operation["security"] = [{"BearerAuth": []}]
|
|
|
|
app.openapi_schema = openapi_schema
|
|
return app.openapi_schema
|
|
|
|
|
|
app.openapi = custom_openapi
|
|
|
|
init_admin(app, engine)
|
|
|
|
custom_cors_middleware = CustomCORSMiddleware(app)
|
|
custom_cors_middleware.configure_cors()
|
|
|
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
|
app.mount("/media", StaticFiles(directory="media"), name="media")
|
|
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
allow_credentials=True,
|
|
max_age=-1,
|
|
)
|
|
|
|
|
|
@app.get("/docs", include_in_schema=False)
|
|
def get_scalar_docs():
|
|
return get_scalar_api_reference(
|
|
openapi_url=app.openapi_url,
|
|
title="Scalar API",
|
|
)
|
|
|
|
|
|
app.include_router(home_router)
|
|
app.include_router(auth_router, prefix="/user") # Auth API 라우터 추가
|
|
app.include_router(lyric_router)
|
|
app.include_router(song_router)
|
|
app.include_router(video_router)
|
|
|
|
# DEBUG 모드에서만 테스트 라우터 등록
|
|
if prj_settings.DEBUG:
|
|
app.include_router(auth_test_router, prefix="/user") # Test Auth API 라우터
|