세션 로그인 사용자는 프론트가 v2(/portfolio/v2)를 쓰는데, 멀티테넌트가 꺼져 있으면 v2 컨텍스트가 legacy로 떨어져 KIS 동기화 없이 DB 스냅숏만 반환 → 현재가·손익이 갱신되지 않음. /auth/me 에 multi_tenant_enabled 를 추가하고, 프론트는 세션 로그인 AND 플래그 true 일 때만 v2 사용. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
58 lines
2.9 KiB
TypeScript
58 lines
2.9 KiB
TypeScript
/**
|
|
* tenant.ts — 멀티테넌트 v2/legacy 전환 스위치
|
|
*
|
|
* 역할:
|
|
* - `GET /auth/me`로 호출 주체(auth_type)를 확인해 포트폴리오·거래이력·매수/매도가
|
|
* 사용자 스코프 v2 API(`/portfolio/v2`, `/trades/v2`)를 쓸지, 기존 v1 API를
|
|
* 쓸지 결정한다.
|
|
* - auth_type === 'session' (로그인 사용자) AND 백엔드 multi_tenant_enabled=true → v2
|
|
* - auth_type === 'api_key' (레거시 운영자 API 키, MULTI_TENANT_ENABLED=false 환경 포함)
|
|
* → legacy(v1). 백엔드도 이 경우 `/portfolio/v2/sync`를 스킵 응답하므로 v1 그대로 사용해야 한다.
|
|
*
|
|
* 캐시: staleTime 5분 — 세션 타입은 로그인 상태에서 바뀌지 않으므로 자주 재조회할 필요 없음.
|
|
*
|
|
* 리뷰 M5 대응: `/auth/me` 응답이 오기 전에 'legacy'를 반환하면 세션(로그인) 사용자에게
|
|
* 잠깐 owner(legacy) 데이터가 노출되고 그 사이 매수/매도가 legacy 계좌로 나갈 수 있다.
|
|
* 따라서 결정 전(isLoading) 및 조회 실패(401 등) 시에는 `undefined`를 반환해 호출부가
|
|
* 데이터 조회·매매 액션을 모두 보류하도록 한다. 401은 기존 axios 응답 인터셉터가
|
|
* `api_key`를 지우고 새로고침(→ 로그인 화면)하므로 별도 처리가 필요 없다.
|
|
*/
|
|
import { useQuery } from '@tanstack/react-query'
|
|
import api from './api'
|
|
|
|
export interface AuthMe {
|
|
username: string
|
|
auth_type: 'session' | 'api_key'
|
|
is_admin: boolean
|
|
/** 백엔드 MULTI_TENANT_ENABLED. 구버전 백엔드는 필드가 없음(undefined) → legacy 취급 */
|
|
multi_tenant_enabled?: boolean
|
|
}
|
|
|
|
/** 'v2' | 'legacy' 확정 전(로딩 중·조회 실패)에는 undefined */
|
|
export type TenantMode = 'v2' | 'legacy' | undefined
|
|
|
|
/**
|
|
* useTenantMode — 현재 호출 주체의 v2/legacy 모드를 반환
|
|
*
|
|
* `/auth/me` 조회가 끝나기 전(isLoading)이거나 실패(error)한 동안에는 모드를
|
|
* 확정할 수 없으므로 `undefined`를 반환한다. 호출부는 `mode !== undefined`를
|
|
* react-query `enabled` 조건과 매수/매도 버튼 disabled 조건으로 사용해야 한다.
|
|
*/
|
|
export const useTenantMode = () => {
|
|
const { data: me, isLoading, error } = useQuery<AuthMe>({
|
|
queryKey: ['auth-me'],
|
|
queryFn: async () => (await api.get('/auth/me')).data,
|
|
staleTime: 5 * 60 * 1000,
|
|
refetchOnWindowFocus: false,
|
|
})
|
|
|
|
const mode: TenantMode = isLoading || error || !me
|
|
? undefined
|
|
// 세션 로그인이어도 백엔드 멀티테넌트가 꺼져 있으면 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 }
|
|
}
|