fix(audit): безопасный рендер reason/entity_id из legacy API.
CI / test (push) Successful in 2m28s
CI / push-image (push) Has been cancelled
CI / ci-done (push) Has been cancelled

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-16 14:08:25 +03:00
parent 840f06e68e
commit d200260497
+24 -2
View File
@@ -51,6 +51,25 @@ const entityTypeBadgeVariant = (type: string) => {
const isBadValue = (val: unknown) => const isBadValue = (val: unknown) =>
val === '-' || val === 'undefined' || val === '' || val === null || val === undefined; val === '-' || val === 'undefined' || val === '' || val === null || val === undefined;
const asAuditText = (val: unknown): string => {
if (isBadValue(val)) return '-';
if (typeof val === 'string') return val;
if (typeof val === 'object' && val !== null && 'reason' in val) {
const nested = (val as { reason?: unknown }).reason;
return typeof nested === 'string' ? nested : '-';
}
return String(val);
};
const asEntityId = (val: unknown): string => {
if (typeof val === 'string') return val;
if (typeof val === 'object' && val !== null && 'id' in val) {
const id = (val as { id?: unknown }).id;
return typeof id === 'string' ? id : String(id ?? '');
}
return String(val ?? '');
};
const toDateInput = (iso: string | undefined): string => { const toDateInput = (iso: string | undefined): string => {
if (!iso) return ''; if (!iso) return '';
return iso.slice(0, 10); return iso.slice(0, 10);
@@ -167,7 +186,10 @@ const AuditPage: React.FC = () => {
header: t('audit.name'), header: t('audit.name'),
enableSorting: false, enableSorting: false,
cell: ({ row }) => ( cell: ({ row }) => (
<EntityNameCell entityType={row.original.entity_type} entityId={row.original.entity_id} /> <EntityNameCell
entityType={row.original.entity_type}
entityId={asEntityId(row.original.entity_id)}
/>
), ),
}, },
{ accessorKey: 'timestamp', header: t('common.date'), enableSorting: true }, { accessorKey: 'timestamp', header: t('common.date'), enableSorting: true },
@@ -177,7 +199,7 @@ const AuditPage: React.FC = () => {
header: t('common.reason'), header: t('common.reason'),
enableSorting: false, enableSorting: false,
cell: ({ getValue }) => { cell: ({ getValue }) => {
const reason = getValue<string>(); const reason = asAuditText(getValue());
return <span className="line-clamp-2">{reason}</span>; return <span className="line-clamp-2">{reason}</span>;
}, },
}, },