Show readable names in audit log for top-level deletions
Task: #177 — Make user/app/role deletion audit rows render readable names ("Deleted user @alice (Alice Smith)", "Deleted app 'Notes'", "Deleted role 'Editor'") instead of relying on whatever the route happened to capture. Backend metadata changes: - artifacts/api-server/src/routes/users.ts (user.delete): now also persists displayNameEn and displayNameAr alongside the existing username/email. - artifacts/api-server/src/routes/apps.ts (app.delete): renamed the metadata keys slug/nameAr/nameEn → appSlug/appNameAr/appNameEn so app sub-resource events and top-level deletes share one prefix. - artifacts/api-server/src/routes/roles.ts (role.delete): renamed the metadata key name → roleName, matching group.role.add/remove. Frontend formatter (artifacts/tx-os/src/pages/admin.tsx): - appName helper now reads both legacy (slug/nameEn/nameAr) and new (appSlug/appNameEn/appNameAr) keys so old rows still render. - role.delete case prefers roleName, falls back to legacy name. - user.delete case picks the user's localized display name and uses new locale strings user.deleteWithName / user.forceDeleteWithName when present; falls back to the existing username-only strings. - forceDeletedEntityName also accepts appNameEn/appNameAr/appSlug so force-deleted apps still get their inline name chip. Locales: - artifacts/tx-os/src/locales/{en,ar}.json: added admin.audit.summary.user.deleteWithName and forceDeleteWithName. Test updates: - artifacts/api-server/tests/audit-log-coverage.test.mjs: updated the role.delete and app.delete (no-deps) assertions to read the new metadata key names. The user.delete assertions kept working as-is since username/email/force are unchanged. No DB migration was required — audit_logs.metadata is already JSON. Legacy rows continue to render via the formatter fallbacks called out in the task description. Replit-Task-Id: a25d35dd-5005-4e57-96a5-580016f35e46
This commit is contained in:
@@ -914,9 +914,9 @@ router.delete("/apps/:id", requireAdmin, async (req, res): Promise<void> => {
|
||||
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,
|
||||
|
||||
@@ -414,7 +414,7 @@ router.delete("/roles/:id", requireAdmin, async (req, res): Promise<void> => {
|
||||
targetType: "role",
|
||||
targetId: id,
|
||||
metadata: {
|
||||
name: existing.name,
|
||||
roleName: existing.name,
|
||||
descriptionAr: existing.descriptionAr,
|
||||
descriptionEn: existing.descriptionEn,
|
||||
},
|
||||
|
||||
@@ -720,6 +720,8 @@ router.delete("/users/:id", requireAdmin, async (req, res): Promise<void> => {
|
||||
targetId: userId,
|
||||
metadata: {
|
||||
username: existing.username,
|
||||
displayNameEn: existing.displayNameEn,
|
||||
displayNameAr: existing.displayNameAr,
|
||||
email: existing.email,
|
||||
force,
|
||||
...(hasDeps
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user