import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import type { AxiosError } from "axios"; import { ArrowLeft, Save } from "lucide-react"; import { useState } from "react"; import { Link, useNavigate } from "react-router-dom"; import { Button } from "../../components/ui/button"; import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "../../components/ui/card"; import { Input } from "../../components/ui/input"; import { Label } from "../../components/ui/label"; import { createRelyingParty, fetchTenants, } from "../../lib/adminApi"; import type { HydraClientReq } from "../../lib/adminApi"; import { Badge } from "../../components/ui/badge"; function RelyingPartyCreatePage() { const navigate = useNavigate(); const queryClient = useQueryClient(); const [selectedTenantId, setSelectedTenantId] = useState(""); const [formData, setFormData] = useState({ client_name: "", redirect_uris: [], scope: "openid profile email", grant_types: ["authorization_code", "refresh_token"], response_types: ["code"], token_endpoint_auth_method: "client_secret_basic", }); const [redirectUriInput, setRedirectUriInput] = useState(""); // 테넌트 목록 조회 (선택용) const { data: tenantsData } = useQuery({ queryKey: ["tenants", { limit: 100 }], queryFn: () => fetchTenants(100, 0), }); const tenants = tenantsData?.items ?? []; const createMutation = useMutation({ mutationFn: (data: HydraClientReq) => createRelyingParty(selectedTenantId, data), onSuccess: () => { queryClient.invalidateQueries({ queryKey: ["relyingParties"] }); navigate("/relying-parties"); }, }); const errorMsg = (createMutation.error as AxiosError<{ error?: string }>) ?.response?.data?.error; const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (!selectedTenantId) { alert("소속될 테넌트를 선택해주세요."); return; } createMutation.mutate(formData); }; const addRedirectUri = () => { if (!redirectUriInput.trim()) return; setFormData((prev) => ({ ...prev, redirect_uris: [...prev.redirect_uris, redirectUriInput.trim()], })); setRedirectUriInput(""); }; const removeRedirectUri = (index: number) => { setFormData((prev) => ({ ...prev, redirect_uris: prev.redirect_uris.filter((_, i) => i !== index), })); }; return (
Applications / New App

새 애플리케이션 등록

전체 시스템 차원에서 새로운 Relying Party를 등록합니다.

App & Tenant Assignment 애플리케이션이 소속될 테넌트와 기본 정보를 설정합니다. {errorMsg && (
{errorMsg}
)} {/* 테넌트 선택 추가 */}

이 앱을 관리할 조직을 선택하세요.

setFormData({ ...formData, client_name: e.target.value }) } placeholder="My Awesome App" required />
setRedirectUriInput(e.target.value)} placeholder="https://myapp.com/callback" onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); addRedirectUri(); } }} />
{formData.redirect_uris.map((uri, idx) => ( {uri} ))}
setFormData({ ...formData, scope: e.target.value }) } placeholder="openid profile email" />
); } export default RelyingPartyCreatePage;