AuditLogDetail kısmı çalışmıyordu düzeltildi.
This commit is contained in:
parent
0f5d44ceb0
commit
d50c62cd1c
6 changed files with 142 additions and 66 deletions
|
|
@ -5,11 +5,11 @@ namespace Sozsoft.Platform.AuditLogs;
|
||||||
|
|
||||||
public class AuditLogActionDto : EntityDto<Guid>
|
public class AuditLogActionDto : EntityDto<Guid>
|
||||||
{
|
{
|
||||||
public virtual Guid AuditLogId { get; protected set; }
|
public virtual Guid AuditLogId { get; set; }
|
||||||
public virtual string ServiceName { get; protected set; }
|
public virtual string ServiceName { get; set; }
|
||||||
public virtual string MethodName { get; protected set; }
|
public virtual string MethodName { get; set; }
|
||||||
public virtual string Parameters { get; protected set; }
|
public virtual string Parameters { get; set; }
|
||||||
public virtual DateTime ExecutionTime { get; protected set; }
|
public virtual DateTime ExecutionTime { get; set; }
|
||||||
public virtual int ExecutionDuration { get; protected set; }
|
public virtual int ExecutionDuration { get; set; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,24 +13,24 @@ public class AuditLogDto : EntityDto<Guid>
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ApplicationName { get; set; }
|
public string ApplicationName { get; set; }
|
||||||
public Guid? UserId { get; protected set; }
|
public Guid? UserId { get; set; }
|
||||||
public string UserName { get; protected set; }
|
public string UserName { get; set; }
|
||||||
public Guid? TenantId { get; protected set; }
|
public Guid? TenantId { get; set; }
|
||||||
public string TenantName { get; protected set; }
|
public string TenantName { get; set; }
|
||||||
public DateTime ExecutionTime { get; protected set; }
|
public DateTime ExecutionTime { get; set; }
|
||||||
public int ExecutionDuration { get; protected set; }
|
public int ExecutionDuration { get; set; }
|
||||||
public string ClientIpAddress { get; protected set; }
|
public string ClientIpAddress { get; set; }
|
||||||
public string ClientName { get; protected set; }
|
public string ClientName { get; set; }
|
||||||
public string ClientId { get; set; }
|
public string ClientId { get; set; }
|
||||||
public string CorrelationId { get; set; }
|
public string CorrelationId { get; set; }
|
||||||
public string BrowserInfo { get; protected set; }
|
public string BrowserInfo { get; set; }
|
||||||
public string HttpMethod { get; protected set; }
|
public string HttpMethod { get; set; }
|
||||||
public string Url { get; protected set; }
|
public string Url { get; set; }
|
||||||
public string Exceptions { get; protected set; }
|
public string Exceptions { get; set; }
|
||||||
public string Comments { get; protected set; }
|
public string Comments { get; set; }
|
||||||
public int? HttpStatusCode { get; set; }
|
public int? HttpStatusCode { get; set; }
|
||||||
public ICollection<EntityChangeDto> EntityChanges { get; protected set; }
|
public ICollection<EntityChangeDto> EntityChanges { get; set; }
|
||||||
public ICollection<AuditLogActionDto> Actions { get; protected set; }
|
public ICollection<AuditLogActionDto> Actions { get; set; }
|
||||||
|
|
||||||
public int? EntityChangeCount { get; set; }
|
public int? EntityChangeCount { get; set; }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,12 @@ public class EntityChangeDto : EntityDto<Guid>
|
||||||
PropertyChanges = new List<EntityPropertyChangeDto>();
|
PropertyChanges = new List<EntityPropertyChangeDto>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Guid AuditLogId { get; protected set; }
|
public virtual Guid AuditLogId { get; set; }
|
||||||
public virtual DateTime ChangeTime { get; protected set; }
|
public virtual DateTime ChangeTime { get; set; }
|
||||||
public virtual EntityChangeType ChangeType { get; protected set; }
|
public virtual EntityChangeType ChangeType { get; set; }
|
||||||
public virtual Guid? EntityTenantId { get; protected set; }
|
public virtual Guid? EntityTenantId { get; set; }
|
||||||
public virtual string EntityId { get; protected set; }
|
public virtual string EntityId { get; set; }
|
||||||
public virtual string EntityTypeFullName { get; protected set; }
|
public virtual string EntityTypeFullName { get; set; }
|
||||||
public virtual ICollection<EntityPropertyChangeDto> PropertyChanges { get; protected set; }
|
public virtual ICollection<EntityPropertyChangeDto> PropertyChanges { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,10 @@ namespace Sozsoft.Platform.AuditLogs;
|
||||||
|
|
||||||
public class EntityPropertyChangeDto : EntityDto<Guid>
|
public class EntityPropertyChangeDto : EntityDto<Guid>
|
||||||
{
|
{
|
||||||
public virtual Guid EntityChangeId { get; protected set; }
|
public virtual Guid EntityChangeId { get; set; }
|
||||||
public virtual string NewValue { get; protected set; }
|
public virtual string NewValue { get; set; }
|
||||||
public virtual string OriginalValue { get; protected set; }
|
public virtual string OriginalValue { get; set; }
|
||||||
public virtual string PropertyName { get; protected set; }
|
public virtual string PropertyName { get; set; }
|
||||||
public virtual string PropertyTypeFullName { get; protected set; }
|
public virtual string PropertyTypeFullName { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
export interface AuditLogActionDto {
|
export interface AuditLogActionDto {
|
||||||
|
id: string
|
||||||
|
auditLogId: string
|
||||||
serviceName: string
|
serviceName: string
|
||||||
methodName: string
|
methodName: string
|
||||||
executionTime: string // Date string
|
executionTime: string // Date string
|
||||||
|
|
@ -7,6 +9,8 @@ export interface AuditLogActionDto {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EntityPropertyChangeDto {
|
export interface EntityPropertyChangeDto {
|
||||||
|
id: string
|
||||||
|
entityChangeId: string
|
||||||
propertyName: string
|
propertyName: string
|
||||||
propertyTypeFullName: string
|
propertyTypeFullName: string
|
||||||
originalValue: string | null
|
originalValue: string | null
|
||||||
|
|
@ -14,8 +18,11 @@ export interface EntityPropertyChangeDto {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EntityChangeDto {
|
export interface EntityChangeDto {
|
||||||
|
id: string
|
||||||
|
auditLogId: string
|
||||||
changeTime: string // Date string
|
changeTime: string // Date string
|
||||||
changeType: number
|
changeType: number
|
||||||
|
entityTenantId?: string
|
||||||
entityId: string
|
entityId: string
|
||||||
entityTypeFullName: string
|
entityTypeFullName: string
|
||||||
propertyChanges: EntityPropertyChangeDto[]
|
propertyChanges: EntityPropertyChangeDto[]
|
||||||
|
|
|
||||||
|
|
@ -69,10 +69,40 @@ function AuditLogs({
|
||||||
}
|
}
|
||||||
|
|
||||||
const formatDuration = (ms: number) => {
|
const formatDuration = (ms: number) => {
|
||||||
|
if (ms === undefined || ms === null) return 'Unknown'
|
||||||
if (ms < 1000) return `${ms}ms`
|
if (ms < 1000) return `${ms}ms`
|
||||||
return `${(ms / 1000).toFixed(2)}s`
|
return `${(ms / 1000).toFixed(2)}s`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const formatDateTime = (value?: string) => {
|
||||||
|
if (!value) return 'Unknown'
|
||||||
|
|
||||||
|
const date = new Date(value)
|
||||||
|
if (Number.isNaN(date.getTime()) || date.getFullYear() <= 1) return 'Unknown'
|
||||||
|
|
||||||
|
return date.toLocaleString('tr-TR', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: '2-digit',
|
||||||
|
year: 'numeric',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
second: '2-digit',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatValue = (value?: string | number | null) => {
|
||||||
|
if (value === undefined || value === null || value === '') return 'Unknown'
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatJson = (value: string) => {
|
||||||
|
try {
|
||||||
|
return JSON.stringify(JSON.parse(value), null, 2)
|
||||||
|
} catch {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const InfoRow = ({ icon: Icon, label, value, valueClassName = '' }: any) => (
|
const InfoRow = ({ icon: Icon, label, value, valueClassName = '' }: any) => (
|
||||||
<div className="flex items-start gap-3 py-2 border-b border-gray-100 last:border-0">
|
<div className="flex items-start gap-3 py-2 border-b border-gray-100 last:border-0">
|
||||||
<Icon className="w-5 h-5 text-gray-400 mt-0.5 flex-shrink-0" />
|
<Icon className="w-5 h-5 text-gray-400 mt-0.5 flex-shrink-0" />
|
||||||
|
|
@ -86,7 +116,7 @@ function AuditLogs({
|
||||||
return (
|
return (
|
||||||
<Dialog width="90%" isOpen={open} onClose={onDialogClose} onRequestClose={onDialogClose}>
|
<Dialog width="90%" isOpen={open} onClose={onDialogClose} onRequestClose={onDialogClose}>
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="flex items-center justify-between mb-6 pb-4 border-b border-gray-200 dark:border-gray-700">
|
<div className="flex items-center justify-between mb-2 pb-2 border-b border-gray-200 dark:border-gray-700">
|
||||||
<div>
|
<div>
|
||||||
<h4 className="text-xl font-bold text-gray-800 dark:text-gray-100">Audit Log Details</h4>
|
<h4 className="text-xl font-bold text-gray-800 dark:text-gray-100">Audit Log Details</h4>
|
||||||
{selectedLog?.id && <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">ID: {selectedLog.id}</p>}
|
{selectedLog?.id && <p className="text-sm text-gray-500 dark:text-gray-400 mt-1">ID: {selectedLog.id}</p>}
|
||||||
|
|
@ -113,7 +143,7 @@ function AuditLogs({
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Tabs defaultValue="log" variant="pill">
|
<Tabs defaultValue="log" variant="pill">
|
||||||
<TabList className="mb-6 bg-gray-50 dark:bg-gray-800 p-1 rounded-lg">
|
<TabList className="mb-2 bg-gray-50 dark:bg-gray-800 p-1 rounded-lg">
|
||||||
<TabNav value="log">
|
<TabNav value="log">
|
||||||
<FaRegFileAlt className="w-4 h-4 mr-2" />
|
<FaRegFileAlt className="w-4 h-4 mr-2" />
|
||||||
<span className="text-gray-700 dark:text-gray-200">Overview</span>
|
<span className="text-gray-700 dark:text-gray-200">Overview</span>
|
||||||
|
|
@ -145,7 +175,7 @@ function AuditLogs({
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
||||||
{/* Request Information */}
|
{/* Request Information */}
|
||||||
<AdaptableCard className="shadow-sm dark:bg-gray-900 dark:border-gray-700">
|
<AdaptableCard className="shadow-sm dark:bg-gray-900 dark:border-gray-700">
|
||||||
<h6 className="font-semibold text-gray-700 dark:text-gray-200 mb-4 flex items-center gap-2">
|
<h6 className="font-semibold text-gray-700 dark:text-gray-200 mb-2 flex items-center gap-2">
|
||||||
<FaGlobe className="w-5 h-5 text-blue-500 dark:text-blue-400" />
|
<FaGlobe className="w-5 h-5 text-blue-500 dark:text-blue-400" />
|
||||||
Request Information
|
Request Information
|
||||||
</h6>
|
</h6>
|
||||||
|
|
@ -153,20 +183,13 @@ function AuditLogs({
|
||||||
<InfoRow
|
<InfoRow
|
||||||
icon={FaUser}
|
icon={FaUser}
|
||||||
label="User"
|
label="User"
|
||||||
value={selectedLog.userName || 'Anonymous'}
|
value={selectedLog.userName || selectedLog.userId || 'Anonymous'}
|
||||||
valueClassName="font-medium text-gray-800 dark:text-gray-100"
|
valueClassName="font-medium text-gray-800 dark:text-gray-100"
|
||||||
/>
|
/>
|
||||||
<InfoRow
|
<InfoRow
|
||||||
icon={FaRegClock}
|
icon={FaRegClock}
|
||||||
label="Execution Time"
|
label="Execution Time"
|
||||||
value={new Date(selectedLog.executionTime).toLocaleString('tr-TR', {
|
value={formatDateTime(selectedLog.executionTime)}
|
||||||
day: '2-digit',
|
|
||||||
month: '2-digit',
|
|
||||||
year: 'numeric',
|
|
||||||
hour: '2-digit',
|
|
||||||
minute: '2-digit',
|
|
||||||
second: '2-digit',
|
|
||||||
})}
|
|
||||||
/>
|
/>
|
||||||
<InfoRow
|
<InfoRow
|
||||||
icon={FaRegClock}
|
icon={FaRegClock}
|
||||||
|
|
@ -181,14 +204,33 @@ function AuditLogs({
|
||||||
<InfoRow
|
<InfoRow
|
||||||
icon={FaGlobe}
|
icon={FaGlobe}
|
||||||
label="Client IP"
|
label="Client IP"
|
||||||
value={selectedLog.clientIpAddress || 'Unknown'}
|
value={formatValue(selectedLog.clientIpAddress)}
|
||||||
|
/>
|
||||||
|
<InfoRow
|
||||||
|
icon={FaRegFileAlt}
|
||||||
|
label="Client Name"
|
||||||
|
value={formatValue(selectedLog.clientName)}
|
||||||
|
/>
|
||||||
|
<InfoRow
|
||||||
|
icon={FaRegFileAlt}
|
||||||
|
label="Client ID"
|
||||||
|
value={formatValue(selectedLog.clientId)}
|
||||||
|
/>
|
||||||
|
<InfoRow
|
||||||
|
icon={FaUser}
|
||||||
|
label="Tenant"
|
||||||
|
value={
|
||||||
|
selectedLog.tenantName ||
|
||||||
|
selectedLog.tenantId ||
|
||||||
|
'Host'
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</AdaptableCard>
|
</AdaptableCard>
|
||||||
|
|
||||||
{/* HTTP Details */}
|
{/* HTTP Details */}
|
||||||
<AdaptableCard className="shadow-sm dark:bg-gray-900 dark:border-gray-700">
|
<AdaptableCard className="shadow-sm dark:bg-gray-900 dark:border-gray-700">
|
||||||
<h6 className="font-semibold text-gray-700 dark:text-gray-200 mb-4 flex items-center gap-2">
|
<h6 className="font-semibold text-gray-700 dark:text-gray-200 mb-2 flex items-center gap-2">
|
||||||
<FaCode className="w-5 h-5 text-green-500 dark:text-green-400" />
|
<FaCode className="w-5 h-5 text-green-500 dark:text-green-400" />
|
||||||
HTTP Details
|
HTTP Details
|
||||||
</h6>
|
</h6>
|
||||||
|
|
@ -197,6 +239,7 @@ function AuditLogs({
|
||||||
icon={FaCode}
|
icon={FaCode}
|
||||||
label="Method"
|
label="Method"
|
||||||
value={
|
value={
|
||||||
|
selectedLog.httpMethod ? (
|
||||||
<Badge
|
<Badge
|
||||||
className={
|
className={
|
||||||
selectedLog.httpMethod === 'POST'
|
selectedLog.httpMethod === 'POST'
|
||||||
|
|
@ -211,6 +254,9 @@ function AuditLogs({
|
||||||
}
|
}
|
||||||
content={selectedLog.httpMethod}
|
content={selectedLog.httpMethod}
|
||||||
></Badge>
|
></Badge>
|
||||||
|
) : (
|
||||||
|
'Unknown'
|
||||||
|
)
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<InfoRow
|
<InfoRow
|
||||||
|
|
@ -221,7 +267,7 @@ function AuditLogs({
|
||||||
<InfoRow
|
<InfoRow
|
||||||
icon={FaGlobe}
|
icon={FaGlobe}
|
||||||
label="URL"
|
label="URL"
|
||||||
value={selectedLog.url}
|
value={formatValue(selectedLog.url)}
|
||||||
valueClassName="text-blue-600 dark:text-blue-400 font-mono text-xs"
|
valueClassName="text-blue-600 dark:text-blue-400 font-mono text-xs"
|
||||||
/>
|
/>
|
||||||
<InfoRow
|
<InfoRow
|
||||||
|
|
@ -233,6 +279,12 @@ function AuditLogs({
|
||||||
</span>
|
</span>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<InfoRow
|
||||||
|
icon={FaRegFileAlt}
|
||||||
|
label="Correlation ID"
|
||||||
|
value={formatValue(selectedLog.correlationId)}
|
||||||
|
valueClassName="font-mono text-xs"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</AdaptableCard>
|
</AdaptableCard>
|
||||||
|
|
||||||
|
|
@ -291,13 +343,25 @@ function AuditLogs({
|
||||||
<div>
|
<div>
|
||||||
<p className="text-xs text-gray-500 dark:text-gray-400 mb-1">Service Name</p>
|
<p className="text-xs text-gray-500 dark:text-gray-400 mb-1">Service Name</p>
|
||||||
<p className="text-sm font-mono text-gray-700 dark:text-gray-200 break-all">
|
<p className="text-sm font-mono text-gray-700 dark:text-gray-200 break-all">
|
||||||
{action.serviceName}
|
{formatValue(action.serviceName)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs text-gray-500 dark:text-gray-400 mb-1">Method Name</p>
|
||||||
|
<p className="text-sm font-mono text-gray-700 dark:text-gray-200 break-all">
|
||||||
|
{formatValue(action.methodName)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-xs text-gray-500 dark:text-gray-400 mb-1">Execution Time</p>
|
<p className="text-xs text-gray-500 dark:text-gray-400 mb-1">Execution Time</p>
|
||||||
<p className="text-sm text-gray-700 dark:text-gray-200">
|
<p className="text-sm text-gray-700 dark:text-gray-200">
|
||||||
{new Date(action.executionTime).toLocaleString('tr-TR')}
|
{formatDateTime(action.executionTime)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs text-gray-500 dark:text-gray-400 mb-1">Action ID</p>
|
||||||
|
<p className="text-sm font-mono text-gray-700 dark:text-gray-200 break-all">
|
||||||
|
{formatValue(action.id)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -306,7 +370,7 @@ function AuditLogs({
|
||||||
<div>
|
<div>
|
||||||
<p className="text-xs text-gray-500 dark:text-gray-400 mb-2">Parameters</p>
|
<p className="text-xs text-gray-500 dark:text-gray-400 mb-2">Parameters</p>
|
||||||
<pre className="bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 p-3 rounded-lg text-xs overflow-x-auto text-gray-700 dark:text-gray-200">
|
<pre className="bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 p-3 rounded-lg text-xs overflow-x-auto text-gray-700 dark:text-gray-200">
|
||||||
{JSON.stringify(JSON.parse(action.parameters), null, 2)}
|
{formatJson(action.parameters)}
|
||||||
</pre>
|
</pre>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -338,12 +402,17 @@ function AuditLogs({
|
||||||
{change.entityTypeFullName}
|
{change.entityTypeFullName}
|
||||||
</h6>
|
</h6>
|
||||||
<p className="text-xs text-gray-500 dark:text-gray-400">ID: {change.entityId}</p>
|
<p className="text-xs text-gray-500 dark:text-gray-400">ID: {change.entityId}</p>
|
||||||
|
{change.entityTenantId && (
|
||||||
|
<p className="text-xs text-gray-500 dark:text-gray-400">
|
||||||
|
Tenant ID: {change.entityTenantId}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
{getChangeTypeBadge(change.changeType)}
|
{getChangeTypeBadge(change.changeType)}
|
||||||
<span className="text-xs text-gray-500 dark:text-gray-400">
|
<span className="text-xs text-gray-500 dark:text-gray-400">
|
||||||
{new Date(change.changeTime).toLocaleTimeString('tr-TR')}
|
{formatDateTime(change.changeTime)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue