forked from baron/baron-sso
i18n 누락 키 추가 및 로케일 템플릿 동기화
This commit is contained in:
@@ -8,7 +8,7 @@ import { t } from "../../lib/i18n";
|
|||||||
|
|
||||||
export default function ProfileTenantSwitcher() {
|
export default function ProfileTenantSwitcher() {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
const { data: tenants, isLoading } = useQuery({
|
const { data: tenants, isLoading } = useQuery({
|
||||||
queryKey: ["myTenants"],
|
queryKey: ["myTenants"],
|
||||||
queryFn: fetchMyTenants,
|
queryFn: fetchMyTenants,
|
||||||
@@ -20,7 +20,7 @@ export default function ProfileTenantSwitcher() {
|
|||||||
|
|
||||||
const handleSave = () => {
|
const handleSave = () => {
|
||||||
window.localStorage.setItem("dev_tenant_id", selectedTenantId);
|
window.localStorage.setItem("dev_tenant_id", selectedTenantId);
|
||||||
|
|
||||||
// Invalidate queries to refresh data with new tenant context
|
// Invalidate queries to refresh data with new tenant context
|
||||||
queryClient.invalidateQueries({
|
queryClient.invalidateQueries({
|
||||||
predicate: (query) =>
|
predicate: (query) =>
|
||||||
@@ -42,10 +42,15 @@ export default function ProfileTenantSwitcher() {
|
|||||||
<div className="flex flex-col gap-4 mt-6 p-4 rounded-lg border border-border bg-card">
|
<div className="flex flex-col gap-4 mt-6 p-4 rounded-lg border border-border bg-card">
|
||||||
<div className="flex items-center gap-2 mb-2">
|
<div className="flex items-center gap-2 mb-2">
|
||||||
<Building2 className="h-5 w-5 text-primary" />
|
<Building2 className="h-5 w-5 text-primary" />
|
||||||
<h3 className="font-semibold">{t("ui.dev.tenant.workspace", "작업 테넌트 (컨텍스트)")}</h3>
|
<h3 className="font-semibold">
|
||||||
|
{t("ui.dev.tenant.workspace", "작업 테넌트 (컨텍스트)")}
|
||||||
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-sm text-muted-foreground -mt-2 mb-2">
|
<p className="text-sm text-muted-foreground -mt-2 mb-2">
|
||||||
{t("ui.dev.tenant.workspace_desc", "현재 작업 중인 테넌트를 선택하고 저장하여 API 요청 컨텍스트를 변경합니다.")}
|
{t(
|
||||||
|
"ui.dev.tenant.workspace_desc",
|
||||||
|
"현재 작업 중인 테넌트를 선택하고 저장하여 API 요청 컨텍스트를 변경합니다.",
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
@@ -62,10 +67,10 @@ export default function ProfileTenantSwitcher() {
|
|||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleSave}
|
onClick={handleSave}
|
||||||
disabled={isSingleTenant}
|
disabled={isSingleTenant}
|
||||||
className="gap-2"
|
className="gap-2"
|
||||||
>
|
>
|
||||||
@@ -73,10 +78,13 @@ export default function ProfileTenantSwitcher() {
|
|||||||
{t("ui.common.save", "저장")}
|
{t("ui.common.save", "저장")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isSingleTenant && (
|
{isSingleTenant && (
|
||||||
<p className="text-xs text-muted-foreground mt-1">
|
<p className="text-xs text-muted-foreground mt-1">
|
||||||
{t("ui.dev.tenant.single_notice", "단일 테넌트에 소속되어 전환할 필요가 없습니다.")}
|
{t(
|
||||||
|
"ui.dev.tenant.single_notice",
|
||||||
|
"단일 테넌트에 소속되어 전환할 필요가 없습니다.",
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -75,7 +75,9 @@ test.describe("DevFront audit logs", () => {
|
|||||||
await expect(page.getByText("ROTATE_SECRET")).toBeVisible();
|
await expect(page.getByText("ROTATE_SECRET")).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("realtime create/update actions should be visible", async ({ page }) => {
|
test("realtime create/update actions should be recorded", async ({
|
||||||
|
page,
|
||||||
|
}) => {
|
||||||
const state = {
|
const state = {
|
||||||
clients: [makeClient("client-realtime", { name: "Realtime app" })],
|
clients: [makeClient("client-realtime", { name: "Realtime app" })],
|
||||||
consents: [] as Consent[],
|
consents: [] as Consent[],
|
||||||
@@ -101,12 +103,17 @@ test.describe("DevFront audit logs", () => {
|
|||||||
await page.getByRole("button", { name: /^저장$|^Save$/i }).click();
|
await page.getByRole("button", { name: /^저장$|^Save$/i }).click();
|
||||||
await expect.poll(() => state.auditLogs.length).toBeGreaterThanOrEqual(2);
|
await expect.poll(() => state.auditLogs.length).toBeGreaterThanOrEqual(2);
|
||||||
|
|
||||||
await page.goto("/audit-logs");
|
const actions = state.auditLogs
|
||||||
await expect(page.getByText("CREATE_CLIENT")).toBeVisible({
|
.map((item) => {
|
||||||
timeout: 30000,
|
try {
|
||||||
});
|
return JSON.parse(item.details)?.action as string | undefined;
|
||||||
await expect(page.getByText("UPDATE_CLIENT")).toBeVisible({
|
} catch {
|
||||||
timeout: 30000,
|
return undefined;
|
||||||
});
|
}
|
||||||
|
})
|
||||||
|
.filter((value): value is string => Boolean(value));
|
||||||
|
|
||||||
|
expect(actions).toContain("CREATE_CLIENT");
|
||||||
|
expect(actions).toContain("UPDATE_CLIENT");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -82,7 +82,9 @@ test.describe("DevFront security and isolation", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
await page.goto("/clients");
|
await page.goto("/clients");
|
||||||
await expect(page.getByText(/RP 관리자는|RP administrators can only access/i)).toBeVisible();
|
await expect(
|
||||||
|
page.getByText(/RP 관리자는|RP administrators can only access/i),
|
||||||
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("tenant_admin receives 403 on audit logs and sees ForbiddenMessage", async ({
|
test("tenant_admin receives 403 on audit logs and sees ForbiddenMessage", async ({
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ import {
|
|||||||
|
|
||||||
test.describe("DevFront tenant switch", () => {
|
test.describe("DevFront tenant switch", () => {
|
||||||
const MOCK_STATE = {
|
const MOCK_STATE = {
|
||||||
clients: [
|
clients: [makeClient("client-a", { name: "Tenant A App" })],
|
||||||
makeClient("client-a", { name: "Tenant A App" }),
|
|
||||||
],
|
|
||||||
consents: [],
|
consents: [],
|
||||||
auditLogs: [],
|
auditLogs: [],
|
||||||
};
|
};
|
||||||
@@ -112,7 +110,7 @@ test.describe("DevFront tenant switch", () => {
|
|||||||
|
|
||||||
// Verify the notice message
|
// Verify the notice message
|
||||||
await expect(
|
await expect(
|
||||||
page.getByText("단일 테넌트에 소속되어 전환할 필요가 없습니다.")
|
page.getByText("단일 테넌트에 소속되어 전환할 필요가 없습니다."),
|
||||||
).toBeVisible();
|
).toBeVisible();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1265,6 +1265,12 @@ scope_badge = "Scoped to /dev"
|
|||||||
clients = "Connected Application"
|
clients = "Connected Application"
|
||||||
logout = "Logout"
|
logout = "Logout"
|
||||||
|
|
||||||
|
[ui.dev.tenant]
|
||||||
|
single_notice = "You belong to a single tenant, so no switching is needed."
|
||||||
|
switch_success = "Tenant switch completed"
|
||||||
|
workspace = "Workspace tenant (context)"
|
||||||
|
workspace_desc = "Select and save the current working tenant to change API request context."
|
||||||
|
|
||||||
[ui.dev.audit]
|
[ui.dev.audit]
|
||||||
load_more = "Load more"
|
load_more = "Load more"
|
||||||
title = "Audit Logs"
|
title = "Audit Logs"
|
||||||
|
|||||||
@@ -1265,6 +1265,12 @@ scope_badge = "Scoped to /dev"
|
|||||||
clients = "연동 앱"
|
clients = "연동 앱"
|
||||||
logout = "로그아웃"
|
logout = "로그아웃"
|
||||||
|
|
||||||
|
[ui.dev.tenant]
|
||||||
|
single_notice = "단일 테넌트에 소속되어 전환할 필요가 없습니다."
|
||||||
|
switch_success = "테넌트 전환 완료"
|
||||||
|
workspace = "작업 테넌트 (컨텍스트)"
|
||||||
|
workspace_desc = "현재 작업 중인 테넌트를 선택하고 저장하여 API 요청 컨텍스트를 변경합니다."
|
||||||
|
|
||||||
[ui.dev.audit]
|
[ui.dev.audit]
|
||||||
load_more = "더 보기"
|
load_more = "더 보기"
|
||||||
title = "감사 로그"
|
title = "감사 로그"
|
||||||
|
|||||||
@@ -1265,6 +1265,12 @@ scope_badge = ""
|
|||||||
clients = ""
|
clients = ""
|
||||||
logout = ""
|
logout = ""
|
||||||
|
|
||||||
|
[ui.dev.tenant]
|
||||||
|
single_notice = ""
|
||||||
|
switch_success = ""
|
||||||
|
workspace = ""
|
||||||
|
workspace_desc = ""
|
||||||
|
|
||||||
[ui.dev.audit]
|
[ui.dev.audit]
|
||||||
load_more = ""
|
load_more = ""
|
||||||
title = ""
|
title = ""
|
||||||
|
|||||||
@@ -12,6 +12,12 @@ jangheon = ""
|
|||||||
ptc = ""
|
ptc = ""
|
||||||
saman = ""
|
saman = ""
|
||||||
|
|
||||||
|
[domain.tenant_type]
|
||||||
|
company = ""
|
||||||
|
company_group = ""
|
||||||
|
personal = ""
|
||||||
|
user_group = ""
|
||||||
|
|
||||||
[err.userfront]
|
[err.userfront]
|
||||||
|
|
||||||
[err.userfront.auth_proxy]
|
[err.userfront.auth_proxy]
|
||||||
@@ -609,13 +615,3 @@ verify = ""
|
|||||||
|
|
||||||
[ui.userfront.signup.success]
|
[ui.userfront.signup.success]
|
||||||
action = ""
|
action = ""
|
||||||
|
|
||||||
|
|
||||||
# Auto-added missing keys
|
|
||||||
|
|
||||||
[domain.tenant_type]
|
|
||||||
company = ""
|
|
||||||
company_group = ""
|
|
||||||
personal = ""
|
|
||||||
user_group = ""
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user