Files
SystemX.Web/Projects/VPKI/VPKI/VPKI.Web.Client/Components/Pages/VPKIManager.razor

527 lines
21 KiB
Plaintext

@page "/vpki/manager"
@using DB.VPKI_DataDB
@using System.Text
@using SystemX.Core.Communication
@using VPKI.Library.Packet
@using VPKI.Library.Static
@inject ApiService ApiService
@inject VpkiDialogService DialogService
@inject IJSRuntime JS
@inject NotificationService NotiService
@inject TooltipService TooltipService
<h3>VPKI MANAGER</h3>
<AuthorizeView Roles="@($"{UserRole.Admin.ToString()},{UserRole.SuperUser.ToString()}")">
<Authorized Context="AuthContext">
<RadzenFieldset Style="margin-bottom: 10px;" Text="Server Info">
<div style="margin-bottom: 10px;">
<RadzenLabel Style="width: 130px;" Text="Server Address"></RadzenLabel>
<RadzenTextBox Style="margin-right: 10px;" @bind-Value="@ServerAddress"></RadzenTextBox>
</div>
</RadzenFieldset>
<RadzenFieldset Style="margin-bottom: 10px;" Text="View Options">
<div style="margin-bottom: 10px;">
<!--date-->
<RadzenLabel Style="margin-right: 5px;" Text="Date"></RadzenLabel>
<RadzenDatePicker Style="margin-right: 5px;" @bind-Value="@SearchStartDate" DateFormat="yyyy/MM/dd" />
<RadzenLabel Style="margin-right: 5px;" Text="~"></RadzenLabel>
<RadzenDatePicker Style="margin-right: 10px;" @bind-Value="@SearchEndDate" DateFormat="yyyy/MM/dd" />
<RadzenButton Style="margin-right: 30px;" Click="@(()=>Search(0))">Search</RadzenButton>
<!--vew Count-->
<RadzenLabel Style="margin-right: 5px;" Text="ViewCount (20~100)"></RadzenLabel>
<RadzenNumeric @bind-Value=@ViewCount Min=20 Max=100></RadzenNumeric>
</div>
</RadzenFieldset>
<br />
<!--count-->
<div style="display: flex; justify-content: space-between; margin-bottom: 0.7rem;">
<div style="display: flex; align-items:center;">
<RadzenLabel Style="color:#BA68C8; font-weight: 600; font-size: 1.1rem; margin-right: 1.2rem;" Text=@($"Total Count: {history.Count}")></RadzenLabel>
<RadzenLabel Style="color:#64B5F6; font-weight: 600; font-size: 1.1rem;" Text=@($"Filter Count: {grid.View.Count()}")></RadzenLabel>
</div>
<div>
<RadzenButton Style="background: #7E57C2; margin-right: 0.5rem;" Text="Export CSV(Full Data)" Click="@(()=>OnClickExportCSV(false))"></RadzenButton>
<RadzenButton Style="background: #1976D2;" Text="Export CSV(Filter Data)" Click="@(()=>OnClickExportCSV(true))"></RadzenButton>
</div>
</div>
<RadzenDataGrid @ref="@grid" Data="@history" TItem="CertificateHistoryModel" AllowFiltering FilterMode="FilterMode.Simple"
AllowPaging PageNumbersCount="10" PageSize="@ViewCount" PagerHorizontalAlign="HorizontalAlign.Center" AllowSorting RowExpand="@((args)=>OnExpand(args))"
FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive" Filter="@OnChangeFilter" FilterCleared="@OnChangeFilter">
<Columns>
<!--index or no-->
@* <RadzenDataGridColumn Title="No">
<Template>
@(history.IndexOf(context)+1)
</Template>
</RadzenDataGridColumn> *@
<!--data-->
@foreach (var prop in typeof(TTbscsr).GetProperties())
{
if (prop.Name.ToLower().Contains("hashedtbscsr") || prop.Name.ToLower().Contains("publickey") || prop.Name.ToLower().Contains("origintbscsr")
|| prop.Name.ToLower().Contains("csrsignature") || prop.Name.ToLower().Contains("datetime") || prop.Name.ToLower().Contains("cdn"))
continue;
string propName = $"{prop.Name}";
<RadzenDataGridColumn Title="@propName" Property=@($"TTbscsr.{propName}") />
}
<!--date time-->
<RadzenDataGridColumn Width="9rem" Title="CDATETIME">
<Template>
@{
<div style="font-size: 0.8rem;">
<RadzenLabel Text="Tbscsr DateTime"></RadzenLabel>
<br />
<RadzenLabel Text="@context?.TTbscsr?.CDateTime.ToString("yyyy-MM-dd HH:mm:ss")"></RadzenLabel>
<br />
<RadzenLabel Text="Certificate DateTime"></RadzenLabel>
<br />
<RadzenLabel Text="@context?.TCertificate?.CDateTime.ToString("yyyy-MM-dd HH:mm:ss")"></RadzenLabel>
</div>
}
</Template>
</RadzenDataGridColumn>
<!--Reissue, Revoke-->
@* <RadzenDataGridColumn Title="Reissue">
<Template>
@{
bool canReissue = string.IsNullOrEmpty($"{context.TCertificate?.CCsr}");
<RadzenButton Style="width:100%; color:black;" Text="Reissue" Disabled=@canReissue
ButtonStyle="ButtonStyle.Warning" Click="@(()=>OnClickReissue(context))"></RadzenButton>
}
</Template>
</RadzenDataGridColumn> *@
@* <RadzenDataGridColumn Title="Revoke">
<Template>
@{
bool canRevoke = true;
canRevoke = !(context.TCertificate?.CIssueCount > 0);
}
<RadzenButton Style="width:100%; color: black;" Text="Revoke" Disabled=@canRevoke
ButtonStyle="ButtonStyle.Danger" Click="@(()=>OnClickRevoke(context))"></RadzenButton>
</Template>
</RadzenDataGridColumn> *@
</Columns>
<Template>
<!--tbscsr-->
<div style="display:flex; align-items: center; margin-bottom: 0.2rem;">
<RadzenLabel Text="Tbscsr" Style="margin-right: 0.5rem;"></RadzenLabel>
<RadzenIcon Icon="description" Style="cursor: pointer;" MouseEnter="@(args => TooltipService.Open(args, "Copy"))" @onclick="@(()=>OnClickCopy(context?.TTbscsr?.ToJson()))"></RadzenIcon>
</div>
<div>
<RadzenTextArea Style="width:100%; height:10rem;" Value="@context?.TTbscsr?.ToJson()" ReadOnly></RadzenTextArea>
</div>
<br />
<!--certificate-->
<RadzenLabel Text="TCertificate"></RadzenLabel>
<div>
<RadzenTextArea Style="width:100%; height:10rem;" Value="@context?.TCertificate?.ToJson()" ReadOnly></RadzenTextArea>
</div>
@{
bool canDownload = string.IsNullOrEmpty($"{context.TCertificate?.CCert}");
}
<RadzenButton Style="background: #7E57C2;" Text="Certificate Download" Click="@(()=>OnClickExportCertificate(context))" Disabled="@canDownload"></RadzenButton>
<RadzenButton Style="background: #1976D2;" Text="SubCA Certificate Download" Click="@(()=>OnClickExportSubCACertificate(context))" Disabled="@canDownload"></RadzenButton>
<br />
<br />
<!--verify result-->
<RadzenLabel Text="TVerifyResult"></RadzenLabel>
<div>
<RadzenTextArea Style="width:100%; height:10rem;" Value="@context?.TVerifyResult?.ToJson()" ReadOnly></RadzenTextArea>
</div>
<br />
@if (context.TTbscsr.CCertType == VpkiType.prov_v1.ToString())
{
<!--certificate info-->
<RadzenLabel Text="TOcsp"></RadzenLabel>
<div>
<RadzenTextArea Style="width:100%; height:10rem;" Value="@context.TOcsp?.ToJson()" ReadOnly></RadzenTextArea>
</div>
<br />
<!--ocsp-->
<RadzenLabel Text="OCSP"></RadzenLabel>
<div>
<RadzenTextArea Style="width:100%; height:10rem;" Value="@context.TOcsp?.COcsp" ReadOnly></RadzenTextArea>
</div>
<RadzenButton Style="background: #7E57C2;" Text="OCSP Download" Click="@(()=>OnClickOcspDownload(context))"></RadzenButton>
}
</Template>
</RadzenDataGrid>
</Authorized>
<NotAuthorized>
<RadzenLabel Text="Not Authorized"></RadzenLabel>
</NotAuthorized>
</AuthorizeView>
@code {
private string ServerAddress = "127.0.0.1:8080";
private DateOnly SearchStartDate = DateOnly.FromDateTime(DateTime.Now.AddDays(-7));
private DateOnly SearchEndDate = DateOnly.FromDateTime(DateTime.Now);
private string FilterIft = string.Empty;
private string FilterWMI = string.Empty;
private string FilterDC = string.Empty;
private string FilterCertType = string.Empty;
private int ViewCount = 20;
List<CertificateHistoryModel> history = new List<CertificateHistoryModel>();
RadzenDataGrid<CertificateHistoryModel> grid = new();
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
//await Search(0);
}
await Task.CompletedTask;
}
private async Task Search(int startCcuid)
{
DialogService.OpenIndicator("Search History");
string requestUrl = $"https://{ServerAddress}/history?";
//Default filter
requestUrl += $"startDate={SearchStartDate}&";
requestUrl += $"endDate={SearchEndDate}&";
// requestUrl += $"startCcuid={startCcuid}&";
//optional filter
// if (string.IsNullOrEmpty(FilterIft) == false)
// {
// requestUrl += $"ift={FilterIft}&";
// }
// if (string.IsNullOrEmpty(FilterWMI) == false)
// {
// requestUrl += $"wmi={FilterWMI}&";
// }
// if (string.IsNullOrEmpty(FilterDC) == false)
// {
// requestUrl += $"dc={FilterDC}&";
// }
// if (string.IsNullOrEmpty(FilterCertType) == false)
// {
// requestUrl += $"certType={FilterCertType}&";
// }
history?.Clear();
var http = new Http();
var result = await http.GetJsonAsync<List<CertificateHistoryModel>>(requestUrl);
if (result != null)
{
history.AddRange(result);
history.Reverse();
}
grid?.Reload();
DialogService.CloseIndicator();
}
private async Task OnClickReissue(CertificateHistoryModel args)
{
var confirmRsult = await DialogService.Confirm("Reissue", "Are you sure certificate reissue?");
if (confirmRsult == false)
return;
DialogService.OpenIndicator("Reissue");
Request_Certificate requestReissue = new Request_Certificate
{
iftid = args.TTbscsr.CIftid,
csrsignature = args.TCertificate.CCsrsignature,
tierCode = args.TCertificate.CTierCode,
unitCode = args.TCertificate.CUnitCode,
vehicleCode = args.TCertificate.CVehicleCode,
localCode = args.TCertificate.CLocalCode,
brandCode = args.TCertificate.CBrandCode
};
string api = string.Empty;
if (args.TTbscsr.CCertType.ToLower() == VpkiType.prov_v1.ToString())
{
api = "api/v1/reissue";
}
else if (args.TTbscsr.CCertType.ToLower() == VpkiType.prov_cert.ToString())
{
api = "api/v2/prov/reissue";
}
else if (args.TTbscsr.CCertType.ToLower() == VpkiType.vehicle_cert.ToString())
{
api = "api/v2/vehicle/reissue";
}
var http = new Http();
var result = await http.PostJsonAsync<Request_Certificate, Response_Certificate>($"https://{ServerAddress}/{api}", requestReissue);
if (result != null)
{
string requestUrl = $"https://{ServerAddress}/history/ccuid?ccuid={args.TTbscsr.CCuid}";
var updateResult = await http.GetJsonAsync<CertificateHistoryModel>(requestUrl);
if (updateResult != null)
{
args.TTbscsr = updateResult.TTbscsr;
args.TCertificate = updateResult.TCertificate;
args.TVerifyResult = updateResult.TVerifyResult;
args.TOcsp = updateResult.TOcsp;
}
NotiService.Notify(NotificationSeverity.Success, "Reissue", "Reissue Success");
}
else
{
NotiService.Notify(NotificationSeverity.Error, "Reissue", "Reissue Failed");
}
await grid?.CollapseAll();
await grid?.Reload();
StateHasChanged();
DialogService.CloseIndicator();
}
private async Task OnClickRevoke(CertificateHistoryModel args)
{
var confirmRsult = await DialogService.Confirm("Revoke", "Are you sure certificate revoke?");
if (confirmRsult == false)
return;
DialogService.OpenIndicator("Revoke");
Request_CertificateRevokeOEM requestRevoke = new Request_CertificateRevokeOEM
{
dn = args.TTbscsr.CDn
};
string api = string.Empty;
if (args.TTbscsr.CCertType.ToLower() == VpkiType.prov_v1.ToString())
{
api = "api/v1/revoke";
}
else if (args.TTbscsr.CCertType.ToLower() == VpkiType.prov_cert.ToString())
{
api = "api/v2/prov/revoke";
}
else if (args.TTbscsr.CCertType.ToLower() == VpkiType.vehicle_cert.ToString())
{
api = "api/v2/vehicle/revoke";
}
var http = new Http();
var result = await http.PostJsonAsync<Request_CertificateRevokeOEM, Response_CertificateRevokeOEM>($"https://{ServerAddress}/{api}", requestRevoke);
if (result != null)
{
string requestUrl = $"https://{ServerAddress}/history/ccuid?ccuid={args.TTbscsr.CCuid}";
var updateResult = await http.GetJsonAsync<CertificateHistoryModel>(requestUrl);
if (updateResult != null)
{
args.TTbscsr = updateResult.TTbscsr;
args.TCertificate = updateResult.TCertificate;
args.TVerifyResult = updateResult.TVerifyResult;
args.TOcsp = updateResult.TOcsp;
}
NotiService.Notify(NotificationSeverity.Success, "Revoke", "Revoke Success");
}
else
{
NotiService.Notify(NotificationSeverity.Error, "Revoke", "Revoke Failed");
}
await grid?.CollapseAll();
await grid?.Reload();
StateHasChanged();
DialogService.CloseIndicator();
}
async Task OnClickExportCSV(bool isFilter = false)
{
DialogService.OpenIndicator("Export to CSV");
List<string> exportData = new List<string>();
if (isFilter == true)
{
//필터링된 데이터만
exportData.AddRange(grid.View.ToList().ConvertToCsvFile());
}
else
{
//전체 데이터
exportData.AddRange(history.ConvertToCsvFile());
}
if (exportData?.Count > 0)
{
string fileName = $"VPKI_{DateTime.Now.ToString("yyyyMMdd_HHmmss")}.csv";
bool exportResult = await JS.InvokeAsync<bool>("openSaveFileCSV", fileName, exportData.ToJson());
if (exportResult == true)
{
NotiService.Notify(new NotificationMessage
{
Severity = NotificationSeverity.Success,
Summary = "Success",
Detail = "CSV Export Success"
});
}
else
{
NotiService.Notify(new NotificationMessage
{
Severity = NotificationSeverity.Error,
Summary = "Failed",
Detail = "CSV Export Failed",
});
}
}
DialogService.CloseIndicator();
}
void OnChangeFilter()
{
StateHasChanged();
}
async Task OnClickExportCertificate(CertificateHistoryModel? certificate)
{
DialogService.OpenIndicator("Export to Prov Certificate");
if (certificate != null)
{
string fileName = $"{certificate?.TTbscsr?.CPcid}.pem";
bool exportResult = await JS.InvokeAsync<bool>("openSaveFileStr", fileName, certificate?.TCertificate?.CCert);
if (exportResult == true)
{
NotiService.Notify(new NotificationMessage
{
Severity = NotificationSeverity.Success,
Summary = "Success",
Detail = "Certificate Export Success"
});
}
else
{
NotiService.Notify(new NotificationMessage
{
Severity = NotificationSeverity.Error,
Summary = "Failed",
Detail = "Certificate Export Failed",
});
}
}
DialogService.CloseIndicator();
}
async Task OnClickExportSubCACertificate(CertificateHistoryModel? certificate)
{
DialogService.OpenIndicator("Export to Prov Certificate");
if (certificate != null)
{
var http = new Http();
string requestUrl = $"https://{ServerAddress}/certificate/GetProv?vpkiType={certificate.TTbscsr.CCertType}";
var response = await http.GetJsonAsync<string>(requestUrl);
string fileName = $"SubCA.pem";
bool exportResult = await JS.InvokeAsync<bool>("openSaveFileStr", fileName, response);
if (exportResult == true)
{
NotiService.Notify(new NotificationMessage
{
Severity = NotificationSeverity.Success,
Summary = "Success",
Detail = "SubCA Certificate Export Success"
});
}
else
{
NotiService.Notify(new NotificationMessage
{
Severity = NotificationSeverity.Error,
Summary = "Failed",
Detail = "SubCA Certificate Export Failed",
});
}
}
DialogService.CloseIndicator();
}
async Task OnClickOcspDownload(CertificateHistoryModel? certificate)
{
DialogService.OpenIndicator("Export to Prov Certificate");
if (certificate != null)
{
string fileName = $"OCSP_{certificate.TTbscsr.CPcid}.txt";
bool exportResult = await JS.InvokeAsync<bool>("openSaveFileStr", fileName, certificate.TOcsp.COcsp);
if (exportResult == true)
{
NotiService.Notify(new NotificationMessage
{
Severity = NotificationSeverity.Success,
Summary = "Success",
Detail = "OCSP Export Success"
});
}
else
{
NotiService.Notify(new NotificationMessage
{
Severity = NotificationSeverity.Error,
Summary = "Failed",
Detail = "OCSP Certificate Export Failed",
});
}
}
DialogService.CloseIndicator();
}
private async Task OnExpand(CertificateHistoryModel history)
{
await Task.CompletedTask;
}
private async Task OnClickCopy(string? text)
{
await CopyToClipboard(text);
}
private async Task CopyToClipboard(string? text)
{
bool result = await JS.InvokeAsync<bool>("copyTextToClipboard", text);
if (result == true)
{
NotiService.Notify(new NotificationMessage
{
Severity = NotificationSeverity.Success,
Summary = "Success",
Detail = "Copy To Clipboard Success."
});
}
else
{
NotiService.Notify(new NotificationMessage
{
Severity = NotificationSeverity.Error,
Summary = "Failed",
Detail = "Copy To Clipboard Failed.",
});
}
}
}