AuditLogs sayfasında güncellemeler
This commit is contained in:
parent
6723ce4e66
commit
d9712403f8
15 changed files with 463 additions and 228 deletions
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
|
||||
namespace Kurs.Platform.AuditLogs;
|
||||
|
||||
public class AuditLogActionDto : EntityDto<Guid>
|
||||
{
|
||||
public virtual Guid AuditLogId { get; protected set; }
|
||||
public virtual string ServiceName { get; protected set; }
|
||||
public virtual string MethodName { get; protected set; }
|
||||
public virtual string Parameters { get; protected set; }
|
||||
public virtual DateTime ExecutionTime { get; protected set; }
|
||||
public virtual int ExecutionDuration { get; protected set; }
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,78 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Volo.Abp;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Application.Services;
|
||||
using Volo.Abp.AuditLogging;
|
||||
using static Kurs.Platform.Data.Seeds.SeedConsts;
|
||||
|
||||
namespace Kurs.Platform.AuditLogs;
|
||||
|
||||
public interface IAuditLogAppService
|
||||
: ICrudAppService<AuditLogDto, Guid>
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
[Authorize(AppCodes.AuditLogs)]
|
||||
public class AuditLogAppService
|
||||
: CrudAppService<AuditLog, AuditLogDto, Guid>
|
||||
, IAuditLogAppService
|
||||
{
|
||||
public AuditLogAppService(IAuditLogRepository auditLogRepository) : base(auditLogRepository)
|
||||
{
|
||||
}
|
||||
|
||||
public override async Task<AuditLogDto> GetAsync(Guid id)
|
||||
{
|
||||
var entity = await Repository.GetAsync(id, includeDetails: true);
|
||||
|
||||
return await MapToGetOutputDtoAsync(entity);
|
||||
}
|
||||
|
||||
public override async Task<PagedResultDto<AuditLogDto>> GetListAsync(PagedAndSortedResultRequestDto input)
|
||||
{
|
||||
var query = await CreateFilteredQueryAsync(input);
|
||||
|
||||
var totalCount = await AsyncExecuter.CountAsync(query);
|
||||
|
||||
query = ApplySorting(query, input);
|
||||
query = ApplyPaging(query, input);
|
||||
|
||||
var auditLogList = await AsyncExecuter.ToListAsync(query);
|
||||
|
||||
var entityDtos = new List<AuditLogDto>();
|
||||
foreach (var item in auditLogList)
|
||||
{
|
||||
var dto = await MapToGetListOutputDtoAsync(item);
|
||||
dto.EntityChangeCount = item.EntityChanges?.Count ?? 0; // null kontrolü artık burada güvenli
|
||||
entityDtos.Add(dto);
|
||||
}
|
||||
|
||||
return new PagedResultDto<AuditLogDto>(
|
||||
totalCount,
|
||||
entityDtos
|
||||
);
|
||||
}
|
||||
|
||||
// Audit Log kayitlarini gormek istiyoruz fakat degistirmek istemiyoruz
|
||||
[RemoteService(IsEnabled = false)]
|
||||
public override Task<AuditLogDto> CreateAsync(AuditLogDto input)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
[RemoteService(IsEnabled = false)]
|
||||
public override Task<AuditLogDto> UpdateAsync(Guid id, AuditLogDto input)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
[RemoteService(IsEnabled = false)]
|
||||
public override Task DeleteAsync(Guid id)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
35
api/src/Kurs.Platform.Application/AuditLogs/AuditLogDto.cs
Normal file
35
api/src/Kurs.Platform.Application/AuditLogs/AuditLogDto.cs
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
|
||||
namespace Kurs.Platform.AuditLogs;
|
||||
|
||||
public class AuditLogDto : EntityDto<Guid>
|
||||
{
|
||||
public AuditLogDto()
|
||||
{
|
||||
Actions = new List<AuditLogActionDto>();
|
||||
EntityChanges = new List<EntityChangeDto>();
|
||||
}
|
||||
|
||||
public string ApplicationName { get; set; }
|
||||
public Guid? UserId { get; protected set; }
|
||||
public string UserName { get; protected set; }
|
||||
public DateTime ExecutionTime { get; protected set; }
|
||||
public int ExecutionDuration { get; protected set; }
|
||||
public string ClientIpAddress { get; protected set; }
|
||||
public string ClientName { get; protected set; }
|
||||
public string ClientId { get; set; }
|
||||
public string CorrelationId { get; set; }
|
||||
public string BrowserInfo { get; protected set; }
|
||||
public string HttpMethod { get; protected set; }
|
||||
public string Url { get; protected set; }
|
||||
public string Exceptions { get; protected set; }
|
||||
public string Comments { get; protected set; }
|
||||
public int? HttpStatusCode { get; set; }
|
||||
public ICollection<EntityChangeDto> EntityChanges { get; protected set; }
|
||||
public ICollection<AuditLogActionDto> Actions { get; protected set; }
|
||||
|
||||
public int? EntityChangeCount { get; set; }
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
using Volo.Abp.Auditing;
|
||||
|
||||
namespace Kurs.Platform.AuditLogs;
|
||||
|
||||
public class EntityChangeDto : EntityDto<Guid>
|
||||
{
|
||||
public EntityChangeDto()
|
||||
{
|
||||
PropertyChanges = new List<EntityPropertyChangeDto>();
|
||||
}
|
||||
|
||||
public virtual Guid AuditLogId { get; protected set; }
|
||||
public virtual DateTime ChangeTime { get; protected set; }
|
||||
public virtual EntityChangeType ChangeType { get; protected set; }
|
||||
public virtual Guid? EntityTenantId { get; protected set; }
|
||||
public virtual string EntityId { get; protected set; }
|
||||
public virtual string EntityTypeFullName { get; protected set; }
|
||||
public virtual ICollection<EntityPropertyChangeDto> PropertyChanges { get; protected set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using Volo.Abp.Application.Dtos;
|
||||
|
||||
namespace Kurs.Platform.AuditLogs;
|
||||
|
||||
public class EntityPropertyChangeDto : EntityDto<Guid>
|
||||
{
|
||||
public virtual Guid EntityChangeId { get; protected set; }
|
||||
public virtual string NewValue { get; protected set; }
|
||||
public virtual string OriginalValue { get; protected set; }
|
||||
public virtual string PropertyName { get; protected set; }
|
||||
public virtual string PropertyTypeFullName { get; protected set; }
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
using AutoMapper;
|
||||
using Volo.Abp.AuditLogging;
|
||||
|
||||
namespace Kurs.Platform.AuditLogs;
|
||||
|
||||
public class LogsAutoMapperProfile : Profile
|
||||
{
|
||||
public LogsAutoMapperProfile()
|
||||
{
|
||||
CreateMap<AuditLog, AuditLogDto>();
|
||||
CreateMap<AuditLogAction, AuditLogActionDto>();
|
||||
CreateMap<EntityChange, EntityChangeDto>();
|
||||
CreateMap<EntityPropertyChange, EntityPropertyChangeDto>();
|
||||
}
|
||||
}
|
||||
|
|
@ -7341,6 +7341,17 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
|
|||
LoadPanelEnabled = "auto",
|
||||
LoadPanelText = "Loading..."
|
||||
}),
|
||||
CommandColumnJson = JsonSerializer.Serialize(new CommandColumnDto[] {
|
||||
new CommandColumnDto() {
|
||||
Hint = "Details",
|
||||
Text = "Details",
|
||||
AuthName = AppCodes.AuditLogs,
|
||||
DialogName = "AuditLogDetail",
|
||||
DialogParameters = JsonSerializer.Serialize(new {
|
||||
id = "@Id",
|
||||
})
|
||||
},
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
|
|
@ -7584,183 +7595,6 @@ public class ListFormsSeeder : IDataSeedContributor, ITransientDependency
|
|||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Entity Changes
|
||||
var listFormEntityChange = await _listFormRepository.InsertAsync(
|
||||
new ListForm()
|
||||
{
|
||||
CultureName = LanguageCodes.En,
|
||||
ListFormCode = ListFormCodes.EntityChange,
|
||||
Name = AppCodes.EntityChanges,
|
||||
Title = AppCodes.EntityChanges,
|
||||
DataSourceCode = SeedConsts.DataSources.DefaultCode,
|
||||
IsTenant = true,
|
||||
IsOrganizationUnit = false,
|
||||
Description = AppCodes.EntityChanges,
|
||||
SelectCommandType = SelectCommandTypeEnum.Table,
|
||||
SelectCommand = "AbpEntityChanges",
|
||||
KeyFieldName = "Id",
|
||||
KeyFieldDbSourceType = DbType.Guid,
|
||||
SortMode = GridOptions.SortModeSingle,
|
||||
FilterRowJson = JsonSerializer.Serialize(new GridFilterRowDto
|
||||
{
|
||||
Visible = true
|
||||
}),
|
||||
HeaderFilterJson = JsonSerializer.Serialize(new
|
||||
{
|
||||
Visible = true
|
||||
}),
|
||||
SearchPanelJson = JsonSerializer.Serialize(new
|
||||
{
|
||||
Visible = true
|
||||
}),
|
||||
GroupPanelJson = JsonSerializer.Serialize(new
|
||||
{
|
||||
Visible = true
|
||||
}),
|
||||
SelectionJson = JsonSerializer.Serialize(new SelectionDto
|
||||
{
|
||||
Mode = GridOptions.SelectionModeSingle,
|
||||
AllowSelectAll = false
|
||||
}),
|
||||
ColumnOptionJson = JsonSerializer.Serialize(new
|
||||
{
|
||||
ColumnFixingEnabled = true,
|
||||
ColumnChooserEnabled = true
|
||||
}),
|
||||
PermissionJson = JsonSerializer.Serialize(new PermissionCrudDto
|
||||
{
|
||||
C = AppCodes.EntityChanges + ".Create",
|
||||
R = AppCodes.EntityChanges,
|
||||
U = AppCodes.EntityChanges + ".Update",
|
||||
D = AppCodes.EntityChanges + ".Delete",
|
||||
E = AppCodes.EntityChanges + ".Export",
|
||||
}),
|
||||
PagerOptionJson = JsonSerializer.Serialize(new GridPagerOptionDto
|
||||
{
|
||||
Visible = true,
|
||||
AllowedPageSizes = "10,20,50,100",
|
||||
ShowPageSizeSelector = true,
|
||||
ShowNavigationButtons = true,
|
||||
ShowInfo = false,
|
||||
InfoText = "Page {0} of {1} ({2} items)",
|
||||
DisplayMode = GridColumnOptions.PagerDisplayModeAdaptive,
|
||||
ScrollingMode = GridColumnOptions.ScrollingModeStandard,
|
||||
LoadPanelEnabled = "auto",
|
||||
LoadPanelText = "Loading..."
|
||||
}),
|
||||
}
|
||||
);
|
||||
|
||||
#region Entity Changes Fields
|
||||
await _listFormFieldRepository.InsertManyAsync(
|
||||
[
|
||||
new() {
|
||||
ListFormCode = listFormEntityChange.ListFormCode,
|
||||
RoleId = null,
|
||||
UserId = null,
|
||||
CultureName = LanguageCodes.En,
|
||||
SourceDbType = DbType.Guid,
|
||||
FieldName = "Id",
|
||||
Width = 100,
|
||||
ListOrderNo = 1,
|
||||
Visible = false,
|
||||
IsActive = true,
|
||||
IsDeleted = false,
|
||||
PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto
|
||||
{
|
||||
C = AppCodes.AuditLogs + ".Create",
|
||||
R = AppCodes.AuditLogs,
|
||||
U = AppCodes.AuditLogs + ".Update",
|
||||
E = true,
|
||||
Deny = false
|
||||
}),
|
||||
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
|
||||
{
|
||||
IsPivot = true
|
||||
})
|
||||
},
|
||||
new() {
|
||||
ListFormCode = listFormEntityChange.ListFormCode,
|
||||
RoleId = null,
|
||||
UserId = null,
|
||||
CultureName = LanguageCodes.En,
|
||||
SourceDbType = DbType.DateTime,
|
||||
FieldName = "ChangeTime",
|
||||
Width = 150,
|
||||
ListOrderNo = 2,
|
||||
Visible = true,
|
||||
IsActive = true,
|
||||
IsDeleted = false,
|
||||
AllowSearch = true,
|
||||
PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto
|
||||
{
|
||||
C = AppCodes.AuditLogs + ".Create",
|
||||
R = AppCodes.AuditLogs,
|
||||
U = AppCodes.AuditLogs + ".Update",
|
||||
E = true,
|
||||
Deny = false
|
||||
}),
|
||||
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
|
||||
{
|
||||
IsPivot = true
|
||||
})
|
||||
},
|
||||
new() {
|
||||
ListFormCode = listFormEntityChange.ListFormCode,
|
||||
RoleId = null,
|
||||
UserId = null,
|
||||
CultureName = LanguageCodes.En,
|
||||
SourceDbType = DbType.String,
|
||||
FieldName = "ChangeType",
|
||||
Width = 125,
|
||||
ListOrderNo = 3,
|
||||
Visible = true,
|
||||
IsActive = true,
|
||||
IsDeleted = false,
|
||||
AllowSearch = true,
|
||||
PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto
|
||||
{
|
||||
C = AppCodes.AuditLogs + ".Create",
|
||||
R = AppCodes.AuditLogs,
|
||||
U = AppCodes.AuditLogs + ".Update",
|
||||
E = true,
|
||||
Deny = false
|
||||
}),
|
||||
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
|
||||
{
|
||||
IsPivot = true
|
||||
})
|
||||
},
|
||||
new() {
|
||||
ListFormCode = listFormEntityChange.ListFormCode,
|
||||
RoleId = null,
|
||||
UserId = null,
|
||||
CultureName = LanguageCodes.En,
|
||||
SourceDbType = DbType.String,
|
||||
FieldName = "EntityTypeFullName",
|
||||
Width = 300,
|
||||
ListOrderNo = 4,
|
||||
Visible = true,
|
||||
IsActive = true,
|
||||
IsDeleted = false,
|
||||
AllowSearch = true,
|
||||
PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto
|
||||
{
|
||||
C = AppCodes.AuditLogs + ".Create",
|
||||
R = AppCodes.AuditLogs,
|
||||
U = AppCodes.AuditLogs + ".Update",
|
||||
E = true,
|
||||
Deny = false
|
||||
}),
|
||||
PivotSettingsJson = JsonSerializer.Serialize(new ListFormFieldPivotSettingsDto
|
||||
{
|
||||
IsPivot = true
|
||||
})
|
||||
},
|
||||
]);
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region Branches
|
||||
var listFormBranches = await _listFormRepository.InsertAsync(
|
||||
new ListForm()
|
||||
|
|
|
|||
|
|
@ -501,22 +501,6 @@ public class MenuSeeder : IDataSeedContributor, ITransientDependency
|
|||
RequiredPermissionName = AppCodes.AuditLogs
|
||||
});
|
||||
|
||||
//Entity Changes
|
||||
await _repository.InsertAsync(new Menu
|
||||
{
|
||||
Code = AppCodes.EntityChanges,
|
||||
DisplayName = AppCodes.EntityChanges,
|
||||
Order = 9,
|
||||
IsDisabled = false,
|
||||
ParentCode = menuAdministration.Code,
|
||||
Icon = "FcSurvey",
|
||||
Target = null,
|
||||
ElementId = null,
|
||||
CssClass = null,
|
||||
Url = $"/list/{PlatformConsts.ListFormCodes.EntityChange}",
|
||||
RequiredPermissionName = AppCodes.EntityChanges
|
||||
});
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -837,39 +837,6 @@ public class PermissionSeeder : IDataSeedContributor, ITransientDependency
|
|||
}
|
||||
#endregion
|
||||
|
||||
#region EntityChanges
|
||||
await repositoryGroup.InsertAsync(new PermissionGroupDefinitionRecord
|
||||
{
|
||||
Name = AppCodes.EntityChanges,
|
||||
DisplayName = AppCodes.EntityChanges
|
||||
});
|
||||
|
||||
var permEntityChanges = await repository.InsertAsync(
|
||||
GetNewPermission(
|
||||
AppCodes.EntityChanges,
|
||||
AppCodes.EntityChanges,
|
||||
AppCodes.EntityChanges,
|
||||
null,
|
||||
true,
|
||||
MultiTenancySides.Both
|
||||
));
|
||||
|
||||
foreach (var item in CUDE)
|
||||
{
|
||||
permissionName = AppCodes.EntityChanges + "." + item;
|
||||
|
||||
await repository.InsertAsync(
|
||||
GetNewPermission(
|
||||
AppCodes.EntityChanges,
|
||||
permissionName,
|
||||
item,
|
||||
permEntityChanges.Name,
|
||||
true,
|
||||
MultiTenancySides.Both
|
||||
));
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Branches
|
||||
await repositoryGroup.InsertAsync(new PermissionGroupDefinitionRecord
|
||||
{
|
||||
|
|
|
|||
|
|
@ -327,7 +327,6 @@ public static class PlatformConsts
|
|||
public const string GlobalSearch = "List-0018";
|
||||
public const string SecurityLog = "List-0019";
|
||||
public const string AuditLog = "List-0020";
|
||||
public const string EntityChange = "List-0021";
|
||||
public const string Branch = "List-0022";
|
||||
public const string ListformField = "List-1000";
|
||||
public const string Order = "List-Order";
|
||||
|
|
|
|||
|
|
@ -362,7 +362,6 @@ public static class SeedConsts
|
|||
public const string IpRestrictions = Prefix.App + ".IpRestrictions";
|
||||
public const string PublicApis = Prefix.App + ".PublicApis";
|
||||
public const string AuditLogs = Prefix.App + ".AuditLogs";
|
||||
public const string EntityChanges = Prefix.App + ".EntityChanges";
|
||||
public const string Branches = Prefix.App + ".Branches";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import {
|
|||
UserInfoViewModel,
|
||||
} from '@/proxy/admin'
|
||||
import apiService from '@/services/api.service'
|
||||
import { AuditLogDto } from '../auditLog/audit-log'
|
||||
|
||||
export const getRoles = (skipCount = 0, maxResultCount = 10) =>
|
||||
apiService.fetchData<ListResultDto<IdentityRoleDto>>({
|
||||
|
|
@ -65,3 +66,9 @@ export const updatePermissions = (
|
|||
url: `/api/permission-management/permissions?providerName=${providerName}&providerKey=${providerKey}`,
|
||||
data: input,
|
||||
})
|
||||
|
||||
export const getAuditLogs = (id: string) =>
|
||||
apiService.fetchData<AuditLogDto>({
|
||||
method: 'GET',
|
||||
url: `/api/app/audit-log/${id}`,
|
||||
})
|
||||
44
ui/src/proxy/auditLog/audit-log.ts
Normal file
44
ui/src/proxy/auditLog/audit-log.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
export interface AuditLogActionDto {
|
||||
serviceName: string
|
||||
methodName: string
|
||||
executionTime: string // Date string
|
||||
executionDuration: number
|
||||
parameters: string
|
||||
}
|
||||
|
||||
export interface EntityPropertyChangeDto {
|
||||
propertyName: string
|
||||
propertyTypeFullName: string
|
||||
originalValue: string | null
|
||||
newValue: string | null
|
||||
}
|
||||
|
||||
export interface EntityChangeDto {
|
||||
changeTime: string // Date string
|
||||
changeType: number
|
||||
entityId: string
|
||||
entityTypeFullName: string
|
||||
propertyChanges: EntityPropertyChangeDto[]
|
||||
}
|
||||
|
||||
export interface AuditLogDto {
|
||||
id: string
|
||||
applicationName: string
|
||||
userId?: string
|
||||
userName?: string
|
||||
executionTime: string
|
||||
executionDuration: number
|
||||
clientIpAddress?: string
|
||||
clientName?: string
|
||||
clientId?: string
|
||||
correlationId?: string
|
||||
browserInfo?: string
|
||||
httpMethod?: string
|
||||
url?: string
|
||||
exceptions?: string
|
||||
comments?: string
|
||||
httpStatusCode?: number
|
||||
entityChangeCount?: number
|
||||
entityChanges: EntityChangeDto[]
|
||||
actions: AuditLogActionDto[]
|
||||
}
|
||||
214
ui/src/views/admin/auditLog/AuditLogDetail.tsx
Normal file
214
ui/src/views/admin/auditLog/AuditLogDetail.tsx
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
import { useEffect, useState } from 'react'
|
||||
import Dialog from '@/components/ui/Dialog'
|
||||
import TabList from '@/components/ui/Tabs/TabList'
|
||||
import TabNav from '@/components/ui/Tabs/TabNav'
|
||||
import TabContent from '@/components/ui/Tabs/TabContent'
|
||||
import { Tabs } from '@/components/ui'
|
||||
import { AdaptableCard } from '@/components/shared'
|
||||
import { getAuditLogs } from '@/proxy/admin/identity.service'
|
||||
import { AuditLogDto } from '@/proxy/auditLog/audit-log'
|
||||
|
||||
function AuditLogs({
|
||||
open,
|
||||
onDialogClose,
|
||||
id,
|
||||
}: {
|
||||
open: boolean
|
||||
onDialogClose: () => void
|
||||
id: string
|
||||
}) {
|
||||
const [selectedLog, setSelectedLog] = useState<AuditLogDto>()
|
||||
|
||||
useEffect(() => {
|
||||
if (open && id) {
|
||||
fetchAuditLog(id)
|
||||
}
|
||||
}, [open, id])
|
||||
|
||||
const fetchAuditLog = async (logId: string) => {
|
||||
const response = await getAuditLogs(logId)
|
||||
setSelectedLog(response.data)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog width="80%" isOpen={open} onClose={onDialogClose} onRequestClose={onDialogClose}>
|
||||
<h5 className="text-lg font-semibold mb-4">
|
||||
Audit Log Detail
|
||||
{selectedLog?.id && (
|
||||
<span className="text-xs font-normal text-slate-500 ml-2">({selectedLog.id})</span>
|
||||
)}
|
||||
</h5>
|
||||
|
||||
{!selectedLog ? (
|
||||
<div className="text-center py-6 text-gray-500">Loading...</div>
|
||||
) : (
|
||||
<Tabs defaultValue="log" variant="pill">
|
||||
<TabList className="flex-wrap border-b mb-4 bg-slate-50 rounded-t">
|
||||
<TabNav value="log">Log</TabNav>
|
||||
<TabNav value="actions">
|
||||
Actions {selectedLog.actions?.length > 0 && `(${selectedLog.actions.length})`}
|
||||
</TabNav>
|
||||
<TabNav value="changes">
|
||||
Entity Changes{' '}
|
||||
{selectedLog.entityChanges?.length > 0 && `(${selectedLog.entityChanges.length})`}
|
||||
</TabNav>
|
||||
</TabList>
|
||||
|
||||
{/* LOG DETAILS */}
|
||||
<TabContent value="log">
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 p-2">
|
||||
<AdaptableCard>
|
||||
<h6 className="font-medium mb-3 text-slate-600 text-sm">Request Info</h6>
|
||||
<table className="w-full text-xs">
|
||||
<tbody className="[&>tr>*]:py-0.5 [&>tr>td:first-child]:font-semibold [&>tr>td:first-child]:w-40 [&>tr>td:last-child]:break-all">
|
||||
<tr>
|
||||
<td>User</td>
|
||||
<td>{selectedLog.userName}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Time</td>
|
||||
<td>{new Date(selectedLog.executionTime).toLocaleString()}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Duration</td>
|
||||
<td>{selectedLog.executionDuration} ms</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IP</td>
|
||||
<td>{selectedLog.clientIpAddress}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Method</td>
|
||||
<td>{selectedLog.httpMethod}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Status Code</td>
|
||||
<td>{selectedLog.httpStatusCode}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>URL</td>
|
||||
<td>{selectedLog.url}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</AdaptableCard>
|
||||
|
||||
<AdaptableCard>
|
||||
<h6 className="font-medium mb-3 text-slate-600 text-sm">Client Info</h6>
|
||||
<table className="w-full text-xs">
|
||||
<tbody className="[&>tr>*]:py-0.5 [&>tr>td:first-child]:font-semibold [&>tr>td:first-child]:w-40 [&>tr>td:last-child]:break-all">
|
||||
<tr>
|
||||
<td>Browser</td>
|
||||
<td>{selectedLog.browserInfo}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Exceptions</td>
|
||||
<td>
|
||||
<pre className="bg-slate-100 text-red-500 p-2 rounded text-[11px] whitespace-pre-wrap leading-snug">
|
||||
{selectedLog.exceptions || 'None'}
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</AdaptableCard>
|
||||
</div>
|
||||
</TabContent>
|
||||
|
||||
{/* ACTIONS */}
|
||||
<TabContent value="actions">
|
||||
{selectedLog.actions?.map((action, index) => (
|
||||
<AdaptableCard key={index} className="mb-4">
|
||||
<h6 className="font-medium text-slate-600 mb-3 text-sm">Action #{index + 1}</h6>
|
||||
<table className="w-full text-xs">
|
||||
<tbody className="[&>tr>*]:py-0.5 [&>tr>td:first-child]:font-semibold [&>tr>td:first-child]:w-40 [&>tr>td:last-child]:break-all">
|
||||
<tr>
|
||||
<td>Service</td>
|
||||
<td>{action.serviceName}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Method</td>
|
||||
<td>{action.methodName}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Time</td>
|
||||
<td>{action.executionTime}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Duration</td>
|
||||
<td>{action.executionDuration} ms</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Parameters</td>
|
||||
<td>
|
||||
<pre className="bg-slate-100 p-2 rounded text-[11px] whitespace-pre-wrap leading-snug">
|
||||
{action.parameters}
|
||||
</pre>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</AdaptableCard>
|
||||
))}
|
||||
</TabContent>
|
||||
|
||||
{/* ENTITY CHANGES */}
|
||||
<TabContent value="changes">
|
||||
{selectedLog.entityChanges?.map((change, index) => (
|
||||
<AdaptableCard key={index} className="mb-4">
|
||||
<h6 className="font-medium text-slate-600 mb-3 text-sm">Change #{index + 1}</h6>
|
||||
<table className="w-full text-xs">
|
||||
<tbody className="[&>tr>*]:py-0.5 [&>tr>td:first-child]:font-semibold [&>tr>td:first-child]:w-40 [&>tr>td:last-child]:break-all">
|
||||
<tr>
|
||||
<td>Time</td>
|
||||
<td>{new Date(change.changeTime).toLocaleString()}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Type</td>
|
||||
<td>{change.changeType}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Entity ID</td>
|
||||
<td>{change.entityId}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Entity Type</td>
|
||||
<td>{change.entityTypeFullName}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Property Changes</td>
|
||||
<td>
|
||||
<ul className="list-disc pl-4 space-y-1">
|
||||
{change.propertyChanges.map((p, i) => (
|
||||
<li key={i}>
|
||||
<code>{p.propertyName}</code> ({p.propertyTypeFullName}):{' '}
|
||||
{!p.originalValue || p.originalValue === 'null' ? (
|
||||
<span className="text-green-600 font-semibold ml-1">
|
||||
{p.newValue}
|
||||
</span>
|
||||
) : (
|
||||
<>
|
||||
<span className="text-gray-500">{p.originalValue}</span>{' '}
|
||||
<span className="mx-1">→</span>
|
||||
<span className="text-yellow-600 font-semibold">
|
||||
{p.newValue}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</AdaptableCard>
|
||||
))}
|
||||
</TabContent>
|
||||
</Tabs>
|
||||
)}
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
export default AuditLogs
|
||||
|
|
@ -3,6 +3,7 @@ import UsersPermission from '@/views/admin/identity/Users/UsersPermission'
|
|||
import TenantsConnectionString from '@/views/admin/tenant-management/TenantsConnectionString'
|
||||
import { useDialogContext } from './DialogProvider'
|
||||
import CreateNotification from '@/views/admin/notification/CreateNotification'
|
||||
import AuditLogDetail from '@/views/admin/auditLog/AuditLogDetail'
|
||||
|
||||
const DialogShowComponent = (): JSX.Element => {
|
||||
const dialogContext: any = useDialogContext()
|
||||
|
|
@ -41,6 +42,14 @@ const DialogShowComponent = (): JSX.Element => {
|
|||
{...dialogContext.config?.props}
|
||||
></CreateNotification>
|
||||
)
|
||||
case 'AuditLogDetail':
|
||||
return (
|
||||
<AuditLogDetail
|
||||
open={true}
|
||||
onDialogClose={() => dialogContext.setConfig({})}
|
||||
{...dialogContext.config?.props}
|
||||
></AuditLogDetail>
|
||||
)
|
||||
default:
|
||||
return <></>
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue