import { useMutation, useQueryClient } from "@tanstack/react-query"; import type { AxiosError } from "axios"; import { AlertCircle, Check, ChevronLeft, Copy, Loader2, Save, ShieldCheck, } from "lucide-react"; import * as React from "react"; import { useForm } from "react-hook-form"; import { Link, useNavigate } from "react-router-dom"; import { Button } from "../../components/ui/button"; import { Card, CardContent, CardHeader, CardTitle, } from "../../components/ui/card"; import { Input } from "../../components/ui/input"; import { Label } from "../../components/ui/label"; import { type ApiKeyCreateRequest, type ApiKeyCreateResponse, createApiKey, } from "../../lib/adminApi"; import { t } from "../../lib/i18n"; import { cn } from "../../lib/utils"; const AVAILABLE_SCOPES = [ { id: "audit:read", labelKey: "ui.admin.api_keys.scopes.audit_read.title", labelFallback: "감사 로그 조회", descKey: "msg.admin.api_keys.scopes.audit_read.desc", descFallback: "시스템 내의 모든 이력을 조회할 수 있습니다.", }, { id: "audit:write", labelKey: "ui.admin.api_keys.scopes.audit_write.title", labelFallback: "감사 로그 생성", descKey: "msg.admin.api_keys.scopes.audit_write.desc", descFallback: "외부 앱의 로그를 Baron SSO로 전송합니다.", }, { id: "user:read", labelKey: "ui.admin.api_keys.scopes.user_read.title", labelFallback: "사용자 조회", descKey: "msg.admin.api_keys.scopes.user_read.desc", descFallback: "사용자 목록 및 프로필을 읽을 수 있습니다.", }, { id: "user:write", labelKey: "ui.admin.api_keys.scopes.user_write.title", labelFallback: "사용자 관리", descKey: "msg.admin.api_keys.scopes.user_write.desc", descFallback: "사용자 생성, 수정, 삭제 작업을 수행합니다.", }, { id: "tenant:read", labelKey: "ui.admin.api_keys.scopes.tenant_read.title", labelFallback: "테넌트 조회", descKey: "msg.admin.api_keys.scopes.tenant_read.desc", descFallback: "등록된 모든 조직 정보를 조회합니다.", }, { id: "tenant:write", labelKey: "ui.admin.api_keys.scopes.tenant_write.title", labelFallback: "테넌트 관리", descKey: "msg.admin.api_keys.scopes.tenant_write.desc", descFallback: "테넌트 정보를 직접 제어합니다.", }, ]; function ApiKeyCreatePage() { const navigate = useNavigate(); const queryClient = useQueryClient(); const [error, setError] = React.useState(null); const [createdResult, setCreatedResult] = React.useState(null); const [selectedScopes, setSelectedScopes] = React.useState([ "audit:read", "user:read", ]); const { register, handleSubmit, formState: { errors }, } = useForm<{ name: string }>({ defaultValues: { name: "" }, }); const mutation = useMutation({ mutationFn: (payload: ApiKeyCreateRequest) => createApiKey(payload), onSuccess: (data) => { queryClient.invalidateQueries({ queryKey: ["api-keys"] }); setCreatedResult(data); }, onError: (err: AxiosError<{ error?: string }>) => { setError( err.response?.data?.error || t("msg.admin.api_keys.create.error", "API 키 생성에 실패했습니다."), ); }, }); const toggleScope = (scopeId: string) => { setSelectedScopes((prev) => prev.includes(scopeId) ? prev.filter((s) => s !== scopeId) : [...prev, scopeId], ); }; const onSubmit = (data: { name: string }) => { if (selectedScopes.length === 0) { setError( t( "msg.admin.api_keys.create.scope_required", "최소 하나 이상의 권한을 선택해야 합니다.", ), ); return; } setError(null); mutation.mutate({ name: data.name, scopes: selectedScopes }); }; const handleCopy = (text: string) => { navigator.clipboard.writeText(text); }; if (createdResult) { return (

{t("ui.admin.api_keys.create.success.title", "API 키 생성 완료")}

{t( "msg.admin.api_keys.create.success.notice", "아래의 비밀번호(Secret)는 보안을 위해 ", )} {t( "msg.admin.api_keys.create.success.notice_emphasis", "지금 한 번만", )} {" "} {t( "msg.admin.api_keys.create.success.notice_suffix", "표시됩니다.", )}

{t( "ui.admin.api_keys.create.success.copy_secret", "보안 시크릿 복사", )}

{t( "msg.admin.api_keys.create.success.copy_hint", "복사 버튼을 눌러 안전한 곳(비밀번호 관리자 등)에 저장하세요.", )}

); } return (

{t("ui.admin.api_keys.create.title", "새 API 키 생성")}

{t( "msg.admin.api_keys.create.subtitle", "내부 시스템 연동을 위한 보안 인증 키를 구성합니다.", )}

{/* 섹션 1: 이름 설정 */}
1

{t("ui.admin.api_keys.create.section_name", "키 이름 지정")}

{errors.name && (

{errors.name.message}

)}
{/* 섹션 2: 권한 선택 */}
2

{t( "ui.admin.api_keys.create.section_scopes", "권한 범위(Scopes) 선택", )}

{AVAILABLE_SCOPES.map((scope) => { const isSelected = selectedScopes.includes(scope.id); return ( ); })}
{/* 하단 실행 버튼 */}
{error && (

{error}

)}

{t( "msg.admin.api_keys.create.scopes_count", "총 {{count}}개의 권한이 할당됩니다.", { count: selectedScopes.length }, )}

{t( "msg.admin.api_keys.create.scopes_hint", "생성 즉시 활성화되어 사용 가능합니다.", )}

); } export default ApiKeyCreatePage;