1
0
forked from baron/baron-sso

Merge pull request 'feature/devfront-logout' (#290) from feature/devfront-logout into dev

Reviewed-on: baron/baron-sso#290
This commit is contained in:
2026-02-23 09:56:08 +09:00
12 changed files with 163 additions and 104 deletions

View File

@@ -1,7 +1,7 @@
import { BadgeCheck, LogOut, Moon, ShieldHalf, Sun } from "lucide-react"; import { BadgeCheck, LogOut, Moon, ShieldHalf, Sun } from "lucide-react";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useAuth } from "react-oidc-context"; import { useAuth } from "react-oidc-context";
import { NavLink, Outlet } from "react-router-dom"; import { NavLink, Outlet, useNavigate } from "react-router-dom";
import { t } from "../../lib/i18n"; import { t } from "../../lib/i18n";
import LanguageSelector from "../common/LanguageSelector"; import LanguageSelector from "../common/LanguageSelector";
import { Toaster } from "../ui/toaster"; import { Toaster } from "../ui/toaster";
@@ -16,11 +16,20 @@ const navItems = [
]; ];
function AppLayout() { function AppLayout() {
const auth = useAuth();
const navigate = useNavigate();
const [theme, setTheme] = useState<"light" | "dark">(() => { const [theme, setTheme] = useState<"light" | "dark">(() => {
const stored = window.localStorage.getItem("admin_theme"); const stored = window.localStorage.getItem("admin_theme");
return stored === "dark" ? "dark" : "light"; return stored === "dark" ? "dark" : "light";
}); });
const handleLogout = () => {
if (window.confirm(t("msg.dev.logout_confirm", "로그아웃 하시겠습니까?"))) {
auth.removeUser();
navigate("/login");
}
};
useEffect(() => { useEffect(() => {
const root = document.documentElement; const root = document.documentElement;
root.classList.remove("light", "dark"); root.classList.remove("light", "dark");
@@ -38,60 +47,73 @@ function AppLayout() {
return ( return (
<div className="grid min-h-screen bg-background text-foreground md:grid-cols-[240px,1fr]"> <div className="grid min-h-screen bg-background text-foreground md:grid-cols-[240px,1fr]">
<aside className="border-b border-border bg-card md:sticky md:top-0 md:h-screen md:border-b-0 md:border-r md:bg-card md:backdrop-blur"> <aside className="border-b border-border bg-card md:sticky md:top-0 md:h-screen md:border-b-0 md:border-r md:bg-card md:backdrop-blur flex flex-col justify-between">
<div className="flex items-center justify-between px-5 py-4 md:block md:space-y-6 md:py-6"> <div>
<div className="flex items-center gap-3 md:flex-col md:items-start"> <div className="flex items-center justify-between px-5 py-4 md:block md:space-y-6 md:py-6">
<div className="grid h-11 w-11 place-items-center rounded-xl bg-primary/15 text-primary shadow-[0_12px_30px_rgba(54,211,153,0.22)]"> <div className="flex items-center gap-3 md:flex-col md:items-start">
<ShieldHalf size={20} /> <div className="grid h-11 w-11 place-items-center rounded-xl bg-primary/15 text-primary shadow-[0_12px_30px_rgba(54,211,153,0.22)]">
<ShieldHalf size={20} />
</div>
<div>
<p className="text-xs uppercase tracking-[0.18em] text-muted-foreground">
{t("ui.dev.brand", "Baron 로그인")}
</p>
<h1 className="text-lg font-semibold">
{t("ui.dev.console_title", "Developer Console")}
</h1>
</div>
</div> </div>
<div> <div className="hidden rounded-full border border-border px-3 py-2 text-xs text-muted-foreground md:inline-flex md:items-center md:gap-2">
<p className="text-xs uppercase tracking-[0.18em] text-muted-foreground"> <BadgeCheck size={14} />
{t("ui.dev.brand", "Baron 로그인")} {t("ui.dev.scope_badge", "Scoped to /dev")}
</p>
<h1 className="text-lg font-semibold">
{t("ui.dev.console_title", "Developer Console")}
</h1>
</div> </div>
</div> </div>
<div className="hidden rounded-full border border-border px-3 py-2 text-xs text-muted-foreground md:inline-flex md:items-center md:gap-2"> <nav className="px-2 pb-4 md:px-3 md:pb-8">
<BadgeCheck size={14} /> <div className="flex flex-wrap gap-2 px-3 pb-4 text-[11px] text-muted-foreground md:flex-col md:items-start">
{t("ui.dev.scope_badge", "Scoped to /dev")} <span className="rounded-full border border-border px-3 py-1">
{t("ui.dev.env_badge", "Env: dev")}
</span>
</div>
<div className="flex flex-col gap-1">
{navItems.map(({ labelKey, labelFallback, to, icon: Icon }) => (
<NavLink
key={to}
to={to}
className={({ isActive }) =>
[
"flex items-center gap-3 rounded-xl px-3 py-3 text-sm transition",
isActive
? "bg-primary/10 text-primary shadow-[0_12px_40px_rgba(54,211,153,0.18)]"
: "text-muted-foreground hover:bg-muted/10 hover:text-foreground",
].join(" ")
}
>
<Icon size={18} />
<span>{t(labelKey, labelFallback)}</span>
</NavLink>
))}
</div>
</nav>
<div className="hidden space-y-2 px-5 pb-6 text-xs text-[var(--color-muted)] md:block">
<p>{t("msg.dev.sidebar.notice", "개발자 전용 콘솔입니다.")}</p>
<p>
{t(
"msg.dev.sidebar.notice_detail",
"클라이언트 애플리케이션 등록 및 관리를 수행할 수 있습니다.",
)}
</p>
</div> </div>
</div> </div>
<nav className="px-2 pb-4 md:px-3 md:pb-8">
<div className="flex flex-wrap gap-2 px-3 pb-4 text-[11px] text-muted-foreground md:flex-col md:items-start"> <div className="px-2 pb-6 md:px-3">
<span className="rounded-full border border-border px-3 py-1"> <button
{t("ui.dev.env_badge", "Env: dev")} type="button"
</span> onClick={handleLogout}
</div> className="flex w-full items-center gap-3 rounded-xl px-3 py-3 text-sm text-muted-foreground transition hover:bg-muted/10 hover:text-foreground"
<div className="flex flex-col gap-1"> >
{navItems.map(({ labelKey, labelFallback, to, icon: Icon }) => ( <LogOut size={18} />
<NavLink <span>{t("ui.dev.nav.logout", "Logout")}</span>
key={to} </button>
to={to}
className={({ isActive }) =>
[
"flex items-center gap-3 rounded-xl px-3 py-3 text-sm transition",
isActive
? "bg-primary/10 text-primary shadow-[0_12px_40px_rgba(54,211,153,0.18)]"
: "text-muted-foreground hover:bg-muted/10 hover:text-foreground",
].join(" ")
}
>
<Icon size={18} />
<span>{t(labelKey, labelFallback)}</span>
</NavLink>
))}
</div>
</nav>
<div className="hidden space-y-2 px-5 pb-6 text-xs text-[var(--color-muted)] md:block">
<p>{t("msg.dev.sidebar.notice", "개발자 전용 콘솔입니다.")}</p>
<p>
{t(
"msg.dev.sidebar.notice_detail",
"클라이언트 애플리케이션 등록 및 관리를 수행할 수 있습니다.",
)}
</p>
</div> </div>
</aside> </aside>

View File

@@ -69,7 +69,7 @@ function ClientConsentsPage() {
</Link> </Link>
<span>/</span> <span>/</span>
<Link to="/clients" className="hover:text-primary"> <Link to="/clients" className="hover:text-primary">
{t("ui.dev.clients.consents.breadcrumb.clients", "Clients")} {t("ui.dev.clients.consents.breadcrumb.clients", "Apps")}
</Link> </Link>
<span>/</span> <span>/</span>
<span>{clientData?.client?.name || clientId}</span> <span>{clientData?.client?.name || clientId}</span>

View File

@@ -124,7 +124,7 @@ function ClientDetailsPage() {
if (isLoading) { if (isLoading) {
return ( return (
<div className="p-8 text-center"> <div className="p-8 text-center">
{t("msg.dev.clients.details.loading", "Loading client...")} {t("msg.dev.clients.details.loading", "Loading app...")}
</div> </div>
); );
} }
@@ -137,7 +137,7 @@ function ClientDetailsPage() {
<div className="p-8 text-center text-red-500"> <div className="p-8 text-center text-red-500">
{t( {t(
"msg.dev.clients.details.load_error", "msg.dev.clients.details.load_error",
"Error loading client: {{error}}", "Error loading app: {{error}}",
{ error: errMsg || t("msg.common.unknown_error", "unknown error") }, { error: errMsg || t("msg.common.unknown_error", "unknown error") },
)} )}
</div> </div>
@@ -185,7 +185,7 @@ function ClientDetailsPage() {
<div className="space-y-3"> <div className="space-y-3">
<div className="flex flex-wrap items-center gap-2 text-sm text-muted-foreground"> <div className="flex flex-wrap items-center gap-2 text-sm text-muted-foreground">
<Link to="/clients" className="text-primary hover:underline"> <Link to="/clients" className="text-primary hover:underline">
{t("ui.dev.clients.details.breadcrumb.section", "Relying Parties")} {t("ui.dev.clients.details.breadcrumb.section", "Apps")}
</Link> </Link>
<span>/</span> <span>/</span>
<span className="text-foreground"> <span className="text-foreground">

View File

@@ -376,7 +376,6 @@ function ClientGeneralPage() {
<table className="w-full text-sm"> <table className="w-full text-sm">
<thead className="bg-muted/50 border-b border-border text-xs uppercase tracking-wider text-muted-foreground"> <thead className="bg-muted/50 border-b border-border text-xs uppercase tracking-wider text-muted-foreground">
<tr> <tr>
<th className="px-4 py-3 text-left font-bold">Scope Name</th>
<th className="px-4 py-3 text-left font-bold"> <th className="px-4 py-3 text-left font-bold">
{t( {t(
"ui.dev.clients.general.scopes.table.name", "ui.dev.clients.general.scopes.table.name",
@@ -395,7 +394,9 @@ function ClientGeneralPage() {
"Mandatory", "Mandatory",
)} )}
</th> </th>
<th className="px-4 py-3 text-right" /> <th className="px-4 py-3 text-right font-bold">
{t("ui.dev.clients.general.scopes.table.delete", "Delete")}
</th>
</tr> </tr>
</thead> </thead>
<tbody className="divide-y divide-border"> <tbody className="divide-y divide-border">

View File

@@ -101,7 +101,7 @@ function ClientsPage() {
const stats: StatItem[] = [ const stats: StatItem[] = [
{ {
labelKey: "ui.dev.clients.stats.total", labelKey: "ui.dev.clients.stats.total",
labelFallback: "총 클라이언트", labelFallback: "총 애플리케이션",
value: totalClients.toString(), value: totalClients.toString(),
deltaKey: "ui.dev.clients.stats.realtime", deltaKey: "ui.dev.clients.stats.realtime",
deltaFallback: "Realtime", deltaFallback: "Realtime",

View File

@@ -205,14 +205,15 @@ saving = "Saving..."
unknown_error = "unknown error" unknown_error = "unknown error"
[msg.dev] [msg.dev]
logout_confirm = "Are you sure you want to log out?"
[msg.dev.clients] [msg.dev.clients]
copy_client_id = "Copy Client Id" copy_client_id = "Copy Client Id"
load_error = "Error loading clients: {{error}}" load_error = "Error loading clients: {{error}}"
loading = "Loading clients..." loading = "Loading apps..."
showing = "Showing {{shown}} of {{total}} clients" showing = "Showing {{shown}} of {{total}} apps"
status_update_error = "Failed to update client status" status_update_error = "Failed to update client status"
status_updated = "Status Updated" status_updated = "The app has been {{status}}."
[msg.dev.clients.consents] [msg.dev.clients.consents]
empty = "No consents found." empty = "No consents found."
@@ -927,10 +928,14 @@ console_title = "Developer Console"
env_badge = "Env: dev" env_badge = "Env: dev"
scope_badge = "Scoped to /dev" scope_badge = "Scoped to /dev"
[ui.dev.nav]
clients = "Connected Application"
logout = "Logout"
[ui.dev.clients] [ui.dev.clients]
copy_client_id = "Copy client id" copy_client_id = "Copy client id"
new = "New" new = "Add Connected Application"
search_placeholder = "Search Placeholder" search_placeholder = "Search by app name or ID..."
tenant_scoped = "Tenant-scoped" tenant_scoped = "Tenant-scoped"
untitled = "Untitled" untitled = "Untitled"
@@ -1006,8 +1011,8 @@ consents = "Consent & Users"
settings = "Settings" settings = "Settings"
[ui.dev.clients.general] [ui.dev.clients.general]
create = "Create" create = "Create Application"
display_new = "Display New" display_new = "Add Connected Application"
save = "Settings Save" save = "Settings Save"
title_create = "Create Client" title_create = "Create Client"
title_edit = "Client Settings" title_edit = "Client Settings"
@@ -1043,6 +1048,7 @@ title = "Scopes"
description = "Description" description = "Description"
mandatory = "Mandatory" mandatory = "Mandatory"
name = "Scope Name" name = "Scope Name"
delete = "Delete"
[ui.dev.clients.general.security] [ui.dev.clients.general.security]
confidential = "Confidential" confidential = "Confidential"
@@ -1055,7 +1061,7 @@ title = "Need help with OIDC configuration?"
view_guides = "View guides" view_guides = "View guides"
[ui.dev.clients.list] [ui.dev.clients.list]
title = "Title" title = "Connected Applications"
[ui.dev.clients.owner] [ui.dev.clients.owner]
avatar_alt = "ops user" avatar_alt = "ops user"

View File

@@ -205,14 +205,15 @@ saving = "저장 중..."
unknown_error = "unknown error" unknown_error = "unknown error"
[msg.dev] [msg.dev]
logout_confirm = "로그아웃 하시겠습니까?"
[msg.dev.clients] [msg.dev.clients]
copy_client_id = "클라이언트 ID가 복사되었습니다." copy_client_id = "Client ID가 복사되었습니다."
load_error = "Error loading clients: {{error}}" load_error = "Error loading clients: {{error}}"
loading = "Loading clients..." loading = "Loading apps..."
showing = "Showing {{shown}} of {{total}} clients" showing = "Showing {{shown}} of {{total}} apps"
status_update_error = "Failed to update client status" status_update_error = "Failed to update client status"
status_updated = "클라이언트가 {{status}}되었습니다." status_updated = "앱이 {{status}}되었습니다."
[msg.dev.clients.consents] [msg.dev.clients.consents]
empty = "No consents found." empty = "No consents found."
@@ -257,19 +258,19 @@ help = "인증 후 리다이렉트될 URI를 입력하세요. 생성 후 Connect
[msg.dev.clients.general.scopes] [msg.dev.clients.general.scopes]
empty = "등록된 스코프가 없습니다." empty = "등록된 스코프가 없습니다."
subtitle = "이 클라이언트가 요청할 수 있는 권한 범위를 정의합니다." subtitle = "이 앱이 요청할 수 있는 권한 범위를 정의합니다."
[msg.dev.clients.general.security] [msg.dev.clients.general.security]
confidential_help = "서버 사이드 앱(예: Node.js, Java)처럼 비밀키를 안전하게 보관 가능한 경우." confidential_help = "서버 사이드 앱(예: Node.js, Java)처럼 비밀키를 안전하게 보관 가능한 경우."
public_help = "SPA/모바일 앱처럼 비밀키 보관이 어려운 경우. PKCE를 기본 사용합니다." public_help = "SPA/모바일 앱처럼 비밀키 보관이 어려운 경우. PKCE를 기본 사용합니다."
subtitle = "클라이언트 유형을 선택하세요. 보안 수준에 따라 인증 방식이 달라집니다." subtitle = " 유형을 선택하세요. 보안 수준에 따라 인증 방식이 달라집니다."
[msg.dev.clients.help] [msg.dev.clients.help]
docs_body = "Includes PKCE, client_secret_basic, redirect URI validation tips." docs_body = "Includes PKCE, client_secret_basic, redirect URI validation tips."
subtitle = "Developer guides for Confidential/Public clients, redirect URIs, and auth methods." subtitle = "Developer guides for Confidential/Public clients, redirect URIs, and auth methods."
[msg.dev.clients.registry] [msg.dev.clients.registry]
description = "OIDC 클라이언트, 인증 방식, 리다이렉트 URI, 비밀키 재발행을 감사 로그와 함께 관리합니다." description = "OIDC , 인증 방식, 리다이렉트 URI, 비밀키 재발행을 감사 로그와 함께 관리합니다."
[msg.dev.clients.scopes] [msg.dev.clients.scopes]
email = "이메일 주소 접근" email = "이메일 주소 접근"
@@ -291,7 +292,7 @@ hydra_health = "Hydra Admin 상태 체크 준비"
[msg.dev.sidebar] [msg.dev.sidebar]
notice = "개발자 전용 콘솔입니다." notice = "개발자 전용 콘솔입니다."
notice_detail = "클라이언트 애플리케이션 등록 및 관리를 수행할 수 있습니다." notice_detail = "연동 앱 등록 및 관리를 수행할 수 있습니다."
[msg.info] [msg.info]
saved_success = "저장이 완료되었습니다." saved_success = "저장이 완료되었습니다."
@@ -927,10 +928,14 @@ console_title = "Developer Console"
env_badge = "Env: dev" env_badge = "Env: dev"
scope_badge = "Scoped to /dev" scope_badge = "Scoped to /dev"
[ui.dev.nav]
clients = "연동 앱"
logout = "로그아웃"
[ui.dev.clients] [ui.dev.clients]
copy_client_id = "Copy client id" copy_client_id = "Copy client id"
new = "새 클라이언트" new = "연동 앱 추가"
search_placeholder = "클라이언트 이름/ID로 검색..." search_placeholder = "연동 앱 이름/ID로 검색..."
tenant_scoped = "Tenant-scoped" tenant_scoped = "Tenant-scoped"
untitled = "Untitled" untitled = "Untitled"
@@ -973,13 +978,13 @@ user = "User"
[ui.dev.clients.details] [ui.dev.clients.details]
[ui.dev.clients.details.breadcrumb] [ui.dev.clients.details.breadcrumb]
current = "클라이언트 상세" current = "연동 앱 상세"
section = "Relying Parties" section = "Relying Parties"
[ui.dev.clients.details.credentials] [ui.dev.clients.details.credentials]
client_id = "Client ID" client_id = "Client ID"
client_secret = "Client Secret" client_secret = "Client Secret"
title = "클라이언트 자격 증명" title = " 자격 증명"
[ui.dev.clients.details.endpoints] [ui.dev.clients.details.endpoints]
read_only = "읽기 전용" read_only = "읽기 전용"
@@ -1006,8 +1011,8 @@ consents = "Consent & Users"
settings = "Settings" settings = "Settings"
[ui.dev.clients.general] [ui.dev.clients.general]
create = "클라이언트 생성" create = " 생성"
display_new = "새 클라이언트" display_new = "연동 앱 추가"
save = "설정 저장" save = "설정 저장"
title_create = "Create Client" title_create = "Create Client"
title_edit = "Client Settings" title_edit = "Client Settings"
@@ -1043,6 +1048,7 @@ title = "Scopes"
description = "Description" description = "Description"
mandatory = "Mandatory" mandatory = "Mandatory"
name = "Scope Name" name = "Scope Name"
delete = "Delete"
[ui.dev.clients.general.security] [ui.dev.clients.general.security]
confidential = "Confidential" confidential = "Confidential"
@@ -1055,7 +1061,7 @@ title = "Need help with OIDC configuration?"
view_guides = "View guides" view_guides = "View guides"
[ui.dev.clients.list] [ui.dev.clients.list]
title = "클라이언트 목록" title = "연동 앱 목록"
[ui.dev.clients.owner] [ui.dev.clients.owner]
avatar_alt = "ops user" avatar_alt = "ops user"

View File

@@ -205,6 +205,7 @@ saving = ""
unknown_error = "" unknown_error = ""
[msg.dev] [msg.dev]
logout_confirm = ""
[msg.dev.clients] [msg.dev.clients]
copy_client_id = "" copy_client_id = ""
@@ -939,6 +940,10 @@ console_title = ""
env_badge = "" env_badge = ""
scope_badge = "" scope_badge = ""
[ui.dev.nav]
clients = ""
logout = ""
[ui.dev.clients] [ui.dev.clients]
copy_client_id = "" copy_client_id = ""
new = "" new = ""
@@ -1055,6 +1060,7 @@ title = ""
description = "" description = ""
mandatory = "" mandatory = ""
name = "" name = ""
delete = ""
[ui.dev.clients.general.security] [ui.dev.clients.general.security]
confidential = "" confidential = ""

View File

@@ -68,7 +68,7 @@ test("clients page loads correctly", async ({ page }) => {
await expect(page).toHaveTitle(/바론 개발자 서비스/); await expect(page).toHaveTitle(/바론 개발자 서비스/);
// 페이지 내 주요 텍스트 확인 // 페이지 내 주요 텍스트 확인
await expect(page.getByText("클라이언트 목록")).toBeVisible(); await expect(page.getByText("연동 앱 목록")).toBeVisible();
// 테이블 헤더 확인 // 테이블 헤더 확인
await expect( await expect(

View File

@@ -205,14 +205,15 @@ saving = "Saving..."
unknown_error = "unknown error" unknown_error = "unknown error"
[msg.dev] [msg.dev]
logout_confirm = "Are you sure you want to log out?"
[msg.dev.clients] [msg.dev.clients]
copy_client_id = "Copy Client Id" copy_client_id = "Copy Client Id"
load_error = "Error loading clients: {{error}}" load_error = "Error loading clients: {{error}}"
loading = "Loading clients..." loading = "Loading apps..."
showing = "Showing {{shown}} of {{total}} clients" showing = "Showing {{shown}} of {{total}} apps"
status_update_error = "Failed to update client status" status_update_error = "Failed to update client status"
status_updated = "Status Updated" status_updated = "The app has been {{status}}."
[msg.dev.clients.consents] [msg.dev.clients.consents]
empty = "No consents found." empty = "No consents found."
@@ -927,10 +928,14 @@ console_title = "Developer Console"
env_badge = "Env: dev" env_badge = "Env: dev"
scope_badge = "Scoped to /dev" scope_badge = "Scoped to /dev"
[ui.dev.nav]
clients = "Connected Application"
logout = "Logout"
[ui.dev.clients] [ui.dev.clients]
copy_client_id = "Copy client id" copy_client_id = "Copy client id"
new = "New" new = "Add Connected Application"
search_placeholder = "Search Placeholder" search_placeholder = "Search by app name or ID..."
tenant_scoped = "Tenant-scoped" tenant_scoped = "Tenant-scoped"
untitled = "Untitled" untitled = "Untitled"
@@ -1006,8 +1011,8 @@ consents = "Consent & Users"
settings = "Settings" settings = "Settings"
[ui.dev.clients.general] [ui.dev.clients.general]
create = "Create" create = "Create Application"
display_new = "Display New" display_new = "Add Connected Application"
save = "Settings Save" save = "Settings Save"
title_create = "Create Client" title_create = "Create Client"
title_edit = "Client Settings" title_edit = "Client Settings"
@@ -1043,6 +1048,7 @@ title = "Scopes"
description = "Description" description = "Description"
mandatory = "Mandatory" mandatory = "Mandatory"
name = "Scope Name" name = "Scope Name"
delete = "Delete"
[ui.dev.clients.general.security] [ui.dev.clients.general.security]
confidential = "Confidential" confidential = "Confidential"
@@ -1055,7 +1061,7 @@ title = "Need help with OIDC configuration?"
view_guides = "View guides" view_guides = "View guides"
[ui.dev.clients.list] [ui.dev.clients.list]
title = "Title" title = "Connected Applications"
[ui.dev.clients.owner] [ui.dev.clients.owner]
avatar_alt = "ops user" avatar_alt = "ops user"

View File

@@ -205,14 +205,15 @@ saving = "저장 중..."
unknown_error = "unknown error" unknown_error = "unknown error"
[msg.dev] [msg.dev]
logout_confirm = "로그아웃 하시겠습니까?"
[msg.dev.clients] [msg.dev.clients]
copy_client_id = "클라이언트 ID가 복사되었습니다." copy_client_id = "Client ID가 복사되었습니다."
load_error = "Error loading clients: {{error}}" load_error = "Error loading clients: {{error}}"
loading = "Loading clients..." loading = "Loading apps..."
showing = "Showing {{shown}} of {{total}} clients" showing = "Showing {{shown}} of {{total}} apps"
status_update_error = "Failed to update client status" status_update_error = "Failed to update client status"
status_updated = "클라이언트가 {{status}}되었습니다." status_updated = "앱이 {{status}}되었습니다."
[msg.dev.clients.consents] [msg.dev.clients.consents]
empty = "No consents found." empty = "No consents found."
@@ -257,19 +258,19 @@ help = "인증 후 리다이렉트될 URI를 입력하세요. 생성 후 Connect
[msg.dev.clients.general.scopes] [msg.dev.clients.general.scopes]
empty = "등록된 스코프가 없습니다." empty = "등록된 스코프가 없습니다."
subtitle = "이 클라이언트가 요청할 수 있는 권한 범위를 정의합니다." subtitle = "이 앱이 요청할 수 있는 권한 범위를 정의합니다."
[msg.dev.clients.general.security] [msg.dev.clients.general.security]
confidential_help = "서버 사이드 앱(예: Node.js, Java)처럼 비밀키를 안전하게 보관 가능한 경우." confidential_help = "서버 사이드 앱(예: Node.js, Java)처럼 비밀키를 안전하게 보관 가능한 경우."
public_help = "SPA/모바일 앱처럼 비밀키 보관이 어려운 경우. PKCE를 기본 사용합니다." public_help = "SPA/모바일 앱처럼 비밀키 보관이 어려운 경우. PKCE를 기본 사용합니다."
subtitle = "클라이언트 유형을 선택하세요. 보안 수준에 따라 인증 방식이 달라집니다." subtitle = " 유형을 선택하세요. 보안 수준에 따라 인증 방식이 달라집니다."
[msg.dev.clients.help] [msg.dev.clients.help]
docs_body = "Includes PKCE, client_secret_basic, redirect URI validation tips." docs_body = "Includes PKCE, client_secret_basic, redirect URI validation tips."
subtitle = "Developer guides for Confidential/Public clients, redirect URIs, and auth methods." subtitle = "Developer guides for Confidential/Public clients, redirect URIs, and auth methods."
[msg.dev.clients.registry] [msg.dev.clients.registry]
description = "OIDC 클라이언트, 인증 방식, 리다이렉트 URI, 비밀키 재발행을 감사 로그와 함께 관리합니다." description = "OIDC , 인증 방식, 리다이렉트 URI, 비밀키 재발행을 감사 로그와 함께 관리합니다."
[msg.dev.clients.scopes] [msg.dev.clients.scopes]
email = "이메일 주소 접근" email = "이메일 주소 접근"
@@ -291,7 +292,7 @@ hydra_health = "Hydra Admin 상태 체크 준비"
[msg.dev.sidebar] [msg.dev.sidebar]
notice = "개발자 전용 콘솔입니다." notice = "개발자 전용 콘솔입니다."
notice_detail = "클라이언트 애플리케이션 등록 및 관리를 수행할 수 있습니다." notice_detail = "연동 앱 등록 및 관리를 수행할 수 있습니다."
[msg.info] [msg.info]
saved_success = "저장이 완료되었습니다." saved_success = "저장이 완료되었습니다."
@@ -927,10 +928,14 @@ console_title = "Developer Console"
env_badge = "Env: dev" env_badge = "Env: dev"
scope_badge = "Scoped to /dev" scope_badge = "Scoped to /dev"
[ui.dev.nav]
clients = "연동 앱"
logout = "로그아웃"
[ui.dev.clients] [ui.dev.clients]
copy_client_id = "Copy client id" copy_client_id = "Copy client id"
new = "새 클라이언트" new = "연동 앱 추가"
search_placeholder = "클라이언트 이름/ID로 검색..." search_placeholder = "연동 앱 이름/ID로 검색..."
tenant_scoped = "Tenant-scoped" tenant_scoped = "Tenant-scoped"
untitled = "Untitled" untitled = "Untitled"
@@ -973,13 +978,13 @@ user = "User"
[ui.dev.clients.details] [ui.dev.clients.details]
[ui.dev.clients.details.breadcrumb] [ui.dev.clients.details.breadcrumb]
current = "클라이언트 상세" current = "연동 앱 상세"
section = "Relying Parties" section = "Relying Parties"
[ui.dev.clients.details.credentials] [ui.dev.clients.details.credentials]
client_id = "Client ID" client_id = "Client ID"
client_secret = "Client Secret" client_secret = "Client Secret"
title = "클라이언트 자격 증명" title = " 자격 증명"
[ui.dev.clients.details.endpoints] [ui.dev.clients.details.endpoints]
read_only = "읽기 전용" read_only = "읽기 전용"
@@ -1006,8 +1011,8 @@ consents = "Consent & Users"
settings = "Settings" settings = "Settings"
[ui.dev.clients.general] [ui.dev.clients.general]
create = "클라이언트 생성" create = " 생성"
display_new = "새 클라이언트" display_new = "연동 앱 추가"
save = "설정 저장" save = "설정 저장"
title_create = "Create Client" title_create = "Create Client"
title_edit = "Client Settings" title_edit = "Client Settings"
@@ -1043,6 +1048,7 @@ title = "Scopes"
description = "Description" description = "Description"
mandatory = "Mandatory" mandatory = "Mandatory"
name = "Scope Name" name = "Scope Name"
delete = "Delete"
[ui.dev.clients.general.security] [ui.dev.clients.general.security]
confidential = "Confidential" confidential = "Confidential"
@@ -1055,7 +1061,7 @@ title = "Need help with OIDC configuration?"
view_guides = "View guides" view_guides = "View guides"
[ui.dev.clients.list] [ui.dev.clients.list]
title = "클라이언트 목록" title = "연동 앱 목록"
[ui.dev.clients.owner] [ui.dev.clients.owner]
avatar_alt = "ops user" avatar_alt = "ops user"

View File

@@ -205,6 +205,7 @@ saving = ""
unknown_error = "" unknown_error = ""
[msg.dev] [msg.dev]
logout_confirm = ""
[msg.dev.clients] [msg.dev.clients]
copy_client_id = "" copy_client_id = ""
@@ -939,6 +940,10 @@ console_title = ""
env_badge = "" env_badge = ""
scope_badge = "" scope_badge = ""
[ui.dev.nav]
clients = ""
logout = ""
[ui.dev.clients] [ui.dev.clients]
copy_client_id = "" copy_client_id = ""
new = "" new = ""
@@ -1055,6 +1060,7 @@ title = ""
description = "" description = ""
mandatory = "" mandatory = ""
name = "" name = ""
delete = ""
[ui.dev.clients.general.security] [ui.dev.clients.general.security]
confidential = "" confidential = ""