Compare commits
2 Commits
d813cf5f3f
...
d0049cf9a4
| Author | SHA1 | Date | |
|---|---|---|---|
| d0049cf9a4 | |||
| 8b8c7a423e |
@@ -257,12 +257,16 @@ async def login(body: LoginRequest, request: Request, db: AsyncSession = Depends
|
|||||||
@router.get("/me")
|
@router.get("/me")
|
||||||
async def me(credential: str = Depends(require_api_key), db: AsyncSession = Depends(get_db)):
|
async def me(credential: str = Depends(require_api_key), db: AsyncSession = Depends(get_db)):
|
||||||
"""현재 자격 증명 확인 — 세션 토큰이면 계정 정보, API 키면 'api-key'(관리자)."""
|
"""현재 자격 증명 확인 — 세션 토큰이면 계정 정보, API 키면 'api-key'(관리자)."""
|
||||||
|
# multi_tenant_enabled: 프론트가 v2(사용자 스코프) API를 쓸지 결정하는 근거.
|
||||||
|
# False면 세션 로그인이라도 v2 컨텍스트가 legacy로 떨어져 /portfolio/v2 는
|
||||||
|
# KIS 동기화 없는 DB 스냅숏만 반환하므로(화면 갱신 안 됨) v1을 써야 한다.
|
||||||
|
_mt = bool(settings.MULTI_TENANT_ENABLED)
|
||||||
if hmac.compare_digest(credential.encode(), _get_api_key().encode()):
|
if hmac.compare_digest(credential.encode(), _get_api_key().encode()):
|
||||||
return {"username": "api-key", "auth_type": "api_key", "is_admin": True}
|
return {"username": "api-key", "auth_type": "api_key", "is_admin": True, "multi_tenant_enabled": _mt}
|
||||||
user = await _resolve_user(credential, db)
|
user = await _resolve_user(credential, db)
|
||||||
if user is None or not user.is_active:
|
if user is None or not user.is_active:
|
||||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="세션이 유효하지 않습니다.")
|
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="세션이 유효하지 않습니다.")
|
||||||
return {"username": user.username, "auth_type": "session", "is_admin": user.is_admin}
|
return {"username": user.username, "auth_type": "session", "is_admin": user.is_admin, "multi_tenant_enabled": _mt}
|
||||||
|
|
||||||
|
|
||||||
@router.get("/users", response_model=list[UserOut], dependencies=[Depends(require_admin)])
|
@router.get("/users", response_model=list[UserOut], dependencies=[Depends(require_admin)])
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* - `GET /auth/me`로 호출 주체(auth_type)를 확인해 포트폴리오·거래이력·매수/매도가
|
* - `GET /auth/me`로 호출 주체(auth_type)를 확인해 포트폴리오·거래이력·매수/매도가
|
||||||
* 사용자 스코프 v2 API(`/portfolio/v2`, `/trades/v2`)를 쓸지, 기존 v1 API를
|
* 사용자 스코프 v2 API(`/portfolio/v2`, `/trades/v2`)를 쓸지, 기존 v1 API를
|
||||||
* 쓸지 결정한다.
|
* 쓸지 결정한다.
|
||||||
* - auth_type === 'session' (로그인 사용자) → v2
|
* - auth_type === 'session' (로그인 사용자) AND 백엔드 multi_tenant_enabled=true → v2
|
||||||
* - auth_type === 'api_key' (레거시 운영자 API 키, MULTI_TENANT_ENABLED=false 환경 포함)
|
* - auth_type === 'api_key' (레거시 운영자 API 키, MULTI_TENANT_ENABLED=false 환경 포함)
|
||||||
* → legacy(v1). 백엔드도 이 경우 `/portfolio/v2/sync`를 스킵 응답하므로 v1 그대로 사용해야 한다.
|
* → legacy(v1). 백엔드도 이 경우 `/portfolio/v2/sync`를 스킵 응답하므로 v1 그대로 사용해야 한다.
|
||||||
*
|
*
|
||||||
@@ -24,6 +24,8 @@ export interface AuthMe {
|
|||||||
username: string
|
username: string
|
||||||
auth_type: 'session' | 'api_key'
|
auth_type: 'session' | 'api_key'
|
||||||
is_admin: boolean
|
is_admin: boolean
|
||||||
|
/** 백엔드 MULTI_TENANT_ENABLED. 구버전 백엔드는 필드가 없음(undefined) → legacy 취급 */
|
||||||
|
multi_tenant_enabled?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 'v2' | 'legacy' 확정 전(로딩 중·조회 실패)에는 undefined */
|
/** 'v2' | 'legacy' 확정 전(로딩 중·조회 실패)에는 undefined */
|
||||||
@@ -46,7 +48,10 @@ export const useTenantMode = () => {
|
|||||||
|
|
||||||
const mode: TenantMode = isLoading || error || !me
|
const mode: TenantMode = isLoading || error || !me
|
||||||
? undefined
|
? undefined
|
||||||
: me.auth_type === 'session' ? 'v2' : 'legacy'
|
// 세션 로그인이어도 백엔드 멀티테넌트가 꺼져 있으면 v2 컨텍스트는 legacy로
|
||||||
|
// 떨어져 /portfolio/v2 가 KIS 동기화 없는 DB 스냅숏만 돌려준다(화면 갱신 안 됨).
|
||||||
|
// → MULTI_TENANT_ENABLED=true 인 경우에만 v2 사용.
|
||||||
|
: me.auth_type === 'session' && me.multi_tenant_enabled === true ? 'v2' : 'legacy'
|
||||||
|
|
||||||
return { mode, me, isLoading, error }
|
return { mode, me, isLoading, error }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user