diff --git a/smp-angular/src/_smp-all-themes.scss b/smp-angular/src/_smp-all-themes.scss index 333fd2ac018b34233041b4126a7e10e0bfcec2b5..cc7ab387dca37b9fa924f041a00ad5097993f5a0 100644 --- a/smp-angular/src/_smp-all-themes.scss +++ b/smp-angular/src/_smp-all-themes.scss @@ -16,9 +16,7 @@ @include access-token-panel.set-component-colors($theme); @include expandable-panel.set-component-colors($theme); /* shared classes*/ - .smp-data-panel:hover { - background-color: smp.get-theme-color($theme, primary, 300); - } + .datatable-row-odd { background-color: smp.get-theme-color($theme, primary, 50, 0.2) !important; diff --git a/smp-angular/src/app/common/global-lookups.ts b/smp-angular/src/app/common/global-lookups.ts index cec7984f7dd357fa44dd7091a3a92bbd9ce06b79..d3fa51fa4e4ff0916a5e0f106a84237c55b75f7f 100644 --- a/smp-angular/src/app/common/global-lookups.ts +++ b/smp-angular/src/app/common/global-lookups.ts @@ -116,6 +116,12 @@ export class GlobalLookups { return result; } + public getDateFormat(): string { + let locale = this.getCurrentLocale(); + locale = locale ? locale : this.DEFAULT_LOCALE; + return getLocaleDateFormat(locale, FormatWidth.Short); + } + private format(str, opt_values) { if (opt_values) { str = str.replace(/\{([^}]+)}/g, function (match, key) { diff --git a/smp-angular/src/app/common/services/user.service.ts b/smp-angular/src/app/common/services/user.service.ts index e5b633f5c2f5ca0637b16f747f2540d3c2f21c75..3fc6acdb46e2385735b9c74afe5e6d5d82b88e3f 100644 --- a/smp-angular/src/app/common/services/user.service.ts +++ b/smp-angular/src/app/common/services/user.service.ts @@ -4,10 +4,11 @@ import {SmpConstants} from "../../smp.constants"; import {User} from "../../security/user.model"; import {AlertMessageService} from "../alert-message/alert-message.service"; import {SecurityService} from "../../security/security.service"; -import {Observable, Subject} from "rxjs"; +import {lastValueFrom, Observable, Subject} from "rxjs"; import {CredentialRo} from "../../security/credential.model"; import {AccessTokenRo} from "../model/access-token-ro.model"; import {HttpErrorHandlerService} from "../error/http-error-handler.service"; +import {TranslateService} from "@ngx-translate/core"; /** * Class handle current user settings such-as profile, credentials, DomiSMP settings... , @@ -31,6 +32,7 @@ export class UserService { private httpErrorHandlerService: HttpErrorHandlerService, private securityService: SecurityService, private alertService: AlertMessageService, + protected translateService: TranslateService ) { } @@ -52,13 +54,15 @@ export class UserService { } this.http.get<CredentialRo>(SmpConstants.REST_PUBLIC_USER_CREDENTIAL_STATUS .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, user.userId)) - .subscribe((response: CredentialRo) => { - this.notifyPwdStatusUpdated(response) - }, error => { - if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){ - return; + .subscribe({ + next: (response: CredentialRo) => { + this.notifyPwdStatusUpdated(response) + }, error: (error: any) => { + if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) { + return; + } + this.alertService.error(error.error?.errorDescription) } - this.alertService.error(error.error?.errorDescription) }); } @@ -69,13 +73,15 @@ export class UserService { } this.http.get<CredentialRo[]>(SmpConstants.REST_PUBLIC_USER_ACCESS_TOKEN_CREDENTIALS .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, user.userId)) - .subscribe((response: CredentialRo[]) => { - this.notifyAccessTokensUpdated(response) - }, error => { - if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){ - return; + .subscribe({ + next: (response: CredentialRo[]) => { + this.notifyAccessTokensUpdated(response) + }, error: (error: any) => { + if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) { + return; + } + this.alertService.error(error.error?.errorDescription) } - this.alertService.error(error.error?.errorDescription) }); } @@ -87,14 +93,16 @@ export class UserService { this.http.delete<CredentialRo>(SmpConstants.REST_PUBLIC_USER_MANAGE_ACCESS_TOKEN_CREDENTIAL .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, user.userId) .replace(SmpConstants.PATH_PARAM_ENC_CREDENTIAL_ID, credential.credentialId)) - .subscribe((response: CredentialRo) => { - this.notifyAccessTokenUpdated(response) - this.alertService.success("Access token ["+response.name+"] has been deleted!") - }, error => { - if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){ - return; + .subscribe({ + next: async (response: CredentialRo) => { + this.notifyAccessTokenUpdated(response) + this.alertService.success(await lastValueFrom(this.translateService.get("user.access.tokens.success.deleted", {credentialName: response.name}))) + }, error: (error: any) => { + if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) { + return; + } + this.alertService.error(error.error?.errorDescription) } - this.alertService.error(error.error?.errorDescription) }); } @@ -106,14 +114,16 @@ export class UserService { this.http.post<CredentialRo>(SmpConstants.REST_PUBLIC_USER_MANAGE_ACCESS_TOKEN_CREDENTIAL .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, user.userId) .replace(SmpConstants.PATH_PARAM_ENC_CREDENTIAL_ID, credential.credentialId), credential) - .subscribe((response: CredentialRo) => { - this.notifyAccessTokenUpdated(response) - this.alertService.success("Access token ["+response.name+"] has been updated!") - }, error => { - if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){ - return; + .subscribe({ + next: async (response: CredentialRo) => { + this.notifyAccessTokenUpdated(response) + this.alertService.success(await lastValueFrom(this.translateService.get("user.access.tokens.success.updated", {credentialName: response.name}))) + }, error: (error: any) => { + if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) { + return; + } + this.alertService.error(error.error?.errorDescription) } - this.alertService.error(error.error?.errorDescription) }); } @@ -125,14 +135,16 @@ export class UserService { this.http.post<CredentialRo>(SmpConstants.REST_PUBLIC_USER_MANAGE_CERTIFICATE_CREDENTIAL .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, user.userId) .replace(SmpConstants.PATH_PARAM_ENC_CREDENTIAL_ID, credential.credentialId), credential) - .subscribe((response: CredentialRo) => { - this.notifyCertificateUpdated(response) - this.alertService.success("Certificate ["+response.name+"] has been updated!") - }, error => { - if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){ - return; + .subscribe({ + next: async (response: CredentialRo) => { + this.notifyCertificateUpdated(response) + this.alertService.success(await lastValueFrom(this.translateService.get("user.certificate.success.updated", {credentialName: response.name}))) + }, error: (error: any) => { + if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) { + return; + } + this.alertService.error(error.error?.errorDescription) } - this.alertService.error(error.error?.errorDescription) }); } @@ -144,14 +156,16 @@ export class UserService { this.http.delete<CredentialRo>(SmpConstants.REST_PUBLIC_USER_MANAGE_CERTIFICATE_CREDENTIAL .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, user.userId) .replace(SmpConstants.PATH_PARAM_ENC_CREDENTIAL_ID, credential.credentialId)) - .subscribe((response: CredentialRo) => { - this.notifyCertificateUpdated(response) - this.alertService.success("Certificate ["+response.name+"] has been deleted!") - }, error => { - if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){ - return; + .subscribe({ + next: async (response: CredentialRo) => { + this.notifyCertificateUpdated(response) + this.alertService.success(await lastValueFrom(this.translateService.get("user.certificate.success.deleted", {credentialName: response.name}))) + }, error: (error: any) => { + if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) { + return; + } + this.alertService.error(error.error?.errorDescription) } - this.alertService.error(error.error?.errorDescription) }); } @@ -174,15 +188,16 @@ export class UserService { this.http.put<CredentialRo>(SmpConstants.REST_PUBLIC_USER_MANAGE_CERTIFICATE_CREDENTIAL .replace(SmpConstants.PATH_PARAM_ENC_USER_ID, user.userId) .replace(SmpConstants.PATH_PARAM_ENC_CREDENTIAL_ID, credential.credentialId), credential) - .subscribe((response: CredentialRo) => { - this.notifyCertificateUpdated(response) - this.alertService.success("Certificate ["+response.name+"] has been successfully uploaded!") - }, error => { - if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){ - return; + .subscribe({ + next: async (response: CredentialRo) => { + this.notifyCertificateUpdated(response) + this.alertService.success(await lastValueFrom(this.translateService.get("user.certificate.success.uploaded", {credentialName: response.name}))) + }, error: (error: any) => { + if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) { + return; + } + this.alertService.error(error.error?.errorDescription) } - this.alertService.error(error.error?.errorDescription) - }); } @@ -199,7 +214,7 @@ export class UserService { .subscribe((response: CredentialRo[]) => { this.notifyCertificatesUpdated(response) }, error => { - if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)){ + if (this.httpErrorHandlerService.logoutOnInvalidSessionError(error)) { return; } this.alertService.error(error.error?.errorDescription) diff --git a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/_access-token-panel.component-theme.scss b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/_access-token-panel.component-theme.scss index e05994ebd40993c1d0ad1ab80963d366e047da20..28fabcf74d1072be6c1b1ea487ed583b4c350ae3 100644 --- a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/_access-token-panel.component-theme.scss +++ b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/_access-token-panel.component-theme.scss @@ -1,9 +1,7 @@ @use '../../../../_smp-theme-helper' as smp; @mixin set-component-colors($theme) { - .access-token:hover { - background-color: smp.get-theme-color($theme, primary, 0.2); - } + } diff --git a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.html b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.html index 74291e1d520577910a1e16dd5af2d0a96b40a8dc..db7be175adc386036673947db9c8ad741ff0211b 100644 --- a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.html +++ b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.html @@ -1,27 +1,44 @@ <mat-expansion-panel [expanded]="_expanded"> - <mat-expansion-panel-header style="height: 72px"> - <div style="display: flex; flex-direction: column;width: 100%; padding-right: 10px"> - <smp-warning-panel *ngIf="!!_credential?.expired;" class="smp-certificate-warning-panel" + <mat-expansion-panel-header style="height: 95px"> + <div + style="display: flex; flex-direction: column;width: 100%;margin-right: 10px;"> + <smp-warning-panel *ngIf="!!_credential?.expired;" + class="smp-certificate-warning-panel" [padding]="false" icon="error" label="{{ 'access.token.panel.label.token.expired' | translate }}"> </smp-warning-panel> - <div style="display: flex; flex-direction: row; justify-content: space-between; gap: 3px; padding-left: 5px;"> - <input matInput style="flex-grow: 1; padding: 5px 0" - [value]="credential?.name" - [disabled]="!credential?.active" - maxlength="255" readonly> - <div style="display: inline"> + <div + style="display: flex; flex-direction: row; justify-content: space-between; gap: 3px; padding-left: 5px;"> + + <mat-form-field style="flex-grow: 1"> + <mat-label>{{ "access.token.panel.label.name" | translate }}</mat-label> + <input matInput + [value]="_credential.name" + maxlength="255" disabled> + <mat-hint + style="display: flex; flex-direction: row; font-size: 0.8em;overflow: hidden"> + <span + *ngIf="credentialForm.controls['activeFrom'].value;else elseNoDate">{{ credentialForm.controls["activeFrom"].value | date: dateFormat }}</span> + - + <span + *ngIf="credentialForm.controls['expireOn'].value;else elseNoDate">{{ credentialForm.controls["expireOn"].value | date: dateFormat }}</span>; + <span + style="overflow: hidden">{{ credentialForm.controls["description"].value }}</span> + <ng-template #elseNoDate><span> / </span></ng-template> + </mat-hint> + </mat-form-field> + <div style="display: inline;display: flex;flex-direction: column"> <button id="deleteButton" mat-raised-button - (click)="onDeleteButtonClicked()" - color="primary" > + (click)="onDeleteButtonClicked($event)" + color="primary"> <mat-icon>delete</mat-icon> <span>{{ "access.token.panel.button.delete" | translate }}</span> </button> <button id="saveButton" mat-raised-button - (click)="onSaveButtonClicked()" + (click)="onSaveButtonClicked($event)" color="primary" - [disabled]="!submitButtonEnabled" > + [disabled]="!submitButtonEnabled"> <mat-icon>save</mat-icon> <span>{{ "access.token.panel.button.save" | translate }}</span> </button> @@ -29,7 +46,7 @@ </div> </div> </mat-expansion-panel-header> - <div class="panel smp-data-panel" [formGroup]="credentialForm" (ngSubmit)="onSaveButtonClicked()"> + <div class="smp-data-panel" [formGroup]="credentialForm"> <mat-form-field style="width: 100%"> <mat-label>{{ "access.token.panel.label.description" | translate }}</mat-label> <input matInput @@ -38,20 +55,30 @@ </mat-form-field> <div style="display: flex;flex-flow: row wrap;"> - <mat-checkbox formControlName="active" style="align-self: center; padding-bottom: 1em;padding-right: 2em"> + <mat-checkbox formControlName="active" + style="align-self: center; padding-bottom: 1em;padding-right: 2em"> {{ "access.token.panel.label.active" | translate }} </mat-checkbox> <mat-form-field appearance="fill" style="flex-grow: 1"> <mat-label>{{ "access.token.panel.label.validity.dates" | translate }}</mat-label> - <mat-date-range-input [rangePicker]="picker" [min]="minSelectableDate" > - <input matStartDate formControlName="activeFrom" placeholder="{{ 'access.token.panel.placeholder.end.date' | translate }}"> - <input matEndDate formControlName="expireOn" placeholder="{{ 'access.token.panel.placeholder.end.date' | translate }}"> + <mat-date-range-input [rangePicker]="picker" [min]="minSelectableDate"> + <input matStartDate formControlName="activeFrom" + placeholder="{{ 'access.token.panel.placeholder.end.date' | translate }}" + required> + <input matEndDate formControlName="expireOn" + placeholder="{{ 'access.token.panel.placeholder.end.date' | translate }}" + required> </mat-date-range-input> - <mat-datepicker-toggle matIconSuffix [for]="picker"></mat-datepicker-toggle> + <mat-datepicker-toggle matIconSuffix + [for]="picker"></mat-datepicker-toggle> <mat-date-range-picker #picker></mat-date-range-picker> - <smp-field-error *ngIf="credentialForm.controls.activeFrom.hasError('matStartDateInvalid')">{{ "access.token.panel.error.invalid.start.date" | translate }}</smp-field-error > - <smp-field-error *ngIf="credentialForm.controls.expireOn.hasError('matEndDateInvalid')">{{ "access.token.panel.error.invalid.end.date" | translate }}</smp-field-error > + <smp-field-error + *ngIf="credentialForm.controls.activeFrom.hasError('matStartDateInvalid') || credentialForm.controls.activeFrom.hasError('required')">{{ "access.token.panel.error.invalid.start.date" | translate }} + </smp-field-error> + <smp-field-error + *ngIf="credentialForm.controls.expireOn.hasError('matEndDateInvalid') || credentialForm.controls.expireOn.hasError('required')">{{ "access.token.panel.error.invalid.end.date" | translate }} + </smp-field-error> </mat-form-field> </div> <div style="display: flex;flex-flow: row;"> @@ -59,26 +86,33 @@ <mat-label>{{ "access.token.panel.label.login.failed.attempts" | translate }}</mat-label> <input matInput [value]="sequentialLoginFailureCount" - id="sequentialTokenLoginFailureCount_id" maxlength="255" disabled readonly> + id="sequentialTokenLoginFailureCount_id" maxlength="255" disabled + readonly> </mat-form-field> - <mat-form-field style="flex-grow:2 " floatLabel="always"> + <mat-form-field style="flex-grow:2 " floatLabel="always"> <mat-label>{{ "access.token.panel.label.login.last.failed.attempt" | translate }}</mat-label> - <input id="LastFailedAttempt_id" matInput [ngxMatDatetimePicker]="LastFailedAttemptPicker" + <input id="LastFailedAttempt_id" matInput + [ngxMatDatetimePicker]="LastFailedAttemptPicker" [value]="lastFailedLoginAttempt" placeholder="---" readonly> - <mat-datepicker-toggle matSuffix [for]="LastFailedAttemptPicker" style="visibility: hidden"></mat-datepicker-toggle> - <ngx-mat-datetime-picker #LastFailedAttemptPicker [showSpinners]="true" [showSeconds]="false" + <mat-datepicker-toggle matSuffix [for]="LastFailedAttemptPicker" + style="visibility: hidden"></mat-datepicker-toggle> + <ngx-mat-datetime-picker #LastFailedAttemptPicker [showSpinners]="true" + [showSeconds]="false" [hideTime]="false"></ngx-mat-datetime-picker> </mat-form-field> - <mat-form-field style="flex-grow: 2" floatLabel="always"> + <mat-form-field style="flex-grow: 2" floatLabel="always"> <mat-label>{{ "access.token.panel.label.suspended.until" | translate }}</mat-label> - <input id="SuspendedUtil_id" matInput [ngxMatDatetimePicker]="suspendedUtilPicker" + <input id="SuspendedUtil_id" matInput + [ngxMatDatetimePicker]="suspendedUtilPicker" [value]="suspendedUtil" placeholder="---" readonly> - <mat-datepicker-toggle matSuffix [for]="suspendedUtilPicker" style="visibility: hidden"></mat-datepicker-toggle> - <ngx-mat-datetime-picker #suspendedUtilPicker [showSpinners]="true" [showSeconds]="false" + <mat-datepicker-toggle matSuffix [for]="suspendedUtilPicker" + style="visibility: hidden"></mat-datepicker-toggle> + <ngx-mat-datetime-picker #suspendedUtilPicker [showSpinners]="true" + [showSeconds]="false" [hideTime]="false"></ngx-mat-datetime-picker> </mat-form-field> diff --git a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.scss b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.scss index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..2ff5c115ed308f4c86a6cb9b801a6c949555e1d5 100644 --- a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.scss +++ b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.scss @@ -0,0 +1,5 @@ +.access-token-panel { + + + border-bottom: 1px solid #e0e0e0; +} diff --git a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.ts b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.ts index 9a6e22e34398d8872ad065e4f673ce9c63687648..f290f68eabf2061190e857918fcd1d3271cc33e5 100644 --- a/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.ts +++ b/smp-angular/src/app/user-settings/user-access-tokens/access-token-panel/access-token-panel.component.ts @@ -1,7 +1,31 @@ import {Component, EventEmitter, Input, Output} from '@angular/core'; -import {FormBuilder, FormControl, FormGroup} from "@angular/forms"; +import { + AbstractControl, + FormBuilder, + FormControl, + FormGroup, ValidatorFn +} from "@angular/forms"; import {CredentialRo} from "../../../security/credential.model"; import {BeforeLeaveGuard} from "../../../window/sidenav/navigation-on-leave-guard"; +import {GlobalLookups} from "../../../common/global-lookups"; + + +export function notAfterCurrentDateValidator(): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } | null => { + const date = control.value; + const forbidden = date && date > Date.now(); + + return forbidden ? { 'matStartDateInvalid': { value: control.value } } : null; + }; +} + +export function notBeforeCurrentDateValidator(): ValidatorFn { + return (control: AbstractControl): { [key: string]: any } | null => { + const date = control.value; + const forbidden = date && date < Date.now(); + return forbidden ? { 'matEndDateInvalid': { value: control.value } } : null; + }; +} @Component({ @@ -11,24 +35,27 @@ import {BeforeLeaveGuard} from "../../../window/sidenav/navigation-on-leave-guar }) export class AccessTokenPanelComponent implements BeforeLeaveGuard { - @Output() minSelectableDate: Date = new Date(); + @Output() minSelectableDate: Date = null; @Output() onDeleteEvent: EventEmitter<CredentialRo> = new EventEmitter(); @Output() onSaveEvent: EventEmitter<CredentialRo> = new EventEmitter(); - dateFormat: string = 'yyyy-MM-dd' - _credential: CredentialRo; credentialForm: FormGroup; _expanded: boolean = false; - constructor(private formBuilder: FormBuilder) { + + + constructor(private formBuilder: FormBuilder, + private globalLookups: GlobalLookups) { this.credentialForm = formBuilder.group({ // common values + 'name': new FormControl({value: '', disabled: true}), 'active': new FormControl({value: '', disabled: false}), 'description': new FormControl({value: '', disabled: false}), - 'activeFrom': new FormControl({value: '', disabled: false}), - 'expireOn': new FormControl({value: '', disabled: false}) + 'activeFrom': new FormControl({value: '', disabled: false}, [notAfterCurrentDateValidator()]), + 'expireOn': new FormControl({value: '', disabled: false}, [notBeforeCurrentDateValidator()]) }); + } get credential(): CredentialRo { @@ -38,11 +65,13 @@ export class AccessTokenPanelComponent implements BeforeLeaveGuard { @Input() set credential(value: CredentialRo) { this._credential = value; if (this._credential) { + this.credentialForm.controls['name'].setValue(this._credential.name); this.credentialForm.controls['active'].setValue(this._credential.active); this.credentialForm.controls['description'].setValue(this._credential.description); this.credentialForm.controls['activeFrom'].setValue(this._credential.activeFrom); this.credentialForm.controls['expireOn'].setValue(this._credential.expireOn); } else { + this.credentialForm.controls['name'].setValue(null); this.credentialForm.controls['active'].setValue(null); this.credentialForm.controls['description'].setValue(null); this.credentialForm.controls['activeFrom'].setValue(null); @@ -53,16 +82,30 @@ export class AccessTokenPanelComponent implements BeforeLeaveGuard { this.credentialForm.markAsPristine(); } - onDeleteButtonClicked() { + onDeleteButtonClicked(event: MouseEvent) { this.onDeleteEvent.emit(this.credential); + event?.stopPropagation(); } - onSaveButtonClicked() { + onSaveButtonClicked(event: MouseEvent) { this._credential.active = this.credentialForm.controls['active'].value this._credential.description = this.credentialForm.controls['description'].value - this._credential.activeFrom = this.credentialForm.controls['activeFrom'].value - this._credential.expireOn = this.credentialForm.controls['expireOn'].value + let dateFrom = this.credentialForm.controls['activeFrom'].value; + if (dateFrom) { + // make date mutable and the modification + dateFrom = new Date(dateFrom); + dateFrom.setHours(0, 0, 0, 0); + } + this._credential.activeFrom = dateFrom + let dateTo = this.credentialForm.controls['expireOn'].value; + if (dateTo) { + // make date mutable and the modification + dateTo = new Date(dateTo); + dateTo.setHours(0, 0, 0, 0); + } + this._credential.expireOn = dateTo + event?.stopPropagation(); this.onSaveEvent.emit(this._credential); } @@ -71,7 +114,7 @@ export class AccessTokenPanelComponent implements BeforeLeaveGuard { } get sequentialLoginFailureCount(): string { - return this._credential && this._credential.sequentialLoginFailureCount ? + return this._credential?.sequentialLoginFailureCount ? this._credential.sequentialLoginFailureCount + "" : "0"; } @@ -87,4 +130,7 @@ export class AccessTokenPanelComponent implements BeforeLeaveGuard { return this.credentialForm.dirty; } + get dateFormat(): string { + return this.globalLookups.getDateFormat(); + } } diff --git a/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.html b/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.html index a6b7f96f9d5f2741d51bd71405a87e1c6038d297..535aa91f957ca84fb7d52df7937a5e488ccf18c5 100644 --- a/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.html +++ b/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.html @@ -3,33 +3,43 @@ text="{{ 'user.access.tokens.text' | translate }}" [labelColumnContent]="commonToolbar"> - <table mat-table id="user-access-token-table" [dataSource]="dataSource" class="panel smp-data-panel" > + <table mat-table id="user-access-token-table" [dataSource]="dataSource" + class="panel smp-data-panel"> <ng-container matColumnDef="accessTokens"> - <th mat-header-cell *matHeaderCellDef>{{ "user.access.tokens.label.access.tokens" | translate }}</th> + <th mat-header-cell + *matHeaderCellDef>{{ "user.access.tokens.label.access.tokens" | translate }} + </th> <td mat-cell *matCellDef="let token" [ngClass]="{'datatable-row-error': token.invalid}" - [matTooltip]="token.name"> - <access-token-panel (onDeleteEvent)="onDeleteItemClicked(token)" + [matTooltip]="token.name" + class="access-token-panel"> + <access-token-panel class="access-token-panel" + (onDeleteEvent)="onDeleteItemClicked(token)" (onSaveEvent)="onSaveItemClicked(token)" [credential]="token"></access-token-panel> </td> - <tr mat-header-row class="user-access-token-table-header" *matHeaderRowDef="displayedColumns"></tr> - <tr mat-row class="user-access-token-table-data" *matRowDef="let myRowData; columns: displayedColumns"></tr> + <tr mat-header-row class="user-access-token-table-header" + *matHeaderRowDef="displayedColumns"></tr> + <tr mat-row class="user-access-token-table-data" + *matRowDef="let myRowData; columns: displayedColumns"></tr> </ng-container> </table> <mat-paginator class="mat-elevation-z2" id="tokens-paginator" [hidePageSize]="true" - [pageSize]="5" attr.aria-label="{{ 'user.access.tokens.label.select.page' | translate }}"></mat-paginator> + [pageSize]="5" + attr.aria-label="{{ 'user.access.tokens.label.select.page' | translate }}"></mat-paginator> </data-panel> </div> <ng-template #commonToolbar> - <button id="createAccessTokenButton" mat-raised-button color="primary" matTooltip="{{ 'user.access.tokens.tooltip.create' | translate }}" style="margin: 2em " - (click)="createNewAccessToken()"> + <button id="createAccessTokenButton" mat-raised-button color="primary" + matTooltip="{{ 'user.access.tokens.tooltip.create' | translate }}" + style="margin: 2em " + (click)="createNewAccessToken()"> <mat-icon>key</mat-icon> <span>{{ "user.access.tokens.button.create" | translate }}</span> </button> diff --git a/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.scss b/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.scss index bde62fecdac7bff9df60de91601e44f25d8564b3..1766781f6f50b737e002940eddf6ce12e69cc3d3 100644 --- a/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.scss +++ b/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.scss @@ -17,6 +17,7 @@ #user-access-token-table { padding: 0; border: none; + background-color: transparent !important; } .user-access-token-table-header { @@ -25,4 +26,5 @@ .user-access-token-table-data td { padding: 0; + background-color: transparent !important; } diff --git a/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.ts b/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.ts index 1c1416474551825a2ef6e16ac17479ae2dd27e3d..2be5a50b57e59d1ca2e2fae44879f3a73460955a 100644 --- a/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.ts +++ b/smp-angular/src/app/user-settings/user-access-tokens/user-access-tokens.component.ts @@ -68,9 +68,12 @@ export class UserAccessTokensComponent implements AfterViewInit, BeforeLeaveGuar userAccessToken]; } + // show current page after update if possible or previous page + let pageIndex = Math.min(this.paginator.pageIndex, + Math.floor(this.accessTokens.length / this.paginator.pageSize)); + // set the data source this.dataSource.data = this.accessTokens; - // show the last page - this.paginator.lastPage(); + this.paginator.pageIndex = pageIndex; } public trackListItem(index: number, credential: CredentialRo) { diff --git a/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.html b/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.html index 3a97f9e57814c31ed6fbbe50eaa50d704d38c8b3..06ca05efe59ada95c938a395a41aaa14f8f668ff 100644 --- a/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.html +++ b/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.html @@ -1,28 +1,41 @@ -<mat-expansion-panel [expanded]="_expanded" [formGroup]="credentialForm" (ngSubmit)="onSaveButtonClicked()"> - <mat-expansion-panel-header style="height: 72px"> - <div style="display: flex; flex-direction: column;width: 100%; padding-right: 10px"> - <smp-warning-panel *ngIf="_credential.certificate?.invalid;" class="smp-certificate-warning-panel" +<mat-expansion-panel [expanded]="_expanded" [formGroup]="credentialForm"> + <mat-expansion-panel-header style="height: 95px"> + <div + style="display: flex; flex-direction: column;width: 100%; padding-right: 10px"> + <smp-warning-panel *ngIf="_credential.certificate?.invalid;" + class="smp-certificate-warning-panel" [padding]="false" icon="error" label="{{ 'user.certificate.panel.label.invalid.certificate' | translate: { reason: _credential.certificate.invalidReason} }}"> </smp-warning-panel> - <div style="display: flex;flex-flow: row; align-items: center; width: 100%"> + <div + style="display: flex;flex-flow: row; align-items: center; width: 100%"> - <input matInput style="flex-grow: 1; padding: 5px 0" [matTooltip]="credential?.name" - [value]="credential?.name" - [disabled]="!credential?.active" - maxlength="255" readonly> + <mat-form-field style="flex-grow: 1"> + <mat-label>{{ "user.certificate.panel.label.certificate.id" | translate }}</mat-label> + <input matInput + [value]="_credential.name" + maxlength="255" disabled> + <mat-hint + style="display: flex; flex-direction: row; font-size: 0.8em;overflow: hidden"> + <span *ngIf="credentialForm.controls['activeFrom'].value;else elseNoDate ">{{ credentialForm.controls["activeFrom"].value | date: dateFormat }}</span> + - + <span *ngIf="credentialForm.controls['expireOn'].value;else elseNoDate">{{ credentialForm.controls["expireOn"].value | date: dateFormat }}</span>; + <span style="overflow: hidden">{{ credentialForm.controls["description"].value }}</span> + </mat-hint> + <ng-template #elseNoDate><span> / </span></ng-template> + </mat-form-field> <div - style="display: flex; flex-direction: row; justify-content: space-between; gap: 3px; padding-left: 5px;"> + style="display: flex; flex-direction: column; justify-content: space-between; padding-left: 5px;"> <button id="deleteButton" mat-raised-button - (click)="onDeleteButtonClicked()" + (click)="onDeleteButtonClicked($event)" color="primary"> <mat-icon>delete</mat-icon> <span>{{ "user.certificate.panel.button.delete" | translate }}</span> </button> <button id="saveButton" mat-raised-button - (click)="onSaveButtonClicked()" + (click)="onSaveButtonClicked($event)" color="primary" [disabled]="!submitButtonEnabled"> <mat-icon>save</mat-icon> @@ -63,13 +76,17 @@ <mat-form-field appearance="fill" style="flex-grow: 1"> <mat-label>{{ "user.certificate.panel.label.validity.dates" | translate }}</mat-label> <mat-date-range-input> - <input matStartDate formControlName="activeFrom" placeholder="{{ 'user.certificate.panel.placeholder.start.date' | translate }}"> - <input matEndDate formControlName="expireOn" placeholder="{{ 'user.certificate.panel.placeholder.end.date' | translate }}"> + <input matStartDate formControlName="activeFrom" + placeholder="{{ 'user.certificate.panel.placeholder.start.date' | translate }}"> + <input matEndDate formControlName="expireOn" + placeholder="{{ 'user.certificate.panel.placeholder.end.date' | translate }}"> </mat-date-range-input> - <smp-field-error *ngIf="credentialForm.controls.activeFrom.hasError('matStartDateInvalid')"> + <smp-field-error + *ngIf="credentialForm.controls.activeFrom.hasError('matStartDateInvalid')"> {{ "user.certificate.panel.label.invalid.start.date" | translate }} </smp-field-error> - <smp-field-error *ngIf="credentialForm.controls.expireOn.hasError('matEndDateInvalid')"> + <smp-field-error + *ngIf="credentialForm.controls.expireOn.hasError('matEndDateInvalid')"> {{ "user.certificate.panel.label.invalid.end.date" | translate }} </smp-field-error> </mat-form-field> diff --git a/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.ts b/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.ts index 232de7158629e9b9cd2bfb398168c62d4581b229..3a772a9a4f3241f23c44292f370a90344510b2bd 100644 --- a/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.ts +++ b/smp-angular/src/app/user-settings/user-certificates/user-certificate-panel/user-certificate-panel.component.ts @@ -2,6 +2,7 @@ import {Component, EventEmitter, Input, Output} from '@angular/core'; import {FormBuilder, FormControl, FormGroup} from "@angular/forms"; import {CredentialRo} from "../../../security/credential.model"; import {BeforeLeaveGuard} from "../../../window/sidenav/navigation-on-leave-guard"; +import {GlobalLookups} from "../../../common/global-lookups"; @Component({ @@ -15,13 +16,12 @@ export class UserCertificatePanelComponent implements BeforeLeaveGuard { @Output() onShowCertificate: EventEmitter<CredentialRo> = new EventEmitter(); - dateFormat: string = 'yyyy-MM-dd' - _credential: CredentialRo; _expanded: boolean = false; credentialForm: FormGroup; - constructor(private formBuilder: FormBuilder) { + constructor(private formBuilder: FormBuilder, + private globalLookups: GlobalLookups) { this.credentialForm = formBuilder.group({ // common values 'active': new FormControl({value: '', disabled: false}), @@ -59,13 +59,14 @@ export class UserCertificatePanelComponent implements BeforeLeaveGuard { this.credentialForm.markAsPristine(); } - onDeleteButtonClicked() { - + onDeleteButtonClicked(event: MouseEvent) { this.onDeleteEvent.emit(this.credential); + event?.stopPropagation(); } - onSaveButtonClicked() { + onSaveButtonClicked(event: MouseEvent) { this.onSaveEvent.emit(this.credential); + event?.stopPropagation(); } onShowCertificateButtonClicked(){ @@ -95,4 +96,8 @@ export class UserCertificatePanelComponent implements BeforeLeaveGuard { return this.credentialForm.dirty; } + get dateFormat(): string { + return this.globalLookups.getDateFormat(); + } + } diff --git a/smp-angular/src/app/user-settings/user-certificates/user-certificates.component.ts b/smp-angular/src/app/user-settings/user-certificates/user-certificates.component.ts index 694b7c37004193bf51430878e777a3e6aa1dbd6d..c375ab987e23268259a5374f34e7da77c38191fa 100644 --- a/smp-angular/src/app/user-settings/user-certificates/user-certificates.component.ts +++ b/smp-angular/src/app/user-settings/user-certificates/user-certificates.component.ts @@ -73,8 +73,13 @@ export class UserCertificatesComponent implements AfterViewInit, BeforeLeaveGuar certificate]; } + // show current page after update if possible or previous page + let pageIndex = Math.min(this.paginator.pageIndex, + Math.floor(this.certificates.length / this.paginator.pageSize)); + // set data this.dataSource.data = this.certificates; - // show the last page + // set page + this.paginator.pageIndex = pageIndex; this.paginator.lastPage(); } diff --git a/smp-angular/src/assets/i18n/en.json b/smp-angular/src/assets/i18n/en.json index 49ead257d9fc50a3042f21002ca6c0423df9a85e..cf3fc495fde3ef289162c6cb85c9a0bd03d5c199 100644 --- a/smp-angular/src/assets/i18n/en.json +++ b/smp-angular/src/assets/i18n/en.json @@ -812,6 +812,7 @@ "access.token.panel.button.save": "Save", "access.token.panel.error.invalid.end.date": "Invalid expire on date", "access.token.panel.error.invalid.start.date": "Invalid active from date", + "access.token.panel.label.name": "Name", "access.token.panel.label.active": "Active", "access.token.panel.label.description": "Description", "access.token.panel.label.login.failed.attempts": "Seq. failed attempts", @@ -833,6 +834,9 @@ "user.access.tokens.update.confirmation.dialog.description": "Action will update access token: \"{{credentialName}}\"!<br /><br />Do you wish to continue?", "user.access.tokens.update.confirmation.dialog.title": "Update Access token", "user.access.tokens.tooltip.create": "Create new Access token", + "user.access.tokens.success.deleted": "Access token \"{{credentialName}}\" has been deleted!", + "user.access.tokens.success.updated": "Access token \"{{credentialName}}\" has been updated!", + "user.certificate.panel.button.delete": "Delete", "user.certificate.panel.button.show.details": "Show Details", @@ -846,6 +850,9 @@ "user.certificate.panel.label.validity.dates": "Validity period of the certificate", "user.certificate.panel.placeholder.end.date": "End date", "user.certificate.panel.placeholder.start.date": "Start date", + "user.certificate.success.deleted": "Certificate \"{{credentialName}}\" has been deleted!", + "user.certificate.success.updated": "Certificate \"{{credentialName}}\" has been updated!", + "user.certificate.success.uploaded": "Certificate \"{{credentialName}}\" has been uploaded!", "user.certificates.button.import": "Import new certificate", "user.certificates.label.user.certificate": "User Certificates", diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/DatabaseProperties.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/DatabaseProperties.java index 04787384baa36c4d5e7d775db41ade0bf62d6e47..999c8349be552e15360be45f02736f988d2ccc1e 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/DatabaseProperties.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/DatabaseProperties.java @@ -22,6 +22,7 @@ import eu.europa.ec.edelivery.smp.data.model.DBConfiguration; import eu.europa.ec.edelivery.smp.logging.SMPLogger; import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory; import eu.europa.ec.edelivery.smp.utils.PropertyUtils; +import org.slf4j.event.Level; import javax.persistence.EntityManager; import javax.persistence.Transient; @@ -40,8 +41,6 @@ import static org.apache.commons.lang3.StringUtils.trim; * @since 4.2 */ public class DatabaseProperties extends Properties { - @Transient - private static final SMPLogger LOG = SMPLoggerFactory.getLogger(DatabaseProperties.class); private OffsetDateTime lastUpdate; @@ -54,7 +53,7 @@ public class DatabaseProperties extends Properties { String prop =trim(dc.getProperty()); String value =trim(dc.getValue()); setProperty(prop, value); - LOG.info("Database property: [{}] value: [{}]", prop,PropertyUtils.getMaskedData(prop, value) ); + PropertyUtils.printProperty(prop, value, Level.INFO); } lastUpdate = (lastUpdate == null || lastUpdate.isBefore(dc.getLastUpdatedOn())) ? dc.getLastUpdatedOn() : lastUpdate; } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPDatabaseConfig.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPDatabaseConfig.java index 68e41fb0a1dc7245a6ef990df2a6408d1f3b9171..f2196507272c65ada79915198bfd368271f83da6 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPDatabaseConfig.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPDatabaseConfig.java @@ -55,7 +55,7 @@ public class SMPDatabaseConfig { @Bean(name = "smpDataSource") @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON) public DataSource getDataSource() { - LOG.info("Create DomiSMP datasource"); + LOG.trace("Create DomiSMP datasource"); return databaseConnectionBeanCreator.getDataSource(); } @@ -63,7 +63,7 @@ public class SMPDatabaseConfig { @Bean(name = "smpEntityManagerFactory") @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON) public LocalContainerEntityManagerFactoryBean smpEntityManagerFactory(@Qualifier("smpDataSource") DataSource dataSource, JpaVendorAdapter jpaVendorAdapter) { - LOG.info("Create DomiSMP EntityManagerFactory"); + LOG.trace("Create DomiSMP EntityManagerFactory"); return databaseConnectionBeanCreator.smpEntityManagerFactory(dataSource, jpaVendorAdapter); } @@ -71,7 +71,7 @@ public class SMPDatabaseConfig { @Bean(name = "transactionManager") @Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON) public PlatformTransactionManager smpTransactionManager(@Qualifier("smpEntityManagerFactory") EntityManagerFactory emf) { - LOG.info("Create DomiSMP TransactionManager"); + LOG.trace("Create DomiSMP TransactionManager"); return databaseConnectionBeanCreator.getSmpTransactionManager(emf); } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPEnvironmentProperties.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPEnvironmentProperties.java index 08872099d680281f7aa08fed1a9bb48684a3736e..a37161aafcd2cfc07bd77bbb0a2dd2ec6b18ac6a 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPEnvironmentProperties.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/SMPEnvironmentProperties.java @@ -43,6 +43,7 @@ import java.util.Properties; import static eu.europa.ec.edelivery.smp.config.enums.SMPEnvPropertyEnum.*; import static eu.europa.ec.edelivery.smp.config.enums.SMPPropertyEnum.CLIENT_CERT_HEADER_ENABLED_DEPRECATED; import static eu.europa.ec.edelivery.smp.config.enums.SMPPropertyEnum.EXTERNAL_TLS_AUTHENTICATION_CLIENT_CERT_HEADER_ENABLED; +import static eu.europa.ec.edelivery.smp.utils.PropertyUtils.printProperties; /** * DomiSMP environment property initialization. @@ -102,7 +103,7 @@ public class SMPEnvironmentProperties implements DatabaseConnectionProperties { * Initialize the default properties in to the cache for faster lookup of the default values */ private void init() { - LOG.debug("Initialize DomiSMP environment properties"); + LOG.info("Initialize DomiSMP environment properties"); classPathEnvFileProperties = readProperties(CLASSPATH_PROPERTIES, true); if (classPathEnvFileProperties != null) { LOG.debug("------ Print classPathEnvFileProperties ------"); @@ -114,7 +115,7 @@ public class SMPEnvironmentProperties implements DatabaseConnectionProperties { extInitFileProperties = readProperties(extInitPropFilePath, false); if (extInitFileProperties != null) { LOG.debug("------ Print classPathEnvFileProperties ------"); - printProperties(extInitFileProperties, Level.INFO); + printProperties(extInitFileProperties, Level.DEBUG); } // get init file property @@ -128,45 +129,17 @@ public class SMPEnvironmentProperties implements DatabaseConnectionProperties { extEnvFileProperties = readProperties(extAppFilePath, false); if (extInitFileProperties != null) { LOG.debug("------ Print extInitFileProperties ------"); - printProperties(extInitFileProperties, Level.INFO); + printProperties(extInitFileProperties, Level.DEBUG); } // update log configuration updateLogConfiguration(getEnvPropertyValue(LOG_FOLDER), getEnvPropertyValue(LOG_CONFIGURATION_FILE)); - } - private void printProperties(Properties properties, Level loggingLevel) { - if (properties != null) { - LOG.debug("------ Print properties ------"); - properties.entrySet().stream().forEach(e -> - printProperty((String) e.getKey(), (String) e.getValue(), loggingLevel) - ); - } - } - - private void printProperty(String key, String value, Level loggingLevel) { - String logValue = "\t[" + key + "] --> [" + (key.contains("passw") ? "*******" : value) + "]"; - switch (loggingLevel) { - case TRACE: - LOG.trace(logValue); - break; - case DEBUG: - LOG.debug(logValue); - break; - case INFO: - LOG.info(logValue); - break; - case WARN: - LOG.warn(logValue); - break; - case ERROR: - LOG.error(logValue); - break; - default: - LOG.debug(logValue); - } + LOG.info("DomiSMP environment properties initialized!"); + Properties properties = getEnvProperties(); + printProperties(properties, Level.INFO); } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/PropertyUtils.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/PropertyUtils.java index d8ca9d339538b3d0ceb5baae69bf5c5b965e678a..020e8ab6d9bb8a8d3d6845d9a351aeed5f6cd025 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/PropertyUtils.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/PropertyUtils.java @@ -27,7 +27,7 @@ import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.validator.routines.EmailValidator; -import org.apache.commons.validator.routines.UrlValidator; +import org.slf4j.event.Level; import org.springframework.scheduling.support.CronExpression; import java.io.File; @@ -35,6 +35,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; import java.util.Optional; +import java.util.Properties; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import java.util.stream.Collectors; @@ -196,8 +197,8 @@ public class PropertyUtils { if (propOpt.isPresent()) { return propOpt.get().isEncrypted() || property.toLowerCase().contains(".password.decrypted"); } - LOG.warn("Database property [{}] is not recognized by the SMP!", property); - return false; + LOG.debug("Database property [{}] is not recognized by the SMP. Basic mask rule applied for masking!", property); + return StringUtils.contains(property.toLowerCase(), "passw"); } /** @@ -214,4 +215,36 @@ public class PropertyUtils { public static String getMaskedData(String value) { return isNotBlank(value) ? MASKED_VALUE : "Null/Empty/Blank"; } + + public static void printProperties(Properties properties, Level loggingLevel) { + if (properties != null) { + LOG.debug("------ Print properties ------"); + properties.entrySet().stream().forEach(e -> + printProperty((String) e.getKey(), (String) e.getValue(), loggingLevel) + ); + } + } + + public static void printProperty(String key, String value, Level loggingLevel) { + String logValue = "\t[" + key + "] --> [" + getMaskedData(key, value) + "]"; + switch (loggingLevel) { + case TRACE: + LOG.trace(logValue); + break; + case DEBUG: + LOG.debug(logValue); + break; + case INFO: + LOG.info(logValue); + break; + case WARN: + LOG.warn(logValue); + break; + case ERROR: + LOG.error(logValue); + break; + default: + LOG.debug(logValue); + } + } }