diff --git a/adminfront/src/features/tenants/utils/tenantCsvImport.test.ts b/adminfront/src/features/tenants/utils/tenantCsvImport.test.ts index c70b44dc..42a282d0 100644 --- a/adminfront/src/features/tenants/utils/tenantCsvImport.test.ts +++ b/adminfront/src/features/tenants/utils/tenantCsvImport.test.ts @@ -150,6 +150,27 @@ describe("tenantCsvImport", () => { expect(csv).not.toContain("local-tenant-id"); }); + + it("preserves source tenant_id when a create resolution does not override it", () => { + const exportedTenantId = "11111111-2222-4333-8444-555555555555"; + const rows = parseTenantCSV( + `tenant_id,name,type,parent_tenant_id,parent_tenant_slug,slug,memo,email_domain +${exportedTenantId},Tenant With UUID,COMPANY,,,tenant-with-uuid,Memo,tenant-with-uuid.example.com +`, + ); + const preview = buildTenantImportPreview(rows, tenants); + const csv = serializeTenantImportCSV(preview, { + 2: { + mode: "create", + slug: "tenant-with-uuid", + }, + }); + + expect(csv).toContain( + `${exportedTenantId},Tenant With UUID,COMPANY,,,tenant-with-uuid,Memo,tenant-with-uuid.example.com`, + ); + }); + it("remaps child parent_tenant_id from source ids to selected staging ids", () => { const rows = parseTenantCSV( [ diff --git a/adminfront/src/features/tenants/utils/tenantCsvImport.ts b/adminfront/src/features/tenants/utils/tenantCsvImport.ts index 95154cc4..8d4746dd 100644 --- a/adminfront/src/features/tenants/utils/tenantCsvImport.ts +++ b/adminfront/src/features/tenants/utils/tenantCsvImport.ts @@ -325,12 +325,15 @@ function buildTargetTenantIds( continue; } + const sourceTenantId = isUUIDLikeTenantId(preview.row.tenantId) + ? preview.row.tenantId + : ""; const targetTenantId = typeof resolution === "string" - ? resolution || preview.row.tenantId + ? resolution || sourceTenantId : resolution.mode === "existing" ? resolution.tenantId - : resolution.tenantId || createTenantImportId(); + : resolution.tenantId || sourceTenantId || createTenantImportId(); const targetSlug = typeof resolution === "object" && resolution.mode === "create" ? resolution.slug || preview.defaultCreateSlug @@ -400,6 +403,13 @@ function createTenantImportId() { .padEnd(12, "0")}`; } + +function isUUIDLikeTenantId(value: string) { + return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test( + value, + ); +} + function findTenantImportConflicts( row: TenantCSVRow, tenants: TenantSummary[], diff --git a/userfront/assets/translations/en.toml b/userfront/assets/translations/en.toml index dd073f41..b134100e 100644 --- a/userfront/assets/translations/en.toml +++ b/userfront/assets/translations/en.toml @@ -704,3 +704,4 @@ toggle_label = "Show active sessions only" [msg.userfront.audit.filter] description = "Toggle to view only active sessions." + diff --git a/userfront/assets/translations/ko.toml b/userfront/assets/translations/ko.toml index aa76bb49..c250d088 100644 --- a/userfront/assets/translations/ko.toml +++ b/userfront/assets/translations/ko.toml @@ -807,8 +807,8 @@ action_label = "확인" page_title = "로그인 승인" title = "승인 완료" action_label_close = "창 닫기" -title_remote = "로그인 승인 완료" title_pending = "로그인 승인 확인 중" +title_remote = "로그인 승인 완료" [ui.userfront.login_success] later = "나중에 하기 (대시보드로 이동)" @@ -925,3 +925,4 @@ toggle_label = "활성 세션만 보기" [msg.userfront.audit.filter] description = "활성화된 세션만 보려면 토글을 켜주세요." + diff --git a/userfront/assets/translations/template.toml b/userfront/assets/translations/template.toml index 8dab74b0..228be315 100644 --- a/userfront/assets/translations/template.toml +++ b/userfront/assets/translations/template.toml @@ -428,6 +428,7 @@ body = "" approved = "" approved_local = "" approved_remote = "" +pending_remote = "" success = "" [msg.userfront.login_success] @@ -778,6 +779,7 @@ action_label = "" action_label_close = "" page_title = "" title = "" +title_pending = "" title_remote = "" [ui.userfront.login_success]