1
0
forked from baron/baron-sso

감사 로그 403 권한 안내 문구 및 locale 키 반영

This commit is contained in:
2026-03-03 14:51:54 +09:00
parent 11a06fa94d
commit f485c07f54
10 changed files with 43 additions and 24 deletions

View File

@@ -26,16 +26,16 @@ func TestDevHandler_Isolation(t *testing.T) {
if r.Method == http.MethodGet && r.URL.Path == "/clients" { if r.Method == http.MethodGet && r.URL.Path == "/clients" {
return httpJSONAny(r, http.StatusOK, []map[string]interface{}{ return httpJSONAny(r, http.StatusOK, []map[string]interface{}{
{ {
"client_id": "client-tenant-a", "client_id": "client-tenant-a",
"client_name": "App Tenant A", "client_name": "App Tenant A",
"token_endpoint_auth_method": "none", // PKCE "token_endpoint_auth_method": "none", // PKCE
"metadata": map[string]interface{}{"tenant_id": "tenant-a"}, "metadata": map[string]interface{}{"tenant_id": "tenant-a"},
}, },
{ {
"client_id": "client-tenant-b", "client_id": "client-tenant-b",
"client_name": "App Tenant B", "client_name": "App Tenant B",
"token_endpoint_auth_method": "none", // PKCE "token_endpoint_auth_method": "none", // PKCE
"metadata": map[string]interface{}{"tenant_id": "tenant-b"}, "metadata": map[string]interface{}{"tenant_id": "tenant-b"},
}, },
}), nil }), nil
} }
@@ -46,10 +46,10 @@ func TestDevHandler_Isolation(t *testing.T) {
tenantID = "tenant-b" tenantID = "tenant-b"
} }
return httpJSONAny(r, http.StatusOK, map[string]interface{}{ return httpJSONAny(r, http.StatusOK, map[string]interface{}{
"client_id": id, "client_id": id,
"client_name": "App " + id, "client_name": "App " + id,
"token_endpoint_auth_method": "none", "token_endpoint_auth_method": "none",
"metadata": map[string]interface{}{"tenant_id": tenantID}, "metadata": map[string]interface{}{"tenant_id": tenantID},
}), nil }), nil
} }
if r.Method == http.MethodPost && r.URL.Path == "/clients" { if r.Method == http.MethodPost && r.URL.Path == "/clients" {

View File

@@ -180,7 +180,8 @@ function AuditLogsPage() {
); );
} }
const errMsg = axiosError.response?.data?.error ?? (query.error as Error).message; const errMsg =
axiosError.response?.data?.error ?? (query.error as Error).message;
return ( return (
<div className="p-8 text-center text-red-500"> <div className="p-8 text-center text-red-500">
{t("msg.dev.audit.load_error", "Error loading logs: {{error}}", { {t("msg.dev.audit.load_error", "Error loading logs: {{error}}", {

View File

@@ -113,7 +113,10 @@ function ClientsPage() {
labelKey: "ui.dev.clients.stats.auth_failures", labelKey: "ui.dev.clients.stats.auth_failures",
labelFallback: "Auth Failures (24h)", labelFallback: "Auth Failures (24h)",
value: authFailures.toString(), value: authFailures.toString(),
deltaKey: authFailures > 0 ? "ui.dev.clients.stats.alert" : "ui.dev.clients.stats.stable", deltaKey:
authFailures > 0
? "ui.dev.clients.stats.alert"
: "ui.dev.clients.stats.stable",
deltaFallback: authFailures > 0 ? "Check Logs" : "Stable", deltaFallback: authFailures > 0 ? "Check Logs" : "Stable",
tone: authFailures > 0 ? ("down" as const) : ("stable" as const), tone: authFailures > 0 ? ("down" as const) : ("stable" as const),
}, },
@@ -285,11 +288,11 @@ function ClientsPage() {
<span className="text-3xl font-bold">{item.value}</span> <span className="text-3xl font-bold">{item.value}</span>
<Badge <Badge
variant={ variant={
item.tone === "up" item.tone === "up"
? "success" ? "success"
: item.tone === "down" : item.tone === "down"
? "destructive" ? "destructive"
: "muted" : "muted"
} }
className={cn( className={cn(
"px-2", "px-2",

View File

@@ -957,6 +957,9 @@ logout = "Logout"
load_more = "Load more" load_more = "Load more"
title = "Audit Logs" title = "Audit Logs"
[ui.dev.audit.registry]
title = "Audit registry"
[ui.dev.audit.filter] [ui.dev.audit.filter]
action = "Filter by Action (e.g. ROTATE_SECRET)" action = "Filter by Action (e.g. ROTATE_SECRET)"
client_id = "Filter by Client ID" client_id = "Filter by Client ID"

View File

@@ -957,6 +957,9 @@ logout = "로그아웃"
load_more = "더 보기" load_more = "더 보기"
title = "감사 로그" title = "감사 로그"
[ui.dev.audit.registry]
title = "Audit registry"
[ui.dev.audit.filter] [ui.dev.audit.filter]
action = "액션으로 필터 (예: ROTATE_SECRET)" action = "액션으로 필터 (예: ROTATE_SECRET)"
client_id = "Client ID로 필터" client_id = "Client ID로 필터"

View File

@@ -969,6 +969,9 @@ logout = ""
load_more = "" load_more = ""
title = "" title = ""
[ui.dev.audit.registry]
title = ""
[ui.dev.audit.filter] [ui.dev.audit.filter]
action = "" action = ""
client_id = "" client_id = ""

View File

@@ -268,6 +268,7 @@ logout_confirm = "Are you sure you want to log out?"
[msg.dev.audit] [msg.dev.audit]
empty = "No audit logs found." empty = "No audit logs found."
forbidden = "You do not have permission to view audit logs. Please request access from an administrator."
load_error = "Error loading audit logs: {{error}}" load_error = "Error loading audit logs: {{error}}"
loaded_count = "Loaded {{count}} rows" loaded_count = "Loaded {{count}} rows"
loading = "Loading audit logs..." loading = "Loading audit logs..."
@@ -1116,6 +1117,9 @@ logout = "Logout"
load_more = "Load more" load_more = "Load more"
title = "Audit Logs" title = "Audit Logs"
[ui.dev.audit.registry]
title = "Audit registry"
[ui.dev.audit.filter] [ui.dev.audit.filter]
action = "Filter by Action (e.g. ROTATE_SECRET)" action = "Filter by Action (e.g. ROTATE_SECRET)"
client_id = "Filter by Client ID" client_id = "Filter by Client ID"

View File

@@ -268,6 +268,7 @@ logout_confirm = "로그아웃 하시겠습니까?"
[msg.dev.audit] [msg.dev.audit]
empty = "조회된 감사 로그가 없습니다." empty = "조회된 감사 로그가 없습니다."
forbidden = "감사 로그를 조회할 권한이 없습니다. 관리자에게 권한을 요청해주세요."
load_error = "감사 로그 조회 실패: {{error}}" load_error = "감사 로그 조회 실패: {{error}}"
loaded_count = "로드된 로그 {{count}}건" loaded_count = "로드된 로그 {{count}}건"
loading = "감사 로그를 불러오는 중..." loading = "감사 로그를 불러오는 중..."
@@ -1116,6 +1117,9 @@ logout = "로그아웃"
load_more = "더 보기" load_more = "더 보기"
title = "감사 로그" title = "감사 로그"
[ui.dev.audit.registry]
title = "Audit registry"
[ui.dev.audit.filter] [ui.dev.audit.filter]
action = "액션으로 필터 (예: ROTATE_SECRET)" action = "액션으로 필터 (예: ROTATE_SECRET)"
client_id = "Client ID로 필터" client_id = "Client ID로 필터"

View File

@@ -215,6 +215,7 @@ logout_confirm = ""
[msg.dev.audit] [msg.dev.audit]
empty = "" empty = ""
forbidden = ""
load_error = "" load_error = ""
loaded_count = "" loaded_count = ""
loading = "" loading = ""
@@ -999,6 +1000,9 @@ logout = ""
load_more = "" load_more = ""
title = "" title = ""
[ui.dev.audit.registry]
title = ""
[ui.dev.audit.filter] [ui.dev.audit.filter]
action = "" action = ""
client_id = "" client_id = ""

View File

@@ -7,10 +7,7 @@ void main() {
const challenge = 'loop-guard-test-challenge'; const challenge = 'loop-guard-test-challenge';
loginChallengeLoopGuard.clear(challenge); loginChallengeLoopGuard.clear(challenge);
expect( expect(loginChallengeLoopGuard.shouldAllowAutoAccept(challenge), isTrue);
loginChallengeLoopGuard.shouldAllowAutoAccept(challenge),
isTrue,
);
loginChallengeLoopGuard.markAutoAcceptAttempt(challenge); loginChallengeLoopGuard.markAutoAcceptAttempt(challenge);
@@ -24,10 +21,7 @@ void main() {
loginChallengeLoopGuard.clear(challenge); loginChallengeLoopGuard.clear(challenge);
expect( expect(loginChallengeLoopGuard.shouldAllowAutoAccept(challenge), isTrue);
loginChallengeLoopGuard.shouldAllowAutoAccept(challenge),
isTrue,
);
}); });
}); });
} }