RED-3982 - WIP on 'Configure Digital Signature Certificate' dialog

This commit is contained in:
Valentin Mihai 2022-05-14 01:52:05 +03:00
parent da1fa1246d
commit ea638644fb
17 changed files with 164 additions and 19 deletions

View File

@ -43,6 +43,7 @@ import { ConfirmDeleteDossierStateDialogComponent } from './dialogs/confirm-dele
import { BaseEntityScreenComponent } from './base-entity-screen/base-entity-screen.component';
import { CloneDossierTemplateDialogComponent } from './dialogs/clone-dossier-template-dialog/clone-dossier-template-dialog.component';
import { AdminSideNavComponent } from './admin-side-nav/admin-side-nav.component';
import { ConfigureCertificateDialogComponent } from './dialogs/configure-digital-signature-dialog/configure-certificate-dialog.component';
const dialogs = [
AddEditDossierTemplateDialogComponent,
@ -58,6 +59,7 @@ const dialogs = [
UploadDictionaryDialogComponent,
AddEditDossierStateDialogComponent,
ConfirmDeleteDossierStateDialogComponent,
ConfigureCertificateDialogComponent,
];
const screens = [

View File

@ -0,0 +1,27 @@
<section class="dialog">
<div class="dialog-header heading-l" translate="digital-signature-dialog.title"></div>
<div class="dialog-content">
<div
*ngFor="let option of certificateOptions"
class="option"
(click)="selectedOption = option"
[class.selected]="option === selectedOption"
>
<div class="title">
<iqser-round-checkbox [active]="option === selectedOption"></iqser-round-checkbox>
{{ translations[option].title | translate }}
</div>
<p class="description">
{{ translations[option].description | translate }}
</p>
</div>
</div>
<div class="dialog-actions">
<button (click)="displaySignatureConfiguration()" color="primary" mat-flat-button>
{{ 'digital-signature-dialog.actions.continue' | translate }}
</button>
<div translate="digital-signature-dialog.actions.cancel" class="all-caps-label cancel" mat-dialog-close></div>
</div>
</section>

View File

@ -0,0 +1,37 @@
@use 'variables';
.dialog {
.dialog-content {
.option {
margin-top: 12px;
height: 56px;
border-radius: 8px;
background: rgba(variables.$grey-2, 0.8);
border: 16px solid transparent;
cursor: pointer;
.title {
display: flex;
align-items: center;
font-weight: bold;
iqser-round-checkbox {
padding-right: 6px;
}
p {
font-weight: bold;
}
}
.description {
font-size: 11px;
opacity: 0.7;
margin-top: 6px;
}
}
.selected {
background: rgba(variables.$red-1, 0.1);
}
}
}

View File

@ -0,0 +1,20 @@
import { Component } from '@angular/core';
import { digitalSignatureDialogTranslations } from '../../translations/digital-signature-dialog-translations';
enum CertificateType {
PKCS = 'pkcs',
KMS = 'kms',
}
@Component({
templateUrl: './configure-certificate-dialog.component.html',
styleUrls: ['./configure-certificate-dialog.component.scss'],
})
export class ConfigureCertificateDialogComponent {
readonly certificateOptions = Object.values(CertificateType);
readonly translations = digitalSignatureDialogTranslations;
selectedOption = this.certificateOptions[0];
displaySignatureConfiguration() {}
}

View File

@ -14,14 +14,15 @@
<div class="content-container">
<div class="content-container-content">
<form *ngIf="form" [formGroup]="form" autocomplete="off">
<input #fileInput (change)="fileChanged($event, fileInput)" class="file-upload-input" hidden type="file" />
<!-- <input #fileInput (change)="fileChanged($event, fileInput)" class="file-upload-input" hidden type="file" />-->
<iqser-empty-state
(action)="fileInput.click()"
(action)="openConfigureCertificate()"
*ngIf="!hasDigitalSignatureSet"
[buttonLabel]="'digital-signature-screen.no-data.action' | translate"
[text]="'digital-signature-screen.no-data.title' | translate"
buttonIcon="iqser:upload"
icon="iqser:document"
[buttonIcon]="null"
></iqser-empty-state>
<div [class.hidden]="!hasDigitalSignatureSet" class="iqser-input-group required w-300">

View File

@ -9,6 +9,7 @@ import { DigitalSignatureService } from '../../services/digital-signature.servic
import { IDigitalSignature } from '@red/domain';
import { firstValueFrom } from 'rxjs';
import { HttpStatusCode } from '@angular/common/http';
import { AdminDialogService } from '../../services/admin-dialog.service';
@Component({
selector: 'redaction-digital-signature-screen',
@ -29,8 +30,9 @@ export class DigitalSignatureScreenComponent implements OnInit {
private readonly _formBuilder: FormBuilder,
private readonly _userService: UserService,
private readonly _loadingService: LoadingService,
readonly routerHistoryService: RouterHistoryService,
private readonly _digitalSignatureService: DigitalSignatureService,
private readonly _dialogService: AdminDialogService,
readonly routerHistoryService: RouterHistoryService,
) {}
get hasDigitalSignatureSet() {
@ -82,17 +84,21 @@ export class DigitalSignatureScreenComponent implements OnInit {
}
}
fileChanged(event, input: HTMLInputElement) {
const file = event.target.files[0];
const fileReader = new FileReader();
fileReader.onload = () => {
const dataUrl = <string>fileReader.result;
const actualBase64Value = dataUrl.substring(lastIndexOfEnd(dataUrl, ';base64,'));
this.form.get('base64EncodedPrivateKey').setValue(actualBase64Value);
this.form.get('certificateName').setValue(file.name);
input.value = null;
};
fileReader.readAsDataURL(file as Blob);
// fileChanged(event, input: HTMLInputElement) {
// const file = event.target.files[0];
// const fileReader = new FileReader();
// fileReader.onload = () => {
// const dataUrl = <string>fileReader.result;
// const actualBase64Value = dataUrl.substring(lastIndexOfEnd(dataUrl, ';base64,'));
// this.form.get('base64EncodedPrivateKey').setValue(actualBase64Value);
// this.form.get('certificateName').setValue(file.name);
// input.value = null;
// };
// fileReader.readAsDataURL(file as Blob);
// }
openConfigureCertificate() {
this._dialogService.openDialog('configureCertificate', null, null);
}
async loadDigitalSignatureAndInitializeForm(): Promise<void> {

View File

@ -29,6 +29,7 @@ import { UserService } from '@services/user.service';
import { IDossierAttributeConfig, IFileAttributeConfig, IReportTemplate } from '@red/domain';
import { ReportTemplateService } from '@services/report-template.service';
import { CloneDossierTemplateDialogComponent } from '../dialogs/clone-dossier-template-dialog/clone-dossier-template-dialog.component';
import { ConfigureCertificateDialogComponent } from '../dialogs/configure-digital-signature-dialog/configure-certificate-dialog.component';
type DialogType =
| 'confirm'
@ -44,7 +45,8 @@ type DialogType =
| 'addEditDossierAttribute'
| 'uploadDictionary'
| 'addEditDossierState'
| 'deleteDossierState';
| 'deleteDossierState'
| 'configureCertificate';
@Injectable()
export class AdminDialogService extends DialogService<DialogType> {
@ -101,6 +103,10 @@ export class AdminDialogService extends DialogService<DialogType> {
deleteDossierState: {
component: ConfirmDeleteDossierStateDialogComponent,
},
configureCertificate: {
component: ConfigureCertificateDialogComponent,
dialogConfig: { disableClose: false },
},
};
constructor(

View File

@ -0,0 +1,12 @@
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
export const digitalSignatureDialogTranslations = {
pkcs: {
title: _('digital-signature-dialog.options.pkcs.title'),
description: _('digital-signature-dialog.options.pkcs.description'),
},
kms: {
title: _('digital-signature-dialog.options.kms.title'),
description: _('digital-signature-dialog.options.kms.description'),
},
} as const;

View File

@ -655,6 +655,23 @@
}
},
"digital-signature": "Digitale Signatur",
"digital-signature-dialog": {
"actions": {
"cancel": "",
"continue": ""
},
"options": {
"kms": {
"description": "",
"title": ""
},
"pkcs": {
"description": "",
"title": ""
}
},
"title": ""
},
"digital-signature-screen": {
"action": {
"certificate-not-valid-error": "Das hochgeladene Zertifikat eignet sich nicht zum Signieren von PDF-Dokumenten. Sie benötigen das Format PCKS#12.",

View File

@ -655,6 +655,23 @@
}
},
"digital-signature": "Digital Signature",
"digital-signature-dialog": {
"actions": {
"cancel": "Cancel",
"continue": "Continue"
},
"options": {
"kms": {
"description": "Provide a corresponding PEM file containing the certificate, along with Amazon KMS credentials needed for securing the private key.",
"title": "I use an Amazon KMS private key"
},
"pkcs": {
"description": "A PKCS#12 file is a file that bundles the private key and the X.509 certificate. The password protection is required to secure the private key. Unprotected PKCS#12 files are not supported.",
"title": "I want to upload a PKCS#12 file"
}
},
"title": "Configure Digital Signature Certificate"
},
"digital-signature-screen": {
"action": {
"certificate-not-valid-error": "Uploaded Certificate is not valid for signing PDFs. PCKS.12 format is required.",
@ -679,8 +696,8 @@
"placeholder": "Location"
},
"no-data": {
"action": "Upload Certificate",
"title": "No Digital Signature certificate is configured. For signing redacted documents please upload a PCKS.12 certificate."
"action": "Configure Certificate",
"title": "No Digital Signature Certificate.<br/>For signing redacted documents please configure a certificate."
},
"password": {
"label": "Certificate Password/Key",

@ -1 +1 @@
Subproject commit 58f7b5d8b9c88ef5c1f6ff7780e3417511523ee1
Subproject commit ad3c87b4a09961d8f32778c0c912e586cd4576cd