forked from baron/baron-sso
애플리케이션(RP) 관리 기능 구현 및 Ory Keto 권한 연동
This commit is contained in:
@@ -11,6 +11,10 @@ import TenantDetailPage from "../features/tenants/routes/TenantDetailPage";
|
||||
import TenantListPage from "../features/tenants/routes/TenantListPage";
|
||||
import { TenantProfilePage } from "../features/tenants/routes/TenantProfilePage";
|
||||
import { TenantSchemaPage } from "../features/tenants/routes/TenantSchemaPage";
|
||||
import TenantRelyingPartyListPage from "../features/tenants/routes/TenantRelyingPartyListPage";
|
||||
import TenantRelyingPartyCreatePage from "../features/tenants/routes/TenantRelyingPartyCreatePage";
|
||||
import TenantRelyingPartyDetailPage from "../features/tenants/routes/TenantRelyingPartyDetailPage";
|
||||
import RelyingPartyListPage from "../features/relying-parties/RelyingPartyListPage";
|
||||
import UserCreatePage from "../features/users/UserCreatePage";
|
||||
import UserDetailPage from "../features/users/UserDetailPage";
|
||||
import UserListPage from "../features/users/UserListPage";
|
||||
@@ -28,6 +32,7 @@ export const router = createBrowserRouter(
|
||||
{ path: "users", element: <UserListPage /> },
|
||||
{ path: "users/new", element: <UserCreatePage /> },
|
||||
{ path: "users/:id", element: <UserDetailPage /> },
|
||||
{ path: "relying-parties", element: <RelyingPartyListPage /> },
|
||||
{ path: "tenants", element: <TenantListPage /> },
|
||||
{ path: "tenants/new", element: <TenantCreatePage /> },
|
||||
{
|
||||
@@ -36,6 +41,9 @@ export const router = createBrowserRouter(
|
||||
children: [
|
||||
{ index: true, element: <TenantProfilePage /> },
|
||||
{ path: "schema", element: <TenantSchemaPage /> },
|
||||
{ path: "relying-parties", element: <TenantRelyingPartyListPage /> },
|
||||
{ path: "relying-parties/new", element: <TenantRelyingPartyCreatePage /> },
|
||||
{ path: "relying-parties/:id", element: <TenantRelyingPartyDetailPage /> },
|
||||
],
|
||||
},
|
||||
{ path: "api-keys", element: <ApiKeyListPage /> },
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
ShieldHalf,
|
||||
Sun,
|
||||
Users,
|
||||
Share2,
|
||||
} from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { NavLink, Outlet } from "react-router-dom";
|
||||
@@ -19,6 +20,7 @@ const navItems = [
|
||||
{ label: "Tenant Dashboard", to: "/dashboard", icon: ShieldHalf },
|
||||
{ label: "Tenants", to: "/tenants", icon: Building2 },
|
||||
{ label: "Users", to: "/users", icon: Users },
|
||||
{ label: "Applications", to: "/relying-parties", icon: Share2 },
|
||||
{ label: "API Keys (M2M)", to: "/api-keys", icon: Key },
|
||||
{ label: "Audit Logs", to: "/audit-logs", icon: NotebookTabs },
|
||||
{ label: "Auth Guard", to: "/auth", icon: KeyRound },
|
||||
|
||||
@@ -70,6 +70,16 @@ function TenantDetailPage() {
|
||||
>
|
||||
Schema
|
||||
</Link>
|
||||
<Link
|
||||
to={`/tenants/${tenantId}/relying-parties`}
|
||||
className={`px-4 py-2 text-sm font-medium ${
|
||||
location.pathname.includes("/relying-parties")
|
||||
? "border-b-2 border-blue-500 text-blue-600"
|
||||
: "text-gray-500 hover:text-gray-700"
|
||||
}`}
|
||||
>
|
||||
Relying Parties
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
{/* Outlet for nested routes */}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { Label } from "../../components/ui/label";
|
||||
import {
|
||||
createUser,
|
||||
fetchTenants,
|
||||
fetchTenant,
|
||||
type UserCreateRequest,
|
||||
type UserCreateResponse,
|
||||
} from "../../lib/adminApi";
|
||||
|
||||
@@ -17,6 +17,7 @@ import { Label } from "../../components/ui/label";
|
||||
import {
|
||||
fetchUser,
|
||||
fetchTenants,
|
||||
fetchTenant,
|
||||
updateUser,
|
||||
type UserUpdateRequest,
|
||||
} from "../../lib/adminApi";
|
||||
|
||||
@@ -252,3 +252,70 @@ export async function updateUser(userId: string, payload: UserUpdateRequest) {
|
||||
export async function deleteUser(userId: string) {
|
||||
await apiClient.delete(`/v1/admin/users/${userId}`);
|
||||
}
|
||||
|
||||
// Relying Party Management
|
||||
export type RelyingParty = {
|
||||
clientId: string;
|
||||
tenantId: string;
|
||||
name: string;
|
||||
description: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export type HydraClientReq = {
|
||||
client_id?: string;
|
||||
client_name: string;
|
||||
client_secret?: string;
|
||||
redirect_uris: string[];
|
||||
scope?: string;
|
||||
token_endpoint_auth_method?: string;
|
||||
grant_types?: string[];
|
||||
response_types?: string[];
|
||||
metadata?: Record<string, any>;
|
||||
};
|
||||
|
||||
export async function fetchRelyingParties(tenantId: string) {
|
||||
const { data } = await apiClient.get<RelyingParty[]>(
|
||||
`/v1/admin/tenants/${tenantId}/relying-parties`,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function fetchAllRelyingParties() {
|
||||
const { data } = await apiClient.get<RelyingParty[]>(
|
||||
"/v1/admin/relying-parties",
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function createRelyingParty(
|
||||
tenantId: string,
|
||||
payload: HydraClientReq,
|
||||
) {
|
||||
const { data } = await apiClient.post<RelyingParty>(
|
||||
`/v1/admin/tenants/${tenantId}/relying-parties`,
|
||||
payload,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function fetchRelyingParty(id: string) {
|
||||
const { data } = await apiClient.get<{
|
||||
relyingParty: RelyingParty;
|
||||
oauth2Config: HydraClientReq;
|
||||
}>(`/v1/admin/relying-parties/${id}`);
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function updateRelyingParty(id: string, payload: HydraClientReq) {
|
||||
const { data } = await apiClient.put<RelyingParty>(
|
||||
`/v1/admin/relying-parties/${id}`,
|
||||
payload,
|
||||
);
|
||||
return data;
|
||||
}
|
||||
|
||||
export async function deleteRelyingParty(id: string) {
|
||||
await apiClient.delete(`/v1/admin/relying-parties/${id}`);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user