diff --git a/adminfront/src/app/routes.tsx b/adminfront/src/app/routes.tsx index ac0af8fe..44a2c5b0 100644 --- a/adminfront/src/app/routes.tsx +++ b/adminfront/src/app/routes.tsx @@ -7,10 +7,6 @@ import AuthPage from "../features/auth/AuthPage"; import DashboardPage from "../features/dashboard/DashboardPage"; import GlobalOverviewPage from "../features/overview/GlobalOverviewPage"; import LoginPage from "../features/auth/LoginPage"; -import RPDetailPage from "../features/relying-parties/routes/RPDetailPage"; -import RPListPage from "../features/relying-parties/routes/RPListPage"; -import RPOwnersTab from "../features/relying-parties/routes/RPOwnersTab"; -import RPProfileTab from "../features/relying-parties/routes/RPProfileTab"; import TenantGroupCreatePage from "../features/tenant-groups/routes/TenantGroupCreatePage"; import TenantGroupDetailPage from "../features/tenant-groups/routes/TenantGroupDetailPage"; import TenantGroupListPage from "../features/tenant-groups/routes/TenantGroupListPage"; @@ -68,15 +64,6 @@ export const router = createBrowserRouter( }, { path: "api-keys", element: }, { path: "api-keys/new", element: }, - { path: "relying-parties", element: }, - { - path: "relying-parties/:id", - element: , - children: [ - { index: true, element: }, - { path: "owners", element: }, - ], - }, ], }, ], diff --git a/adminfront/src/components/layout/AppLayout.tsx b/adminfront/src/components/layout/AppLayout.tsx index aedfb714..f0488612 100644 --- a/adminfront/src/components/layout/AppLayout.tsx +++ b/adminfront/src/components/layout/AppLayout.tsx @@ -25,11 +25,9 @@ import { to: "/dashboard", icon: ShieldHalf, }, - { label: "ui.admin.nav.tenant_groups", to: "/tenant-groups", icon: LayoutGrid }, - { label: "ui.admin.nav.tenants", to: "/tenants", icon: Building2 }, - { label: "ui.admin.nav.relying_parties", to: "/relying-parties", icon: Rocket }, - { label: "ui.admin.nav.users", to: "/users", icon: Users }, - { label: "ui.admin.nav.api_keys", to: "/api-keys", icon: Key }, + { label: "ui.admin.nav.tenant_groups", to: "/tenant-groups", icon: LayoutGrid }, + { label: "ui.admin.nav.tenants", to: "/tenants", icon: Building2 }, + { label: "ui.admin.nav.users", to: "/users", icon: Users }, { label: "ui.admin.nav.api_keys", to: "/api-keys", icon: Key }, { label: "ui.admin.nav.audit_logs", to: "/audit-logs", icon: NotebookTabs }, { label: "ui.admin.nav.auth_guard", to: "/auth", icon: KeyRound }, ]; diff --git a/adminfront/src/features/relying-parties/routes/RPDetailPage.tsx b/adminfront/src/features/relying-parties/routes/RPDetailPage.tsx deleted file mode 100644 index cc5f779f..00000000 --- a/adminfront/src/features/relying-parties/routes/RPDetailPage.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { useQuery } from "@tanstack/react-query"; -import { ArrowLeft, Rocket } from "lucide-react"; -import { Link, Outlet, useLocation, useParams } from "react-router-dom"; -import { Badge } from "../../../components/ui/badge"; -import { fetchRelyingParty } from "../../../lib/adminApi"; - -function RPDetailPage() { - const { id } = useParams<{ id: string }>(); - const location = useLocation(); - - const rpQuery = useQuery({ - queryKey: ["relying-party", id], - queryFn: () => fetchRelyingParty(id!), - enabled: !!id, - }); - - const isOwnersTab = location.pathname.endsWith("/owners"); - - return ( -
-
-
-
- - - Apps - - / - Detail -
-
-
- -
-

- {rpQuery.data?.relyingParty?.name ?? "Loading App..."} -

-
-

- Client ID: {id} -

-
- Admin only -
- - {/* Tabs */} -
- - 기본 설정 - - - 소유자 (권한 관리) - -
- -
- -
-
- ); -} - -export default RPDetailPage; diff --git a/adminfront/src/features/relying-parties/routes/RPListPage.tsx b/adminfront/src/features/relying-parties/routes/RPListPage.tsx deleted file mode 100644 index c8fbee27..00000000 --- a/adminfront/src/features/relying-parties/routes/RPListPage.tsx +++ /dev/null @@ -1,146 +0,0 @@ -import { useMutation, useQuery } from "@tanstack/react-query"; -import { Pencil, Plus, RefreshCw, Trash2, Rocket } from "lucide-react"; -import { Link, useNavigate } from "react-router-dom"; -import { Badge } from "../../../components/ui/badge"; -import { Button } from "../../../components/ui/button"; -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "../../../components/ui/card"; -import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "../../../components/ui/table"; -import { deleteRelyingParty, fetchAllRelyingParties } from "../../../lib/adminApi"; - -function RPListPage() { - const navigate = useNavigate(); - const query = useQuery({ - queryKey: ["relying-parties"], - queryFn: () => fetchAllRelyingParties(), - }); - - const deleteMutation = useMutation({ - mutationFn: (id: string) => deleteRelyingParty(id), - onSuccess: () => { - query.refetch(); - }, - }); - - const items = query.data ?? []; - - const handleDelete = (id: string, name: string) => { - if (!window.confirm(`애플리케이션 "${name}"을 삭제할까요?`)) { - return; - } - deleteMutation.mutate(id); - }; - - return ( -
-
-
-
- Apps - / - List -
-

애플리케이션(RP) 목록

-

- 등록된 OAuth2 클라이언트(Relying Party) 목록입니다. -

-
-
- -
-
- - - -
- - - Relying Party Registry - - - 총 {items.length}개 앱 - -
- Admin only -
- - - - - NAME - CLIENT ID - TENANT - ACTIONS - - - - {query.isLoading && ( - - 로딩 중... - - )} - {!query.isLoading && items.length === 0 && ( - - - 등록된 애플리케이션이 없습니다. - - - )} - {items.map((rp) => ( - - {rp.name} - {rp.clientId} - - {rp.tenantId} - - -
- - -
-
-
- ))} -
-
-
-
-
- ); -} - -export default RPListPage; diff --git a/adminfront/src/features/relying-parties/routes/RPOwnersTab.tsx b/adminfront/src/features/relying-parties/routes/RPOwnersTab.tsx deleted file mode 100644 index d4b1a15b..00000000 --- a/adminfront/src/features/relying-parties/routes/RPOwnersTab.tsx +++ /dev/null @@ -1,201 +0,0 @@ -import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; -import { Plus, Trash2, ShieldCheck, Search, UserPlus } from "lucide-react"; -import { useState } from "react"; -import { useOutletContext, useParams } from "react-router-dom"; -import { Button } from "../../../components/ui/button"; -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "../../../components/ui/card"; -import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "../../../components/ui/table"; -import { Input } from "../../../components/ui/input"; -import { - fetchRPOwners, - addRPOwner, - removeRPOwner, - fetchUsers -} from "../../../lib/adminApi"; - -function RPOwnersTab() { - const { id: clientId } = useParams<{ id: string }>(); - const queryClient = useQueryClient(); - const [searchTerm, setSearchTerm] = useState(""); - - if (!clientId) return null; - - // 현재 소유자 목록 - const ownersQuery = useQuery({ - queryKey: ["rp-owners", clientId], - queryFn: () => fetchRPOwners(clientId), - enabled: !!clientId, - }); - - // 전체 사용자 목록 (소유자 추가용) - const usersQuery = useQuery({ - queryKey: ["users", { limit: 100, search: searchTerm }], - queryFn: () => fetchUsers(100, 0, searchTerm), - enabled: searchTerm.length > 1, - }); - - const addMutation = useMutation({ - mutationFn: (subject: string) => addRPOwner(clientId, subject), - onSuccess: () => { - ownersQuery.refetch(); - setSearchTerm(""); - }, - }); - - const removeMutation = useMutation({ - mutationFn: (subject: string) => removeRPOwner(clientId, subject), - onSuccess: () => { - ownersQuery.refetch(); - }, - }); - - const handleAddOwner = (userId: string) => { - addMutation.mutate(`User:${userId}`); - }; - - const handleRemoveOwner = (subject: string, name?: string) => { - if (window.confirm(`${name || subject}의 소유 권한을 회수할까요?`)) { - removeMutation.mutate(subject); - } - }; - - return ( -
- {/* 현재 앱 소유자 */} - - - - - 앱 소유자 - - - 이 애플리케이션의 설정을 관리하고 비밀번호를 회전시킬 수 있는 권한을 가진 사용자들입니다. - - - - - - - 이름/주체 - 유형 - 회수 - - - - {ownersQuery.data?.length === 0 && ( - - - 등록된 소유자가 없습니다. - - - )} - {ownersQuery.data?.map((owner) => ( - - -
{owner.name || owner.subject}
-
{owner.email}
-
- {owner.type} - - - -
- ))} -
-
-
-
- - {/* 사용자 검색 및 추가 */} - - -
- - - 소유자 추가 - -
- - 소유자로 추가할 사용자를 검색하세요. - -
- -
- - setSearchTerm(e.target.value)} - /> -
- - - - - 사용자 - 추가 - - - - {searchTerm.length < 2 && ( - - - 사용자 이름을 입력하여 검색하세요. - - - )} - {searchTerm.length >= 2 && usersQuery.data?.items.length === 0 && ( - - - 검색 결과가 없습니다. - - - )} - {usersQuery.data?.items.filter(u => !ownersQuery.data?.some(o => o.subject === `User:${u.id}`)).map((user) => ( - - -
{user.name}
-
{user.email}
-
- - - -
- ))} -
-
-
-
-
- ); -} - -export default RPOwnersTab; diff --git a/adminfront/src/features/relying-parties/routes/RPProfileTab.tsx b/adminfront/src/features/relying-parties/routes/RPProfileTab.tsx deleted file mode 100644 index 31d9bffa..00000000 --- a/adminfront/src/features/relying-parties/routes/RPProfileTab.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import { useOutletContext } from "react-router-dom"; -import { - Card, - CardContent, - CardDescription, - CardHeader, - CardTitle, -} from "../../../components/ui/card"; -import { Input } from "../../../components/ui/input"; -import { Label } from "../../../components/ui/label"; -import { Badge } from "../../../components/ui/badge"; -import type { RelyingParty, HydraClientReq } from "../../../lib/adminApi"; - -function RPProfileTab() { - const { rp } = useOutletContext<{ - rp: { relyingParty: RelyingParty; oauth2Config: HydraClientReq } - }>(); - - if (!rp) return null; - - return ( -
- - - 애플리케이션 정보 - - OAuth2 클라이언트의 기본 정보 및 상태입니다. - - - -
-
- - -
-
- - -
-
-
- -
- - Owner Tenant -
-
-
- -
- {rp.oauth2Config.scope?.split(" ").map(s => ( - {s} - ))} -
-
-
-
- - - - OAuth2 Endpoints - - -
- - - https://sso.hmac.kr/oidc/oauth2/auth - -
-
- - - https://sso.hmac.kr/oidc/oauth2/token - -
-
-
-
- ); -} - -export default RPProfileTab;