Alexander Shabarshov 2a7a24c9e7 Initial contribution
2025-11-03 14:43:26 +00:00

313 lines
8.8 KiB
Plaintext

@page "/user/audit"
@page "/user/audit/{DatabaseStr}"
@page "/user/audit/{DatabaseStr}/{DatabaseInstanceStr}"
@attribute [Authorize]
@using Rms.Risk.Mango.Services.Audit
@inject NavigationManager NavigationManager
@inject IUserSession UserSession
@inject IJSRuntime JsRuntime
@*
* dbMango
*
* Copyright 2025 Deutsche Bank AG
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*@
<style>
.js-field {
height: 300px;
position: relative;
}
.res-field {
width: 100vw;
height: calc(100vh - (150px + 300px));
overflow: auto;
}
pre {
width: 100%;
height: 100%;
font-size: 10pt;
background-color: #1d2a3b;
color: #FFFFFF;
}
</style>
<h3 class="mt-3">Audit</h3>
<AuthorizedOnly Policy="ReadAccess" Resource="@UserSession.Database">
<EditForm EditContext="EditContext">
<div class="form-row">
<FormItemDate Enabled="@IsReady" Class="mr-2" Name="Date range" @bind-StartDate="StartDate" @bind-EndDate="EndDate" SelectDateRange="true"/>
<FormItemText Enabled="@IsReady" Class="mr-2" Name="Max fetch size" @bind-Value="FetchSize" InputType="number" Icon="icon-download-selected-sm" />
<div class="form-group">
<label>&nbsp;</label>
<FormButton Enabled="@IsReady" Name="Run" Icon="icon-running-man-sm" OnClick="Run" IsPrimary="true"/>
</div>
</div>
</EditForm>
@if (ShowAsJson)
{
<FormJson Class="res-field row" Value="@Result"/>
}
else
{
<SimplePivotComponent
PivotName="audit"
CollectionName="audit"
PivotData="@ResultPivot"
HandleCellClick="@OnCellClick"
GetColumnDescriptor="@GetColumnDescriptor"
/>
}
</AuthorizedOnly>
@code {
[CascadingParameter] public IModalService Modal { get; set; } = null!;
[Parameter] public string? DatabaseStr { get; set; }
[Parameter] public string? DatabaseInstanceStr { get; set; }
private string Database
{
get => UserSession.Database;
set
{
if (UserSession.Database == value)
return;
UserSession.Database = value;
SyncUrl();
}
}
private string DatabaseInstance
{
get => UserSession.DatabaseInstance;
set
{
if (UserSession.DatabaseInstance == value)
return;
UserSession.DatabaseInstance = value;
SyncUrl();
}
}
private string FetchSize { get; set; } = "100";
private bool IsReady { get; set; } = true;
private bool ShowAsJson { get; set; }
private DateOnly? StartDate { get; set; } = DateOnly.FromDateTime(DateTime.UtcNow - TimeSpan.FromDays(7));
private DateOnly? EndDate { get; set; } = DateOnly.FromDateTime(DateTime.UtcNow);
private string Result { get; set; } = "{}";
private List<BsonDocument> ResultBson { get; set; } = [];
private ArrayBasedPivotData ResultPivot { get; set; } = new([]);
private EditContext? _editContext;
private EditContext EditContext => _editContext!;
protected override void OnInitialized()
{
_editContext = new (this);
}
protected override void OnAfterRender(bool firstRender)
{
if (!firstRender)
return;
if (string.IsNullOrWhiteSpace(DatabaseStr))
DatabaseStr = Database;
else
Database = DatabaseStr;
if (string.IsNullOrWhiteSpace(DatabaseInstanceStr))
DatabaseInstanceStr = DatabaseInstance;
else
DatabaseInstance = DatabaseInstanceStr;
UserSession.Collection = AuditService.AuditCollection;
SyncUrl();
}
private async Task Run()
{
var cts = new CancellationTokenSource(TimeSpan.FromSeconds(20));
try
{
IsReady = false;
await InvokeAsync(StateHasChanged);
var res = await RunAudit(cts.Token);
// var res = await RunAuditFind(cts.Token);
ResultPivot = res.Item1;
ResultBson = res.Item2;
await Display(ResultBson);
}
catch (Exception e)
{
await Display(e);
}
finally
{
IsReady = true;
await InvokeAsync(StateHasChanged);
}
}
private Task Display(Exception e)
{
ShowAsJson = true;
Result = e.ToString();
return InvokeAsync(StateHasChanged);
}
private Task Display(IEnumerable<BsonDocument> res)
{
Result = res.ToJson(new() { Indent = true });
return InvokeAsync(StateHasChanged);
}
private async Task<(ArrayBasedPivotData, List<BsonDocument>)> RunAudit(CancellationToken token)
{
if (StartDate == null || EndDate == null)
return (ArrayBasedPivotData.NoData,[]);
var audit = UserSession.Audit;
var res = await audit.Audit(StartDate.Value.ToDateTime(TimeOnly.MinValue), EndDate.Value.ToDateTime(TimeOnly.MaxValue), token);
var pd = new ArrayBasedPivotData([
"Timestamp UTC",
"Collection" ,
"Command" ,
"Success" ,
"Ticket" ,
"Email" ,
"Comment" ,
"Error" ,
"Json" ,
"_id"
]);
var list = new List<BsonDocument>();
var id = 0;
foreach (var auditRecord in res)
{
var row = new object?[pd.Headers.Count];
var i = 0;
row[i++] = auditRecord.Timestamp;
row[i++] = auditRecord.Command.ElementAt(0).Value.ToString() ?? "";
row[i++] = auditRecord.Command.ElementAt(0).Name;
row[i++] = auditRecord.Success;
row[i++] = auditRecord.Ticket;
row[i++] = auditRecord.Email;
row[i++] = auditRecord.Command.GetValue("comment", "").ToString();
row[i++] = auditRecord.Error;
row[i++] = auditRecord.Command.ToJson(new(){ Indent = true });
row[i ] = ++id;
var json = auditRecord.ToJson(new() { Indent = true });
var d = BsonDocument.Parse(json);
d["_id"] = id;
pd.Add(row);
list.Add(d);
}
if (list.Count == 0)
list.Add(BsonDocument.Parse("{\"Result\": \"No data fetched\"}"));
else
{
var newPd = (ArrayBasedPivotData)pd.FilterColumns(
[
"Timestamp UTC" ,
"Collection" ,
"Command" ,
"Success" ,
"Ticket" ,
"Email" ,
"Comment" ,
"Error" ,
"_id"
]);
pd = newPd;
}
return (pd, list);
}
private void SyncUrl()
{
var url = NavigationManager.BaseUri + $"user/audit/{Database}";
if (!string.IsNullOrWhiteSpace(DatabaseInstance))
url += $"/{DatabaseInstance}";
JsRuntime.InvokeAsync<string>("DashboardUtils.ChangeUrl", url);
}
private async Task<bool> OnCellClick(DynamicObject row, string columnName)
{
try
{
var id = TableControl.GetDynamicMember(row, "_id");
if (id == null)
return true;
var bson = ResultBson.FirstOrDefault(x => x["_id"].ToString() == id.ToString());
if (bson == null)
return true;
// var oldId = bson["_id"];
// _ = await Auth.AuthorizeAsync(
// UserSession.User.GetUser(),
// UserSession.Database,
// [new ReadAccessRequirement()]);
_ = await Find.ShowBsonDialog(Modal, id.ToString()!, bson, false);
}
catch (Exception e)
{
await ModalDialogUtils.ShowExceptionDialog(Modal, "Error", e);
}
return true;
}
private PivotColumnDescriptor? GetColumnDescriptor(string column)
{
if (column != "Timestamp UTC")
return null;
return new()
{
Format = "yyyy-MM-dd HH:mm:ss"
};
}
}