diff --git a/artifacts/api-server/src/routes/apps.ts b/artifacts/api-server/src/routes/apps.ts index b5ce451c..02ddc1da 100644 --- a/artifacts/api-server/src/routes/apps.ts +++ b/artifacts/api-server/src/routes/apps.ts @@ -914,9 +914,9 @@ router.delete("/apps/:id", requireAdmin, async (req, res): Promise => { targetType: "app", targetId: appId, metadata: { - slug: existing.slug, - nameAr: existing.nameAr, - nameEn: existing.nameEn, + appSlug: existing.slug, + appNameAr: existing.nameAr, + appNameEn: existing.nameEn, force, groupCount, restrictionCount, diff --git a/artifacts/api-server/src/routes/roles.ts b/artifacts/api-server/src/routes/roles.ts index b169939b..4992cdc1 100644 --- a/artifacts/api-server/src/routes/roles.ts +++ b/artifacts/api-server/src/routes/roles.ts @@ -414,7 +414,7 @@ router.delete("/roles/:id", requireAdmin, async (req, res): Promise => { targetType: "role", targetId: id, metadata: { - name: existing.name, + roleName: existing.name, descriptionAr: existing.descriptionAr, descriptionEn: existing.descriptionEn, }, diff --git a/artifacts/api-server/src/routes/users.ts b/artifacts/api-server/src/routes/users.ts index 6d50a1b6..3d399da9 100644 --- a/artifacts/api-server/src/routes/users.ts +++ b/artifacts/api-server/src/routes/users.ts @@ -720,6 +720,8 @@ router.delete("/users/:id", requireAdmin, async (req, res): Promise => { targetId: userId, metadata: { username: existing.username, + displayNameEn: existing.displayNameEn, + displayNameAr: existing.displayNameAr, email: existing.email, force, ...(hasDeps diff --git a/artifacts/api-server/tests/audit-log-coverage.test.mjs b/artifacts/api-server/tests/audit-log-coverage.test.mjs index c62b9620..9fd42a7b 100644 --- a/artifacts/api-server/tests/audit-log-coverage.test.mjs +++ b/artifacts/api-server/tests/audit-log-coverage.test.mjs @@ -276,6 +276,8 @@ test("DELETE /api/users/:id (no-force, no deps) writes one user.delete row with assert.equal(row.actor_user_id, adminId); assert.equal(row.metadata.username, username); assert.equal(row.metadata.email, email); + assert.equal(row.metadata.displayNameEn, "Audit Coverage"); + assert.equal(row.metadata.displayNameAr, null); assert.equal(row.metadata.force, false); // No-deps path must NOT include the dependency counts. assert.equal(row.metadata.noteCount, undefined); @@ -447,7 +449,7 @@ test("DELETE /api/roles/:id (no users/groups) writes one role.delete row", async }); assert.equal(rows.length, 1); assert.equal(rows[0].actor_user_id, adminId); - assert.equal(rows[0].metadata.name, role.name); + assert.equal(rows[0].metadata.roleName, role.name); }); // ---------- groups ---------- @@ -844,7 +846,9 @@ test("DELETE /api/apps/:id (no deps) writes app.delete with force=false and zero targetType: "app", }); assert.equal(rows.length, 1); - assert.equal(rows[0].metadata.slug, app.slug); + assert.equal(rows[0].metadata.appSlug, app.slug); + assert.equal(rows[0].metadata.appNameEn, "Audit App"); + assert.equal(rows[0].metadata.appNameAr, "تطبيق تدقيق"); assert.equal(rows[0].metadata.force, false); assert.equal(rows[0].metadata.groupCount, 0); assert.equal(rows[0].metadata.restrictionCount, 0); diff --git a/artifacts/tx-os/src/locales/ar.json b/artifacts/tx-os/src/locales/ar.json index 2e746f10..4bbca0eb 100644 --- a/artifacts/tx-os/src/locales/ar.json +++ b/artifacts/tx-os/src/locales/ar.json @@ -814,7 +814,9 @@ }, "user": { "delete": "تم حذف المستخدم @{{username}}", - "forceDelete": "تم حذف المستخدم @{{username}} قسراً" + "deleteWithName": "تم حذف المستخدم @{{username}} ({{displayName}})", + "forceDelete": "تم حذف المستخدم @{{username}} قسراً", + "forceDeleteWithName": "تم حذف المستخدم @{{username}} ({{displayName}}) قسراً" } } }, diff --git a/artifacts/tx-os/src/locales/en.json b/artifacts/tx-os/src/locales/en.json index bd72a67f..a9249aee 100644 --- a/artifacts/tx-os/src/locales/en.json +++ b/artifacts/tx-os/src/locales/en.json @@ -715,7 +715,9 @@ }, "user": { "delete": "Deleted user @{{username}}", - "forceDelete": "Force-deleted user @{{username}}" + "deleteWithName": "Deleted user @{{username}} ({{displayName}})", + "forceDelete": "Force-deleted user @{{username}}", + "forceDeleteWithName": "Force-deleted user @{{username}} ({{displayName}})" } } }, diff --git a/artifacts/tx-os/src/pages/admin.tsx b/artifacts/tx-os/src/pages/admin.tsx index 4c44bc47..edb094f3 100644 --- a/artifacts/tx-os/src/pages/admin.tsx +++ b/artifacts/tx-os/src/pages/admin.tsx @@ -5693,9 +5693,9 @@ function unitLabel(t: AuditTFunction, kind: string, count: number): string { } function appName(meta: Record, lang: string, fallbackId: AuditLogEntry["targetId"]): string { - const en = asString(meta.nameEn); - const ar = asString(meta.nameAr); - const slug = asString(meta.slug); + const en = asString(meta.nameEn) ?? asString(meta.appNameEn); + const ar = asString(meta.nameAr) ?? asString(meta.appNameAr); + const slug = asString(meta.slug) ?? asString(meta.appSlug); const preferred = lang === "ar" ? ar ?? en : en ?? ar; return preferred ?? slug ?? `#${fallbackId ?? "?"}`; } @@ -5908,7 +5908,10 @@ function formatAuditSummary( } case "role.delete": return t("admin.audit.summary.role.delete", { - name: plainName(meta, targetId), + name: + asString(meta.roleName) ?? + asString(meta.name) ?? + `#${targetId ?? "?"}`, }); case "role.permissions.replace": { const added = Array.isArray(meta.added) ? meta.added.length : 0; @@ -5965,6 +5968,22 @@ function formatAuditSummary( } case "user.delete": { const username = asString(meta.username) ?? `#${targetId ?? "?"}`; + const displayEn = asString(meta.displayNameEn); + const displayAr = asString(meta.displayNameAr); + const displayName = lang === "ar" + ? displayAr ?? displayEn + : displayEn ?? displayAr; + if (displayName) { + return meta.force + ? t("admin.audit.summary.user.forceDeleteWithName", { + username, + displayName, + }) + : t("admin.audit.summary.user.deleteWithName", { + username, + displayName, + }); + } return meta.force ? t("admin.audit.summary.user.forceDelete", { username }) : t("admin.audit.summary.user.delete", { username }); @@ -6025,11 +6044,17 @@ function forceDeletedEntityName( ): string | null { if (!isForceDeleteEntry(entry)) return null; const meta = asRecord(entry.metadata); - const en = asString(meta.nameEn) ?? asString(meta.displayNameEn); - const ar = asString(meta.nameAr) ?? asString(meta.displayNameAr); + const en = + asString(meta.nameEn) ?? + asString(meta.appNameEn) ?? + asString(meta.displayNameEn); + const ar = + asString(meta.nameAr) ?? + asString(meta.appNameAr) ?? + asString(meta.displayNameAr); const localized = lang === "ar" ? ar ?? en : en ?? ar; if (localized) return localized; - const plain = asString(meta.name); + const plain = asString(meta.name) ?? asString(meta.appSlug); if (plain) return plain; const username = asString(meta.username); if (username) return `@${username}`;