diff --git a/.gitignore b/.gitignore index 072c92ae016cc899a2656a9d702df426f841b596..73684590bf1425b88b86403ade3e50158c30a665 100644 --- a/.gitignore +++ b/.gitignore @@ -1,32 +1,41 @@ -common/cipa-commons-busdox/target/ -common/cipa-edelivery-common/target/classes/eu/europa/ec/cipa/common/business/AbstractBusinessImpl.class -common/cipa-edelivery-common/target/classes/eu/europa/ec/cipa/common/exception/BusinessException.class -common/cipa-edelivery-common/target/classes/eu/europa/ec/cipa/common/logging/ILogEvent.class -common/cipa-edelivery-common/target/classes/eu/europa/ec/cipa/common/logging/impl/AbstractLoggerImpl.class -common/cipa-edelivery-common/target/classes/eu/europa/ec/cipa/common/logging/impl/LoggingServiceImpl.class -common/cipa-edelivery-common/target/ -common/cipa-peppol-types/target/ -sml/cipa-sml-client-library/target/ -sml/cipa-sml-server-library/target/ -sml/cipa-sml-webapp/target/ -smp/.idea/libraries/Maven__com_sun_jersey_jersey_client_1_17_1.xml -smp/.idea/libraries/ -smp/cipa-smp-client-library/target/ -smp/cipa-smp-full-webapp/target/ -smp/cipa-smp-readonly-webapp/target/ -smp/cipa-smp-server-library/target/ -smp/.idea/ -smp-api/target/ -smp-api/.idea/copyright/profiles_settings.xml -smp-api/.idea/libraries/Maven__junit_junit_4_12.xml -smp-api/.idea/libraries/ -smp-api/.idea/ -*.iml -addons/cipa-sml-util/.idea/ -addons/cipa-sml-util/target/ -addons/cipa-sml-migration/target/test-classes/global-truststore.jks -addons/cipa-sml-migration/target/classes/ -addons/cipa-sml-migration/target/ -addons/cipa-sml-migration/.idea/ +## Eclipse config files ## +.settings/ +.classpath +.project + +## PMD Eclipse plugin files ## +.pmd + +## Maven output folder ## +target/ + +#temporary output of the cargo plugin +cargo + +## Compiled java classes ## +*.class +*.jar +*.war +*.ear + +## generic files to ignore +*~ +*.lock +*.DS_Store +*.swp +*.out +*.tmp +*.log + +## Intellij IDEA files .idea/ -code-coverage \ No newline at end of file +*.iml +*.ipr +*.iws + +## Files generated by checksum plugin +*.sha256 + +## maven-shade-plugin generated files +dependency-reduced-pom.xml +/.idea/ diff --git a/pom.xml b/pom.xml index 870d255edd7e3b714f50fc79addee7a884a5406d..1d6b279c055c7b2ac6473b1546ce014ef4596ac5 100644 --- a/pom.xml +++ b/pom.xml @@ -66,6 +66,7 @@ <jackson.version>2.13.2</jackson.version> <javaee-api.version>7.0</javaee-api.version> <javax.annotation.version>1.3.2</javax.annotation.version> + <javax.mail.version>1.6.2</javax.mail.version> <jaxb.version>2.2.11</jaxb.version> <jaxb2-basics.version>1.11.1</jaxb2-basics.version> <jstl.version>1.2</jstl.version> @@ -89,8 +90,22 @@ <sonar.host.url>http://localhost:9000/sonar/</sonar.host.url> <sonar.language>java</sonar.language> + + <sonar.binaries>target/classes</sonar.binaries> + <sonar.coverage.jacoco.xmlReportPaths>${project.basedir}/target/site/jacoco/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths> <jacoco.maven.plugin.version>0.8.6</jacoco.maven.plugin.version> <surefire.maven.plugin.version>2.22.2</surefire.maven.plugin.version> + <sonar.exclusions> + **/target/**, + **/smp-angular/node_modules/**, + **/swagger*.js, + **/web.xml, + </sonar.exclusions> + <sonar.coverage.exclusions> + **/*Entity.java, + **/*RO.java, + **/*Exception.java, + </sonar.coverage.exclusions> <!-- latest version compatible with SonarQube 5.6 is: 3.3.0.603--> <sonar.maven.plugin.version>3.5.0.1254</sonar.maven.plugin.version> </properties> @@ -374,7 +389,7 @@ <dependency> <groupId>com.sun.mail</groupId> <artifactId>javax.mail</artifactId> - <version>1.6.2</version> + <version>${javax.mail.version}</version> </dependency> <dependency> <groupId>org.mockito</groupId> diff --git a/smp-angular/src/app/domain/domain-controller.ts b/smp-angular/src/app/domain/domain-controller.ts index aa87bf865a973b3b5004d7ba184cba861aca03f9..152f522e60e738a31ce32af4d530f93a02b53391 100644 --- a/smp-angular/src/app/domain/domain-controller.ts +++ b/smp-angular/src/app/domain/domain-controller.ts @@ -45,7 +45,7 @@ export class DomainController implements SearchTableController { signatureKeyAlias: '', status: SearchTableEntityStatus.NEW, smlRegistered: false, - smlBlueCoatAuth: false, + smlClientCertAuth: false, } } public dataSaved() { diff --git a/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.html b/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.html index d04934b9041353e2aba90ad033104843e7b328fa..1f30f9c8369a1dbfc7562ee63c3e51c18f7d12b8 100644 --- a/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.html +++ b/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.html @@ -102,13 +102,13 @@ <mat-form-field style="width:100%" matTooltip="SML Client-Cert http Header used for SML authentication. The header is generated from chosen SML ClientCert Alias"> <input matInput placeholder="SML ClientCert Header" name="Client certificate" id="smlClientHeader_id" - [value]="selectedSMLCert?.blueCoatHeader" maxlength="2000" readonly="true"> + [value]="selectedSMLCert?.clientCertHeader" maxlength="2000" readonly="true"> </mat-form-field> <mat-slide-toggle style="width:100%" - mat-no-ink class="mat-primary" [formControl]="domainForm.controls['smlBlueCoatAuth']" - id="smlBlueCoatAuth_id"> - Use blueCoat http header authentication. + mat-no-ink class="mat-primary" [formControl]="domainForm.controls['smlClientCertAuth']" + id="smlClientCertHeaderAuth_id"> + Use ClientCert http header authentication. </mat-slide-toggle> </fieldset> diff --git a/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.ts b/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.ts index c9ea404e8b3f8598848ae283f9a8eb9b01a53882..65bddca78be126634b59ea62147d6ed238d05f56 100644 --- a/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.ts +++ b/smp-angular/src/app/domain/domain-details-dialog/domain-details-dialog.component.ts @@ -77,7 +77,7 @@ export class DomainDetailsDialogComponent { 'signatureKeyAlias': new FormControl({value: ''}, null), 'smlRegistered': new FormControl({value: ''}, null), - 'smlBlueCoatAuth': new FormControl({value: ''}, null), + 'smlClientCertAuth': new FormControl({value: ''}, null), }); @@ -90,7 +90,7 @@ export class DomainDetailsDialogComponent { this.domainForm.controls['signatureKeyAlias'].setValue(this.current.signatureKeyAlias); this.domainForm.controls['smlRegistered'].setValue(this.current.smlRegistered); - this.domainForm.controls['smlBlueCoatAuth'].setValue(this.current.smlBlueCoatAuth); + this.domainForm.controls['smlClientCertAuth'].setValue(this.current.smlClientCertAuth); if (this.current.smlClientKeyAlias) { this.selectedSMLCert = this.lookups.cachedCertificateList.find(crt => crt.alias === this.current.smlClientKeyAlias); @@ -145,13 +145,13 @@ export class DomainDetailsDialogComponent { this.current.smlClientCertHeader = this.domainForm.value['smlClientCertHeader']; if (this.domainForm.value['smlClientKeyCertificate']) { this.current.smlClientKeyAlias = this.domainForm.value['smlClientKeyCertificate'].alias; - this.current.smlClientCertHeader = this.domainForm.value['smlClientKeyCertificate'].blueCoatHeader; + this.current.smlClientCertHeader = this.domainForm.value['smlClientKeyCertificate'].clientCertHeader; } else { this.current.smlClientKeyAlias = ''; this.current.smlClientCertHeader = ''; } this.current.signatureKeyAlias = this.domainForm.value['signatureKeyAlias']; - this.current.smlBlueCoatAuth = this.domainForm.value['smlBlueCoatAuth']; + this.current.smlClientCertAuth = this.domainForm.value['smlClientCertAuth']; return this.current; diff --git a/smp-angular/src/app/domain/domain-ro.model.ts b/smp-angular/src/app/domain/domain-ro.model.ts index f27b18f91a21a4c814aa8508a3b404444a35db41..3f8ce5e6b2933c2eacfb24d8f530748966d4e7ff 100644 --- a/smp-angular/src/app/domain/domain-ro.model.ts +++ b/smp-angular/src/app/domain/domain-ro.model.ts @@ -9,6 +9,6 @@ export interface DomainRo extends SearchTableEntity { smlClientKeyAlias: string; signatureKeyAlias: string; smlRegistered: boolean; - smlBlueCoatAuth: boolean; + smlClientCertAuth: boolean; } diff --git a/smp-angular/src/app/domain/domain.component.ts b/smp-angular/src/app/domain/domain.component.ts index cf834ada45cb1af202991a127bee665e7562cc8f..6f57cccb9d5f86e28b22145b812893cc54dec1ca 100644 --- a/smp-angular/src/app/domain/domain.component.ts +++ b/smp-angular/src/app/domain/domain.component.ts @@ -1,4 +1,4 @@ -import {AfterViewInit, Component, OnInit, TemplateRef, ViewChild} from '@angular/core'; +import {AfterViewInit, Component, TemplateRef, ViewChild} from '@angular/core'; import {ColumnPicker} from '../common/column-picker/column-picker.model'; import {MatDialog, MatDialogRef} from '@angular/material/dialog'; @@ -14,7 +14,6 @@ import {ConfirmationDialogComponent} from "../common/confirmation-dialog/confirm import {SearchTableEntityStatus} from "../common/search-table/search-table-entity-status.model"; import {KeystoreEditDialogComponent} from "./keystore-edit-dialog/keystore-edit-dialog.component"; import {SmpInfoService} from "../app-info/smp-info.service"; -import {SmpInfo} from "../app-info/smp-info.model"; import {SmlIntegrationService} from "./sml-integration.service"; import {SMLResult} from "./sml-result.model"; @@ -36,8 +35,6 @@ export class DomainComponent implements AfterViewInit { columnPicker: ColumnPicker = new ColumnPicker(); domainController: DomainController; filter: any = {}; - isSMPIntegrationOn: boolean = false; - constructor(public securityService: SecurityService, protected smpInfoService: SmpInfoService, @@ -48,11 +45,8 @@ export class DomainComponent implements AfterViewInit { public dialog: MatDialog) { // check application settings - this.isSMPIntegrationOn = this.lookups.cachedApplicationConfig.smlIntegrationOn - // if system admin refresh certificate list! - if (this.securityService.isCurrentUserSystemAdmin()) { - this.lookups.refreshCertificateLookup(); - } + + } ngAfterViewInit() { @@ -104,14 +98,20 @@ export class DomainComponent implements AfterViewInit { width: 120 }, { - name: 'SML BueCoat Auth.', - prop: 'smlBlueCoatAuth', + name: 'SML ClientCert Auth.', + prop: 'smlClientCertAuth', showInitially: true, width: 130 }, ]; this.searchTable.tableColumnInit(); this.columnPicker.selectedColumns = this.columnPicker.allColumns.filter(col => col.showInitially); + + // if system admin refresh certificate list! + if (this.securityService.isCurrentUserSystemAdmin()) { + this.lookups.refreshCertificateLookup(); + } + } certificateAliasExists(alias: string): boolean { @@ -146,14 +146,15 @@ export class DomainComponent implements AfterViewInit { return 'deleted'; } } + getDomainConfigurationWarning(domain: DomainRo) { - let msg =null; + let msg = null; if (!domain.signatureKeyAlias) { msg = "The domain should have a defined signature CertAlias." } if (this.lookups.cachedApplicationConfig.smlIntegrationOn) { - if( !domain.smlSmpId || !domain.smlClientCertHeader){ - msg = (!msg?"": msg+" ") + "For SML integration the SMP SMP ID and SML client certificate must be defined!" + if (!domain.smlSmpId || !domain.smlClientCertHeader) { + msg = (!msg ? "" : msg + " ") + "For SML integration the SMP SMP ID and SML client certificate must be defined!" } } return msg; @@ -167,6 +168,9 @@ export class DomainComponent implements AfterViewInit { isDirty(): boolean { return this.searchTable.isDirty(); } + get isSMPIntegrationOn(){ + return this.lookups.cachedApplicationConfig?.smlIntegrationOn + } enableSMLRegister(): boolean { if (!this.selectedOneRow || !this.isSMPIntegrationOn) { @@ -174,10 +178,10 @@ export class DomainComponent implements AfterViewInit { } let domainRo = (this.searchTable.selected[0] as DomainRo); - if (!domainRo.smlClientCertHeader && domainRo.smlBlueCoatAuth) { + if (!domainRo.smlClientCertHeader && domainRo.smlClientCertAuth) { return false; } - if (!domainRo.smlClientKeyAlias && !domainRo.smlBlueCoatAuth) { + if (!domainRo.smlClientKeyAlias && !domainRo.smlClientCertAuth) { return false; } @@ -189,15 +193,15 @@ export class DomainComponent implements AfterViewInit { } enableSMLUnregister(): boolean { - if ( !this.selectedOneRow || !this.isSMPIntegrationOn) { + if (!this.selectedOneRow || !this.isSMPIntegrationOn) { return false; } let domainRo = (this.searchTable.selected[0] as DomainRo); - if (!domainRo.smlClientCertHeader && domainRo.smlBlueCoatAuth) { + if (!domainRo.smlClientCertHeader && domainRo.smlClientCertAuth) { return false; } - if (!domainRo.smlClientKeyAlias && !domainRo.smlBlueCoatAuth) { + if (!domainRo.smlClientKeyAlias && !domainRo.smlClientCertAuth) { return false; } @@ -209,7 +213,7 @@ export class DomainComponent implements AfterViewInit { return domainRo.smlRegistered; } - get selectedOneRow() : boolean{ + get selectedOneRow(): boolean { return this.searchTable?.selected.length === 1 } @@ -252,9 +256,9 @@ export class DomainComponent implements AfterViewInit { } smlRegisterDomain(domain: DomainRo) { - this.searchTable.showSpinner=true; + this.searchTable.showSpinner = true; this.smlIntegrationService.registerDomainToSML$(domain.domainCode).toPromise().then((res: SMLResult) => { - this.searchTable.showSpinner=false; + this.searchTable.showSpinner = false; if (res) { if (res.success) { this.alertService.success("Domain " + domain.domainCode + " registered to sml!"); @@ -268,16 +272,16 @@ export class DomainComponent implements AfterViewInit { } }, err => { - this.searchTable.showSpinner=false; + this.searchTable.showSpinner = false; this.alertService.exception('Error occurred while registering domain:' + domain.domainCode, err); } ) } smlUnregisterDomain(domain: DomainRo) { - this.searchTable.showSpinner=true; + this.searchTable.showSpinner = true; this.smlIntegrationService.unregisterDomainToSML$(domain.domainCode).toPromise().then((res: SMLResult) => { - this.searchTable.showSpinner=false; + this.searchTable.showSpinner = false; if (res) { if (res.success) { this.alertService.success("Domain " + domain.domainCode + " unregistered from sml!"); @@ -292,7 +296,7 @@ export class DomainComponent implements AfterViewInit { } , err => { - this.searchTable.showSpinner=false; + this.searchTable.showSpinner = false; this.alertService.exception('Error occurred while unregistering domain:' + domain.domainCode, err); } ) diff --git a/smp-angular/src/app/property/property-details-dialog/property-details-dialog.component.html b/smp-angular/src/app/property/property-details-dialog/property-details-dialog.component.html index 7855da5ad0bab57f63308be6ab439b48bdab85d6..80a8076de4992465d349e615c7966f0c48b14db4 100644 --- a/smp-angular/src/app/property/property-details-dialog/property-details-dialog.component.html +++ b/smp-angular/src/app/property/property-details-dialog/property-details-dialog.component.html @@ -13,12 +13,15 @@ <mat-label>Property value:</mat-label> <input matInput type="{{ getInputType(propertyForm.controls['type'].value) }}" style="width: 100%;padding: 5px" - formControlName="value"/> + formControlName="value" [pattern]="propertyForm.controls['valuePattern'].value"/> </mat-form-field> <mat-checkbox *ngIf="propertyForm.controls['type'].value === 'BOOLEAN'" formControlName="value" > {{ propertyForm.controls['property'].value }} </mat-checkbox> + <div *ngIf="propertyForm.controls['errorMessage'].value" class="alert-message-error"> + {{ propertyForm.controls['errorMessage'].value}} + </div> </mat-card-content> </mat-card> </form> diff --git a/smp-angular/src/app/property/property-details-dialog/property-details-dialog.component.ts b/smp-angular/src/app/property/property-details-dialog/property-details-dialog.component.ts index 58eee4d030b80b741ebab907d354882da6be83bb..2d3b141895698aa4276ad2f4599ae97ddd026742 100644 --- a/smp-angular/src/app/property/property-details-dialog/property-details-dialog.component.ts +++ b/smp-angular/src/app/property/property-details-dialog/property-details-dialog.component.ts @@ -4,6 +4,11 @@ import {FormBuilder, FormControl, FormGroup} from "@angular/forms"; import {PropertyRo} from "../property-ro.model"; import {AlertMessageService} from "../../common/alert-message/alert-message.service"; import {SearchTableEntityStatus} from "../../common/search-table/search-table-entity-status.model"; +import {ServiceGroupValidationRo} from "../../service-group-edit/service-group-details-dialog/service-group-validation-edit-ro.model"; +import {SmpConstants} from "../../smp.constants"; +import {ServiceGroupValidationErrorCodeModel} from "../../service-group-edit/service-group-details-dialog/service-group-validation-error-code.model"; +import {PropertyValidationRo} from "../property-validate-ro.model"; +import {HttpClient} from "@angular/common/http"; @Component({ selector: 'property-details-dialog', @@ -21,10 +26,12 @@ export class PropertyDetailsDialogComponent implements OnInit { current: PropertyRo & { confirmation?: string }; propertyForm: FormGroup; disabled: true; + showSpinner: boolean = false; constructor( public dialog: MatDialog, + protected http: HttpClient, private dialogRef: MatDialogRef<PropertyDetailsDialogComponent>, private alertService: AlertMessageService, @Inject(MAT_DIALOG_DATA) public data: any, @@ -50,6 +57,8 @@ export class PropertyDetailsDialogComponent implements OnInit { 'desc': new FormControl({value: '', readonly: true}, null), 'type': new FormControl({value: '', readonly: true}, null), 'value': new FormControl({value: ''}), + 'valuePattern': new FormControl({value: ''}), + 'errorMessage': new FormControl({value: ''}), }); @@ -57,6 +66,9 @@ export class PropertyDetailsDialogComponent implements OnInit { this.propertyForm.controls['desc'].setValue(this.current.desc); this.propertyForm.controls['type'].setValue(this.current.type); this.propertyForm.controls['value'].setValue(this.valueFromPropertyStringValue(this.current.value, this.current.type)); + this.propertyForm.controls['valuePattern'].setValue(this.current.valuePattern); + + this.propertyForm.controls['errorMessage'].setValue(''); } ngOnInit() { @@ -64,9 +76,26 @@ export class PropertyDetailsDialogComponent implements OnInit { } submitForm() { - this.checkValidity(this.propertyForm) - this.dialogRef.close(true); - + this.checkValidity(this.propertyForm); + + let request = this.getCurrent(); + // + let validationObservable = this.http.post<PropertyValidationRo>(SmpConstants.REST_INTERNAL_PROPERTY_VALIDATE, request); + this.showSpinner = true; + validationObservable.toPromise().then((res: PropertyValidationRo) => { + this.showSpinner = false; + + if (!res.propertyValid) { + this.propertyForm.controls['errorMessage'].setValue(res.errorMessage?res.errorMessage:'Invalid property'); + } else { + this.propertyForm.controls['errorMessage'].setValue(""); + // we can close the dialog + this.dialogRef.close(true); + } + }).catch((err) => { + this.alertService.error("Error occurred on Validation the property", err) + console.log("Error occurred on Validation the property: " + err); + }); } checkValidity(g: FormGroup) { @@ -115,7 +144,7 @@ export class PropertyDetailsDialogComponent implements OnInit { case 'PATH': return 'text'; case 'INTEGER': - return 'number'; + return 'text'; case 'BOOLEAN': return 'checkbox'; case 'REGEXP': @@ -128,6 +157,29 @@ export class PropertyDetailsDialogComponent implements OnInit { return 'text'; } } + getInputPatternType(propertyType: string) { + console.log("Get input pattern for row " + this.current.type) + switch (propertyType) { + case 'STRING': + case 'LIST_STRING': + case 'MAP_STRING': + case 'FILENAME': + case 'PATH': + return ''; + case 'INTEGER': + return '[0-9]*'; + case 'BOOLEAN': + return 'true/false'; + case 'REGEXP': + return ''; + case 'EMAIL': + return ''; + case 'URL': + return ''; + default: + return ''; + } + } public getCurrent(): PropertyRo { this.current.value = this.propertyForm.value['value']; diff --git a/smp-angular/src/app/property/property-ro.model.ts b/smp-angular/src/app/property/property-ro.model.ts index 043f894f4b51b68c7e6b4e2306387e6220a27d7e..d8663bcf39e740f7c36b935719373a8f7016c1b7 100644 --- a/smp-angular/src/app/property/property-ro.model.ts +++ b/smp-angular/src/app/property/property-ro.model.ts @@ -10,4 +10,5 @@ export interface PropertyRo extends SearchTableEntity { updateDate?: Date; mandatory?: boolean; restartNeeded? : boolean; + valuePattern?:string; } diff --git a/smp-angular/src/app/property/property-validate-ro.model.ts b/smp-angular/src/app/property/property-validate-ro.model.ts new file mode 100644 index 0000000000000000000000000000000000000000..bdbbb4b563239b69d15cbb30559b1e297297db6f --- /dev/null +++ b/smp-angular/src/app/property/property-validate-ro.model.ts @@ -0,0 +1,8 @@ +import {SearchTableEntity} from '../common/search-table/search-table-entity.model'; + +export interface PropertyValidationRo { + property: string; + value?: string; + propertyValid : boolean; + errorMessage?: string; +} diff --git a/smp-angular/src/app/smp.constants.ts b/smp-angular/src/app/smp.constants.ts index 921547f22330c96f49db65544c3671bf198f72fb..7038d8a5de1b0f1e1cfe43b53af38b3503c0995f 100644 --- a/smp-angular/src/app/smp.constants.ts +++ b/smp-angular/src/app/smp.constants.ts @@ -40,6 +40,7 @@ export class SmpConstants { public static readonly REST_INTERNAL_ALERT_MANAGE = SmpConstants.REST_INTERNAL + 'alert'; public static readonly REST_INTERNAL_DOMAIN_MANAGE = SmpConstants.REST_INTERNAL + 'domain'; public static readonly REST_INTERNAL_PROPERTY_MANAGE = SmpConstants.REST_INTERNAL + 'property'; + public static readonly REST_INTERNAL_PROPERTY_VALIDATE = SmpConstants.REST_INTERNAL_PROPERTY_MANAGE + '/validate'; public static readonly REST_INTERNAL_DOMAIN_VALIDATE_DELETE = SmpConstants.REST_INTERNAL_DOMAIN_MANAGE + '/validate-delete'; public static readonly REST_INTERNAL_USER_MANAGE = SmpConstants.REST_INTERNAL + 'user'; public static readonly REST_INTERNAL_USER_VALIDATE_DELETE = `${SmpConstants.REST_INTERNAL_USER_MANAGE}/validate-delete`; diff --git a/smp-angular/src/app/user/certificate-ro.model.ts b/smp-angular/src/app/user/certificate-ro.model.ts index a14dbb8b8ca66683701f4ebecf25dc98db2dc00a..7a0a8f1f8d6248999fb80c66d767ca45cc909de8 100644 --- a/smp-angular/src/app/user/certificate-ro.model.ts +++ b/smp-angular/src/app/user/certificate-ro.model.ts @@ -6,7 +6,7 @@ export interface CertificateRo { issuer: string; serialNumber: string; fingerprints: string; - blueCoatHeader?:string; + clientCertHeader?:string; encodedValue?:string; crlUrl?: String; alias?:string; diff --git a/smp-angular/src/app/user/truststore-edit-dialog/truststore-edit-dialog.component.ts b/smp-angular/src/app/user/truststore-edit-dialog/truststore-edit-dialog.component.ts index 8f9a3a2ce6e7509664374ccb00ef4f2848271e16..feab2a2dadeb9eec10fa05cc3383120af12ba2f3 100644 --- a/smp-angular/src/app/user/truststore-edit-dialog/truststore-edit-dialog.component.ts +++ b/smp-angular/src/app/user/truststore-edit-dialog/truststore-edit-dialog.component.ts @@ -77,6 +77,7 @@ export class TruststoreEditDialogComponent { const file = event.target.files[0]; this.truststoreService.uploadCertificate$(file).subscribe((res: CertificateRo) => { if (res && res.certificateId) { + this.alertService.success("Certificate: " + res.certificateId + " is imported!"); this.lookups.refreshTrustedCertificateLookup(); } else { this.alertService.exception("Error occurred while uploading certificate.", "Check if uploaded file has valid certificate type.", false); diff --git a/smp-api/pom.xml b/smp-api/pom.xml index b75507ffc0334c5b2ff3672498ef3992e97429d8..c88981896b5c8b6346724e20ff7160de552b1d01 100644 --- a/smp-api/pom.xml +++ b/smp-api/pom.xml @@ -23,6 +23,7 @@ <artifactId>smp-api</artifactId> <name>smp-api</name> + <packaging>jar</packaging> <dependencies> <!-- Generated equals() methods need it in runtime --> diff --git a/smp-docker/compose/tomcat-mysql-smp-sml/README.md b/smp-docker/compose/tomcat-mysql-smp-sml/README.md new file mode 100755 index 0000000000000000000000000000000000000000..4fd5846afc95ceccff6f53396dfbe74f5e124c47 --- /dev/null +++ b/smp-docker/compose/tomcat-mysql-smp-sml/README.md @@ -0,0 +1,54 @@ +# Experiamental SMP docker image +Purpose of compose plan is to startup fully functinal SMP environment for demo and testing. The plan contains + - MySql database + - SML services + - CAS instance (EULOGIN) + - email server (inbucket) + + +# Run environment +docker-compose -f docker-compose.yml up -d + + +## SMP +url: http://localhost:8982/smp/ + +http://eulogin.protected.smp.local:8982/smp/ +eulogin.protected.smp.local + +### MYSQL +Database client connection (for testing and debugging ) +url: jdbc:mysql://localhost:3908/smp +Username: smp +Password: smp + +### Volume (-v /opt/dockerdata/sml:/data) +Mysql database files and tomcat configuration (and logs) can be externalized for experimenting with different SMP settings. + + +## SML +url: http://localhost:8982/edelivery-sml/ + +### MYSQL +Database client connection (for testing and debugging ) +url: jdbc:mysql://localhost:3908/sml +Username: sml +Password: sml + +## CAS - EULOGIN +url: https://localhost:7102/cas/login +Users: + - user/123456 + - smp/123456 + - system/123456 + + To use eulogin add the following hostname mappings (Linux: /etc/hosts, windows: C:\Windows\System32\drivers\etc\hosts + + and add the lines ) + - 127.0.0.1 eulogin-mock-server + - 127.0.0.1 eulogin.protected.smp.local + + +## Mail server +url: http://172.19.0.2:9005/monitor + diff --git a/smp-docker/compose/tomcat-mysql-smp-sml/docker-compose.yml b/smp-docker/compose/tomcat-mysql-smp-sml/docker-compose.yml index 29724dc5598b2db50a870dbdc94c9ac9f5ad2a36..d4bc79f1d1cc3e5eb9cee8769416d6e29e91ad91 100644 --- a/smp-docker/compose/tomcat-mysql-smp-sml/docker-compose.yml +++ b/smp-docker/compose/tomcat-mysql-smp-sml/docker-compose.yml @@ -12,6 +12,19 @@ services: ||smp.sso.cas.urlpath.login=login ||smp.sso.cas.token.validation.urlpath=laxValidate ||smp.sso.cas.callback.url=http://eulogin.protected.smp.local:8982/smp/ui/public/rest/security/cas + ||bdmsl.integration.enabled=true + ||bdmsl.integration.url=http://localhost:8080/edelivery-sml/ + ||mail.smtp.host=mail-server.smp.local + ||mail.smtp.port=2500 + ||smp.alert.user.login_failure.enabled=true + ||smp.alert.user.suspended.enabled=true + ||smp.alert.password.imminent_expiration.enabled=true + ||smp.alert.password.expired.enabled=true + ||smp.alert.accessToken.imminent_expiration.enabled=true + ||smp.alert.accessToken.expired.enabled=true + ||smp.alert.certificate.imminent_expiration.enabled=true + ||smp.alert.certificate.expired.enabled=true + ||smp.alert.accessToken.expired.enabled=true volumes: - ./properties/db-scripts:/tmp/custom-data/ @@ -32,4 +45,10 @@ services: # Map this folder to host to be able to change runtime data for manual testing! # - ./eulogin/ecas-mock-server:/data/ecas-mock-server ports: - - "7102:7102" \ No newline at end of file + - "7102:7102" + + mail-service: + image: inbucket/inbucket:3.0.0 + hostname: mail-server.smp.local + ports: + - "9005:9000" \ No newline at end of file diff --git a/smp-docker/compose/tomcat-mysql-smp-sml/properties/db-scripts/sml-mysql5innodb-data.sql b/smp-docker/compose/tomcat-mysql-smp-sml/properties/db-scripts/sml-mysql5innodb-data.sql index fe8a92272f55bef576413b723d3aeca21c6359ca..7b6b00682297623b2a335cd6bc57d7f281a90768 100644 --- a/smp-docker/compose/tomcat-mysql-smp-sml/properties/db-scripts/sml-mysql5innodb-data.sql +++ b/smp-docker/compose/tomcat-mysql-smp-sml/properties/db-scripts/sml-mysql5innodb-data.sql @@ -45,8 +45,11 @@ INSERT INTO bdmsl_certificate_domain(certificate, crl_url, is_root_ca, fk_subdo ('CN=rootCNIsa,OU=B4,O=DIGIT,L=Brussels,ST=BE,C=BE','',1, 3, NOW(), NOW(),1), ('CN=AdministratorSML,OU=B4,O=DIGIT,C=BE','',0, 2, NOW(), NOW(),1); +INSERT INTO bdmsl_certificate (id, certificate_id, valid_from ,valid_until,created_on, last_updated_on ) VALUES +(id, 'CN=SMP_TEST-PRE-SET-EXAMPLE,O=DIGITAL,C=BE:00000000000000000000000000000001',DATE_ADD(NOW(), INTERVAL -3 DAY),DATE_ADD(NOW(), INTERVAL 365 DAY), NOW(), NOW()); - +INSERT INTO bdmsl_smp (smp_id, fk_certificate_id, fk_subdomain_id, endpoint_logical_address, endpoint_physical_address, created_on, last_updated_on ) VALUES +('CEF-SMP-001', 1,1, 'http://localhost:8080/smp/','0.0.0.0',NOW(), NOW()); diff --git a/smp-docker/images/build-docker-images.sh b/smp-docker/images/build-docker-images.sh index 174e9bdbd48b474d8929cd0b8ed11354e69da8e2..79753c8ba20f3d3aa604542b81124b1cbec58792 100755 --- a/smp-docker/images/build-docker-images.sh +++ b/smp-docker/images/build-docker-images.sh @@ -53,6 +53,7 @@ while getopts v:o:s:c:p: option; do esac done + if [[ -z "${SMP_VERSION}" ]]; then # get version from setup file echo "Get version from the pom: $(pwd)" @@ -65,11 +66,14 @@ if [[ -z "${SMP_VERSION}" ]]; then fi +SMP_PLUGIN_EXAMPLE="../../smp-examples/smp-spi-example/target/smp-spi-example-$SMP_VERSION.jar" + DIRNAME=$(dirname "$0") cd "$DIRNAME" DIRNAME="$(pwd -P)" echo "*****************************************************************" echo "* SMP artefact folders: $SMP_ARTEFACTS, (Clear folder after build: $SMP_ARTEFACTS_CLEAR )" +echo "* Plugin example: $SMP_PLUGIN_EXAMPLE " echo "* Build SMP image for version $SMP_VERSION" echo "* Oracle artefact folders: $ORACLE_ARTEFACTS" echo "*****************************************************************" @@ -151,6 +155,11 @@ validateAndPrepareArtefacts() { cp "${SMP_ARTEFACTS}/smp-${SMP_VERSION}-setup.zip" ./tomcat-mysql-smp-sml/artefacts/smp-setup.zip fi + if [[ ! -f "${SMP_PLUGIN_EXAMPLE}" ]]; then + echo "SMP SPI plugin '${SMP_PLUGIN_EXAMPLE}' not found. Skip plugin!" + else + cp "${SMP_PLUGIN_EXAMPLE}" ./tomcat-mysql-smp-sml/artefacts/smp-spi-example.jar + fi } # ----------------------------------------------------------------------------- diff --git a/smp-docker/images/tomcat-mysql-smp-sml/Dockerfile b/smp-docker/images/tomcat-mysql-smp-sml/Dockerfile index 133ff6156030ece7c9b2be9571312825ae7f4a22..2429ef129fb6adb0864623d60c1174bab42b1d41 100755 --- a/smp-docker/images/tomcat-mysql-smp-sml/Dockerfile +++ b/smp-docker/images/tomcat-mysql-smp-sml/Dockerfile @@ -132,6 +132,8 @@ RUN unzip /tmp/artefacts/smp-setup.zip -d /tmp/ \ && mv /tmp/bdmsl-webapp-$SML_VERSION /tmp/sml-setup \ && cp /tmp/sml-setup/encriptionPrivateKey.private /opt/smlconf/encriptionPrivateKey.private \ && cp /tmp/sml-setup/keystore.jks /opt/smlconf/keystore.jk \ + && mkdir $SMP_HOME/apache-tomcat-$TOMCAT_VERSION/smp-libs \ + && mv /tmp/artefacts/*.jar $SMP_HOME/apache-tomcat-$TOMCAT_VERSION/smp-libs \ && chmod u+x /sbin/entrypoint.sh diff --git a/smp-docker/images/tomcat-mysql-smp-sml/README.md b/smp-docker/images/tomcat-mysql-smp-sml/README.md index b923fd6fabf1b3f47aeff8b31cc1bf39a9fecf6f..0db205978ed894a3718c1cd623fa120560297467 100755 --- a/smp-docker/images/tomcat-mysql-smp-sml/README.md +++ b/smp-docker/images/tomcat-mysql-smp-sml/README.md @@ -4,12 +4,15 @@ Image uses latest version of eDelivery SMP setup on tomcat, mysql ubuntu # Image build -docker build -t smp . + docker build -t smp . # Run container based on smp image -docker run --name smp -it --rm -p [http-port]:8080 -v [local volume]:/data smp + + docker run --name smp -it --rm -p [http-port]:8080 edelivery-docker.devops.tech.ec.europa.eu/edeliverytest/smp-sml-tomcat-mysql + example: -docker run --name smp --rm -it -p 8080:8080 -v /opt/dockerdata/smp:/data smp smp + + docker run --name smp --rm -it -p 8080:8080 edelivery-docker.devops.tech.ec.europa.eu/edeliverytest/smp-sml-tomcat-mysql:4.2-SNAPSHOT ## SMP (param: -p 8080:8080 ) url: http://localhost:8080/smp @@ -20,9 +23,22 @@ url: jdbc:mysql://localhost:3306/smp Username: smp Password: smp -## Volume (-v /opt/dockerdata/sml:/data) +## Volume (-v /opt/docker-data/smp:/data) Mysql database files and tomcat configuration (and logs) can be externalized for experimenting with different SMP settings. + docker run --name smp --rm -it -p 8080:8080 -v /opt/docker-data/smp:/data edelivery-docker.devops.tech.ec.europa.eu/edeliverytest/smp-sml-tomcat-mysql:4.2-SNAPSHOT + +# Start docker with pre-init data +1. copy init sql script to folder (create folder) + + ./db-scripts + +example: + + curl -k https://ec.europa.eu/digital-building-blocks/code/projects/EDELIVERY/repos/smp/raw/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql?at=refs%2Fheads%2Fdevelopment --output ./db-scripts/mysql5innodb-data.sql + +Then start the docker as: + docker run --name smp --rm -it -p 8080:8080 -v - db-scripts:/tmp/custom-data/ edelivery-docker.devops.tech.ec.europa.eu/edeliverytest/smp-sml-tomcat-mysql:4.2-SNAPSHOT diff --git a/smp-docker/images/tomcat-mysql-smp-sml/bind/db.test.edelivery.local b/smp-docker/images/tomcat-mysql-smp-sml/bind/db.test.edelivery.local index 006d3d0cd818d01d1d96081b7b5ee735aa71f5c9..b962adfa8e4b5c0f42dbcaed90ac2a1fb53ce021 100755 --- a/smp-docker/images/tomcat-mysql-smp-sml/bind/db.test.edelivery.local +++ b/smp-docker/images/tomcat-mysql-smp-sml/bind/db.test.edelivery.local @@ -12,3 +12,4 @@ test.edelivery.local IN SOA ns.test.edelivery.local. root.test.edelivery.local. $ORIGIN test.edelivery.local. $TTL 60 ; 1 minute ns A 127.0.0.1 +CEF-SMP-002.publisher 60 IN CNAME localhost. \ No newline at end of file diff --git a/smp-docker/images/tomcat-mysql-smp-sml/entrypoint.sh b/smp-docker/images/tomcat-mysql-smp-sml/entrypoint.sh index 7a4a0f4dee549332168dc06a38fbcae80f948e61..d3468905349ebf2f5828b63a6106f9725ebc3f93 100755 --- a/smp-docker/images/tomcat-mysql-smp-sml/entrypoint.sh +++ b/smp-docker/images/tomcat-mysql-smp-sml/entrypoint.sh @@ -83,6 +83,8 @@ init_smp_properties() { echo "[INFO] init smp properties:" { echo "# SMP init parameters" + echo "libraries.folder=$SMP_HOME/apache-tomcat-$TOMCAT_VERSION/smp-libs" + echo "bdmsl.integration.logical.address=${SMP_LOGICAL_ADDRESS:-http://localhost:8080/smp/}" echo "authentication.blueCoat.enabled=true" echo "bdmsl.integration.enabled=true" echo "bdmsl.integration.physical.address=0.0.0.0" @@ -202,8 +204,8 @@ addOrReplaceProperties() { for property in "${array[@]}"; do read -r key value <<<"$property" # escape regex chars and remove trailing and leading spaces.. - keyRE="$(printf '%s' "${key// }" | sed 's/[.[\*^$()+?{|]/\\&/g')" - propertyRE="$(printf '%s' "${property// }" | sed 's/[.[\*^$()+?{|/]/\\&/g')" + keyRE="$(printf '%s' "${key// }" | sed 's/[[\*^$()+?{|]/\\&/g')" + propertyRE="$(printf '%s' "${property// }" | sed 's/[[\*^$()+?{|/]/\\&/g')" echo "replace or add property: [$keyRE] with value [$propertyRE]" # replace key line and commented #key line with new property diff --git a/smp-server-library/pom.xml b/smp-server-library/pom.xml index 0006fd33f7f82c57e0bb6a2bf4ede8fc07aaef3f..ccd2e372b84723f4cab770388c4b9b2663d7ddbd 100644 --- a/smp-server-library/pom.xml +++ b/smp-server-library/pom.xml @@ -279,7 +279,7 @@ 2. script version 3. export scripts.--> <java classname="eu.europa.ec.edelivery.smp.data.dao.utils.SMPSchemaGenerator" fork="true" failonerror="true"> - <arg value="org.hibernate.dialect.Oracle10gDialect,org.hibernate.dialect.MySQL5InnoDBDialect" /> + <arg value="org.hibernate.dialect.Oracle10gDialect,org.hibernate.dialect.MySQL5InnoDBDialect,org.hibernate.dialect.H2Dialect" /> <arg value="${project.version}" /> <arg value="${project.basedir}/../smp-webapp/src/main/smp-setup/database-scripts" /> <!-- reference to the passed-in classpath reference --> diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/DatabaseConfig.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/DatabaseConfig.java index df10d4ba7b31abba588810b8fe02d1467e28b349..69ac211a866c86f4911d5e3e12dd74f1573f8a78 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/DatabaseConfig.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/DatabaseConfig.java @@ -13,13 +13,10 @@ package eu.europa.ec.edelivery.smp.config; -import eu.europa.ec.edelivery.smp.exceptions.ErrorCode; import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException; import eu.europa.ec.edelivery.smp.logging.SMPLogger; import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory; -import eu.europa.ec.edelivery.smp.utils.ExtLibraryClassLoader; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; @@ -36,8 +33,6 @@ import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.naming.NamingException; import javax.persistence.EntityManagerFactory; import javax.sql.DataSource; -import java.io.File; -import java.net.MalformedURLException; import java.util.Properties; import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.INTERNAL_ERROR; @@ -74,7 +69,7 @@ public class DatabaseConfig { @Bean(name = "dataSource") public DataSource getDataSource() { - DataSource dataSource = null; + DataSource dataSource; if (!StringUtils.isBlank(url)) { LOG.info("create datasource with URL: " + url); DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource(); 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 b39f942c155aafa7ceee0e19b9deb27dfb58f68f..7331cfe880c0a35afd21a5798ae1fcfde1613419 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 @@ -4,6 +4,7 @@ import eu.europa.ec.edelivery.smp.data.model.DBConfiguration; import eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum; 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 javax.persistence.EntityManager; import javax.persistence.TypedQuery; @@ -26,29 +27,14 @@ public class DatabaseProperties extends Properties { List<DBConfiguration> lst = tq.getResultList(); for (DBConfiguration dc : lst) { if (dc.getValue() != null) { - LOG.info("Database property: [{}] value: [{}]", dc.getProperty(), - isSensitiveData(dc.getProperty()) ? "******" : dc.getValue()); - setProperty(trim(dc.getProperty()), trim(dc.getValue())); + String prop =trim(dc.getProperty()); + String value =trim(dc.getValue()); + setProperty(prop, value); + LOG.info("Database property: [{}] value: [{}]", prop,PropertyUtils.getMaskedData(prop, value) ); } lastUpdate = (lastUpdate == null || lastUpdate.isBefore(dc.getLastUpdatedOn())) ? dc.getLastUpdatedOn() : lastUpdate; } } - - /** - * Return true for properties which must not be logged! - * - * @param property - value to validate if contains sensitive data - * @return true if data is sensitive, else return false - */ - public boolean isSensitiveData(String property) { - Optional<SMPPropertyEnum> propOpt = SMPPropertyEnum.getByProperty(property); - 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; - } - public OffsetDateTime getLastUpdate() { return lastUpdate; } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/FileProperty.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/FileProperty.java index b10e90017a1c656b0e725f7a877a0646593da41a..ab78d7cbea3230cbe11cbee38f9a9d6b2db0a29c 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/FileProperty.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/FileProperty.java @@ -23,6 +23,11 @@ public class FileProperty { private static final SMPLogger LOG = SMPLoggerFactory.getLogger(FileProperty.class); + // the property file is set in the root fo the resources + public static final String PROPERTY_FILE = "/smp.config.properties"; + // legacy configuration file + public static final String PROPERTY_FILE_BACKUP = "/config.properties"; + public static final String PROPERTY_LOG_FOLDER = "log.folder"; public static final String PROPERTY_LOG_PROPERTIES = "log.configuration.file"; public static final String PROPERTY_DB_DRIVER = "jdbc.driver"; @@ -32,6 +37,7 @@ public class FileProperty { public static final String PROPERTY_DB_JNDI = "datasource.jndi"; public static final String PROPERTY_DB_DIALECT = "hibernate.dialect"; public static final String PROPERTY_LIB_FOLDER = "libraries.folder"; + public static final String PROPERTY_SMP_MODE_DEVELOPMENT = "smp.mode.development"; public static void updateLogConfiguration(String logFileFolder, String logPropertyFile, String configurationFolder) { @@ -58,7 +64,7 @@ public class FileProperty { public static void setLogConfiguration(File configurationFile) { try (InputStream configStream = new FileInputStream(configurationFile)) { - LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); + LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); JoranConfigurator configurator = new JoranConfigurator(); configurator.setContext(context); configurator.doConfigure(configStream); // loads logback file @@ -68,11 +74,15 @@ public class FileProperty { } public static Properties getFileProperties() { - LOG.info("Start read file properties from '/smp.config.properties'"); - InputStream is = PropertyInitialization.class.getResourceAsStream("/smp.config.properties"); + return getFileProperties(PROPERTY_FILE); + } + + public static Properties getFileProperties(String filename) { + LOG.info("Start read file properties from [{}]", filename); + InputStream is = PropertyInitialization.class.getResourceAsStream(filename); if (is == null) { - LOG.info("File '/smp.config.properties' not found in classpath, read '/config.properties'"); - is = PropertyInitialization.class.getResourceAsStream("/config.properties"); + LOG.info("File '[{}]' not found in classpath, read [{}].", filename, PROPERTY_FILE_BACKUP); + is = PropertyInitialization.class.getResourceAsStream(PROPERTY_FILE_BACKUP); } Properties connectionProp = new Properties(); try { @@ -84,17 +94,19 @@ public class FileProperty { // update deprecated values and return properties: return updateDeprecatedValues(connectionProp); } + /** * Method validates if new value for deprecated value is already set. If not it set the value from deprecated property if exists! + * * @param properties * @return */ - public static Properties updateDeprecatedValues(Properties properties){ + public static Properties updateDeprecatedValues(Properties properties) { if (!properties.containsKey(EXTERNAL_TLS_AUTHENTICATION_CLIENT_CERT_HEADER_ENABLED.getProperty()) - && properties.containsKey(CLIENT_CERT_HEADER_ENABLED_DEPRECATED.getProperty())){ + && properties.containsKey(CLIENT_CERT_HEADER_ENABLED_DEPRECATED.getProperty())) { properties.setProperty(EXTERNAL_TLS_AUTHENTICATION_CLIENT_CERT_HEADER_ENABLED.getProperty(), - properties.getProperty(CLIENT_CERT_HEADER_ENABLED_DEPRECATED.getProperty()) ); + properties.getProperty(CLIENT_CERT_HEADER_ENABLED_DEPRECATED.getProperty())); } return properties; diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/PropertyInitialization.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/PropertyInitialization.java index 0d00d807f735a5f88089ddb034dda911fcbe3a35..7b67cf97c5e45d33c4be2cd9dea0836039e0f39c 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/PropertyInitialization.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/PropertyInitialization.java @@ -21,6 +21,7 @@ import eu.europa.ec.edelivery.smp.logging.SMPLogger; import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory; import eu.europa.ec.edelivery.smp.utils.SecurityUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.jndi.JndiObjectFactoryBean; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; @@ -34,10 +35,8 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Paths; import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; import java.util.Properties; import static eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum.*; @@ -62,25 +61,33 @@ public class PropertyInitialization { protected Properties getDatabaseProperties(Properties fileProperties) { String dialect = fileProperties.getProperty(FileProperty.PROPERTY_DB_DIALECT); if (StringUtils.isBlank(dialect)) { - LOG.warn("Attribute: {} is empty. Database might not initialize!", FileProperty.PROPERTY_DB_DIALECT); + LOG.warn("The application property: {} is not set!. Database might not initialize!", FileProperty.PROPERTY_DB_DIALECT); } // get datasource DataSource dataSource = getDatasource(fileProperties); EntityManager em = null; - DatabaseProperties prop = null; + DatabaseProperties prop; + boolean devMode = Boolean.parseBoolean(fileProperties.getProperty(FileProperty.PROPERTY_SMP_MODE_DEVELOPMENT, "false")); + if (devMode) { + LOG.warn("***********************************************************************"); + LOG.warn("WARNING: The SMP is started in DEVELOPMENT mode!"); + LOG.warn("***********************************************************************"); + } try { em = createEntityManager(dataSource, dialect); prop = new DatabaseProperties(em); if (prop.size() == 0) { - initializeProperties(em, fileProperties, prop); + initializeProperties(em, fileProperties, prop, devMode); } else { - validateProperties(em, fileProperties, prop); + validateProperties(em, fileProperties, prop, devMode); } } finally { if (em != null && em.isOpen()) { em.close(); } } + + prop.setProperty(FileProperty.PROPERTY_SMP_MODE_DEVELOPMENT, Boolean.toString(devMode)); return prop; } @@ -96,10 +103,10 @@ public class PropertyInitialization { * @param em * @param fileProperties */ - protected void initializeProperties(EntityManager em, Properties fileProperties, Properties initProperties) { + protected void initializeProperties(EntityManager em, Properties fileProperties, Properties initProperties, boolean testMode) { em.getTransaction().begin(); LOG.warn("Database configuration table is empty! Initialize new values!"); - File encFile = initNewValues(em, fileProperties, initProperties); + File encFile = initNewValues(em, fileProperties, initProperties, testMode); for (SMPPropertyEnum val : SMPPropertyEnum.values()) { DBConfiguration dbConf = null; @@ -133,11 +140,9 @@ public class PropertyInitialization { em.getTransaction().commit(); } - public void initTruststore(String absolutePath, File fEncryption, EntityManager em, Properties properties, Properties fileProperties) { + public void initTruststore(String absolutePath, File fEncryption, EntityManager em, Properties properties, Properties fileProperties, boolean testMode) { LOG.info("Start generating new truststore."); - String encTrustEncToken; - if (fileProperties.containsKey(SMPPropertyEnum.TRUSTSTORE_PASSWORD.getProperty())) { LOG.info("get token from properties"); encTrustEncToken = SecurityUtils.encryptWrappedToken(fEncryption, @@ -145,7 +150,7 @@ public class PropertyInitialization { } else { // generate new token LOG.info("generate token"); - String trustToken = SecurityUtils.generateAuthenticationToken(); + String trustToken = SecurityUtils.generateAuthenticationToken(testMode); storeDBEntry(em, SMPPropertyEnum.TRUSTSTORE_PASSWORD_DECRYPTED, trustToken); encTrustEncToken = SecurityUtils.encrypt(fEncryption, trustToken); } @@ -167,6 +172,7 @@ public class PropertyInitialization { LOG.info("Generate truststore file "); truststore = getNewFile(absolutePath, "smp-truststore.jks"); } + LOG.info("Generate new truststore to file [{}]!", truststore.getAbsolutePath()); // store file to database storeDBEntry(em, SMPPropertyEnum.TRUSTSTORE_FILENAME, truststore.getName()); properties.setProperty(SMPPropertyEnum.TRUSTSTORE_FILENAME.getProperty(), truststore.getName()); @@ -180,25 +186,17 @@ public class PropertyInitialization { // init the truststore newTrustStore.load(null, trustToken.toCharArray()); newTrustStore.store(out, trustToken.toCharArray()); - } catch (IOException e) { - throw new SMPRuntimeException(INTERNAL_ERROR, e, "IOException occurred while creating truststore", e.getMessage()); - } catch (CertificateException e) { - throw new SMPRuntimeException(INTERNAL_ERROR, e, "CertificateException occurred while creating truststore", e.getMessage()); - } catch (NoSuchAlgorithmException e) { - throw new SMPRuntimeException(INTERNAL_ERROR, e, "NoSuchAlgorithmException occurred while creating truststore", e.getMessage()); - } catch (KeyStoreException e) { - throw new SMPRuntimeException(INTERNAL_ERROR, e, "KeyStoreException occurred while creating truststore", e.getMessage()); } catch (Exception e) { - throw new SMPRuntimeException(INTERNAL_ERROR, e, "Exception occurred while creating truststore", e.getMessage()); + throw new SMPRuntimeException(INTERNAL_ERROR, e, "Exception occurred while creating truststore", ExceptionUtils.getRootCauseMessage(e)); } } } public void initAndMergeKeystore(String absolutePath, File fEncryption, EntityManager em, Properties initProperties, - Properties fileProperties) { - + Properties fileProperties, boolean testMode) { + LOG.info("Start generating new keystore."); // store keystore password filename - String newKeyPassword = SecurityUtils.generateAuthenticationToken(); + String newKeyPassword = SecurityUtils.generateAuthenticationToken(testMode); storeDBEntry(em, SMPPropertyEnum.KEYSTORE_PASSWORD_DECRYPTED, newKeyPassword); String encPasswd = SecurityUtils.encrypt(fEncryption, newKeyPassword); storeDBEntry(em, SMPPropertyEnum.KEYSTORE_PASSWORD, encPasswd); @@ -216,41 +214,34 @@ public class PropertyInitialization { // check if keystore is empty then generate cert for user if (newKeystore.size() == 0) { X509CertificateUtils.createAndStoreCertificateWithChain( - new String []{TEST_CERT_ISSUER_DN, TEST_CERT_SUBJECT_DN}, - new String []{TEST_CERT_ISSUER_ALIAS, TEST_CERT_CERT_ALIAS}, + new String[]{TEST_CERT_ISSUER_DN, TEST_CERT_SUBJECT_DN}, + new String[]{TEST_CERT_ISSUER_ALIAS, TEST_CERT_CERT_ALIAS}, newKeystore, newKeyPassword); } newKeystore.store(out, newKeyPassword.toCharArray()); - } catch (IOException e) { - throw new SMPRuntimeException(INTERNAL_ERROR, e, "IOException occurred while creating keystore", e.getMessage()); - } catch (CertificateException e) { - throw new SMPRuntimeException(INTERNAL_ERROR, e, "CertificateException occurred while creating keystore", e.getMessage()); - } catch (NoSuchAlgorithmException e) { - throw new SMPRuntimeException(INTERNAL_ERROR, e, "NoSuchAlgorithmException occurred while creating keystore", e.getMessage()); - } catch (KeyStoreException e) { - throw new SMPRuntimeException(INTERNAL_ERROR, e, "KeyStoreException occurred while creating keystore", e.getMessage()); } catch (Exception e) { - throw new SMPRuntimeException(INTERNAL_ERROR, e, "Exception occurred while creating keystore", e.getMessage()); + throw new SMPRuntimeException(INTERNAL_ERROR, e, "Exception occurred while creating keystore", ExceptionUtils.getRootCauseMessage(e)); } } public File initEncryptionKey(String absolutePath, EntityManager em, Properties initProperties, Properties fileProperties) { + LOG.info("Calculate encryption key [{}]. This could take some time!", absolutePath); File fEncryption; if (fileProperties.containsKey(ENCRYPTION_FILENAME.getProperty())) { fEncryption = new File(absolutePath, fileProperties.getProperty(ENCRYPTION_FILENAME.getProperty())); } else { - fEncryption = getNewFile(absolutePath, SMPPropertyEnum.ENCRYPTION_FILENAME.getDefValue()); + fEncryption = getNewFile(absolutePath, ENCRYPTION_FILENAME.getDefValue()); } - ; // if file is not existing yet - as is the case in getNewFile create file if (!fEncryption.exists()) { SecurityUtils.generatePrivateSymmetricKey(fEncryption); } SecurityUtils.generatePrivateSymmetricKey(fEncryption); - storeDBEntry(em, SMPPropertyEnum.ENCRYPTION_FILENAME, fEncryption.getName()); - initProperties.setProperty(SMPPropertyEnum.ENCRYPTION_FILENAME.getProperty(), fEncryption.getName()); + LOG.info("Encryption key generated."); + storeDBEntry(em, ENCRYPTION_FILENAME, fEncryption.getName()); + initProperties.setProperty(ENCRYPTION_FILENAME.getProperty(), fEncryption.getName()); return fEncryption; } @@ -260,34 +251,31 @@ public class PropertyInitialization { * @param em * @param fileProperties */ - protected File initNewValues(EntityManager em, Properties fileProperties, Properties initProperties) { + protected File initNewValues(EntityManager em, Properties fileProperties, Properties initProperties, boolean testMode) { String absolutePath; if (fileProperties.containsKey(CONFIGURATION_DIR.getProperty())) { absolutePath = fileProperties.getProperty(CONFIGURATION_DIR.getProperty()); } else { - File settingsFolder = new File("/"); // set absolute path - absolutePath = new File("/").getAbsolutePath(); + absolutePath = Paths.get(CONFIGURATION_DIR.getDefValue()).toFile().getAbsolutePath(); + LOG.warn("The property [{}] Initialize SMP configuration files to folder [{}]!", CONFIGURATION_DIR.getProperty(), absolutePath); } File confFolder = new File(absolutePath); if (!confFolder.exists()) { - LOG.warn("Configuration folder {} not exists. Folder will be created!", confFolder.getAbsolutePath()); + LOG.warn("Configuration folder [{}] not exists. Folder will be created!", confFolder.getAbsolutePath()); confFolder.mkdirs(); } - - LOG.info("Generate new keystore to folder: " + absolutePath); // add configuration path storeDBEntry(em, CONFIGURATION_DIR, absolutePath); initProperties.setProperty(CONFIGURATION_DIR.getProperty(), absolutePath); // init encryption filename - File fEncryption = initEncryptionKey(absolutePath, em, initProperties, fileProperties); // init truststore - initTruststore(absolutePath, fEncryption, em, initProperties, fileProperties); - initAndMergeKeystore(absolutePath, fEncryption, em, initProperties, fileProperties); + initTruststore(absolutePath, fEncryption, em, initProperties, fileProperties, testMode); + initAndMergeKeystore(absolutePath, fEncryption, em, initProperties, fileProperties, testMode); return fEncryption; } @@ -323,7 +311,7 @@ public class PropertyInitialization { * @param em * @param fileProperties */ - protected void validateProperties(EntityManager em, Properties fileProperties, Properties databaseProperties) { + protected void validateProperties(EntityManager em, Properties fileProperties, Properties databaseProperties, boolean devMode) { em.getTransaction().begin(); if (!databaseProperties.containsKey(CONFIGURATION_DIR.getProperty())) { @@ -353,7 +341,7 @@ public class PropertyInitialization { // init this one because it is new! if (!databaseProperties.containsKey(TRUSTSTORE_FILENAME.getProperty())) { - initTruststore(configurationDir, fEncryption, em, databaseProperties, fileProperties); + initTruststore(configurationDir, fEncryption, em, databaseProperties, fileProperties, devMode); } em.getTransaction().commit(); } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/PropertyUpdateListener.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/PropertyUpdateListener.java index 15e57c40372a94221e4baf52cbce2d238c8589e7..2e6914f930aca7bf90cfc56a8d53250d89c7f1a5 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/PropertyUpdateListener.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/config/PropertyUpdateListener.java @@ -37,6 +37,4 @@ public interface PropertyUpdateListener { default void updateProperty(SMPPropertyEnum property, Object value) { updateProperties(Collections.singletonMap(property, value)); } - - ; } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ConfigurationDao.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ConfigurationDao.java index 10db28feb0915cb50eeca54fad707c7637d8c42a..ca29a53265313adf8cbd4639032ff273d9ba21b8 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ConfigurationDao.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/dao/ConfigurationDao.java @@ -27,6 +27,7 @@ import eu.europa.ec.edelivery.smp.utils.SecurityUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; import org.springframework.context.ApplicationContext; +import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.ContextStartedEvent; import org.springframework.context.event.ContextStoppedEvent; import org.springframework.context.event.EventListener; @@ -88,8 +89,8 @@ public class ConfigurationDao extends BaseDao<DBConfiguration> { @Transactional public DBConfiguration setPropertyToDatabase(SMPPropertyEnum key, String value, String description) { - - if (!PropertyUtils.isValidProperty(key, value)) { + File rootFolder = (File)getCachedPropertyValue(CONFIGURATION_DIR); + if (!PropertyUtils.isValidProperty(key, value, rootFolder)) { throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, key.getPropertyType().getErrorMessage(key.getProperty())); } @@ -143,11 +144,15 @@ public class ConfigurationDao extends BaseDao<DBConfiguration> { } public String getCachedProperty(SMPPropertyEnum key) { + return getCachedProperty(key.getProperty(), key.getDefValue()); + } + + public String getCachedProperty(String property,String defValue) { if (lastUpdate == null) { // init properties refreshProperties(); } - return cachedProperties.getProperty(key.getProperty(), key.getDefValue()); + return cachedProperties.getProperty(property, defValue); } public Object getCachedPropertyValue(SMPPropertyEnum key) { @@ -217,7 +222,7 @@ public class ConfigurationDao extends BaseDao<DBConfiguration> { /** * Application event when an {@code ApplicationContext} gets initialized or start */ - @EventListener({ContextStartedEvent.class}) + @EventListener({ContextRefreshedEvent.class}) public void contextRefreshedEvent() { LOG.debug("Application context is initialized: triggered refresh to update all property listeners"); setInitializedTime(OffsetDateTime.now()); diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/PropertyRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/PropertyRO.java index 7e9ec1ac5ae887e2d992abd4a2a73a7d9608cddb..bd0bf59945f18a230a36a74cec4ace2088ebf8e9 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/PropertyRO.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/PropertyRO.java @@ -14,11 +14,17 @@ public class PropertyRO extends BaseRO{ String newValue; boolean mandatory; boolean restartNeeded; + String valuePattern; - public PropertyRO() { + public PropertyRO(){} + + public PropertyRO(String property, String value) { + this.property = property; + this.value = value; } public PropertyRO(String property, String value, String type, String desc) { + this(property, value); this.property = property; this.value = value; this.type = type; @@ -96,4 +102,12 @@ public class PropertyRO extends BaseRO{ public void setRestartNeeded(boolean restartNeeded) { this.restartNeeded = restartNeeded; } + + public String getValuePattern() { + return valuePattern; + } + + public void setValuePattern(String valuePattern) { + this.valuePattern = valuePattern; + } } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/PropertyValidationRO.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/PropertyValidationRO.java new file mode 100644 index 0000000000000000000000000000000000000000..02706d9c8df9b744159128a830ca4fb22e351e35 --- /dev/null +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/PropertyValidationRO.java @@ -0,0 +1,45 @@ +package eu.europa.ec.edelivery.smp.data.ui; + +public class PropertyValidationRO { + public static final int ERROR_CODE_OK =0; + public static final int ERROR_CODE_SERVICE_GROUP_EXISTS =1; + public static final int ERROR_CODE_INVALID_EXTENSION =2; + + String property; + String value; + + boolean propertyValid; + String errorMessage; + + public String getProperty() { + return property; + } + + public void setProperty(String property) { + this.property = property; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public boolean isPropertyValid() { + return propertyValid; + } + + public void setPropertyValid(boolean propertyValid) { + this.propertyValid = propertyValid; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } +} diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceResult.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceResult.java index eaf5b034572032d4fb419e0cb070ff28724d49aa..1f88ef6524475ea437f0224ed8dfe829de93ff78 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceResult.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/ServiceResult.java @@ -13,7 +13,7 @@ public class ServiceResult<T> implements Serializable { private static final long serialVersionUID = -4971552086560325302L; - private Map<String, Object> filter; //NOSONAR + private String filter; //NOSONAR private List<T> serviceEntities; //NOSONAR @@ -21,11 +21,11 @@ public class ServiceResult<T> implements Serializable { private Integer page; private Integer pageSize; - public Map<String, Object> getFilter() { + public String getFilter() { return filter; } - public void setFilter(Map<String, Object> filter) { + public void setFilter(String filter) { this.filter = filter; } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java index 4176a2b645130b6fbc418f635660fab2e89f6482..aa31c92d0063db5f514df29e3d61780e9e7664b9 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyEnum.java @@ -79,7 +79,7 @@ public enum SMPPropertyEnum { "Force change password at UI login if expired", false, false,false, BOOLEAN), USER_LOGIN_FAIL_DELAY("smp.user.login.fail.delay","1000", - "Delay in ms on invalid username or password", false, false,false, INTEGER), + "Delay response in ms on invalid username or password", false, false,false, INTEGER), USER_MAX_FAILED_ATTEMPTS("smp.user.login.maximum.attempt","5", "Number of console login attempt before the user is deactivated", false, false,false, INTEGER), @@ -117,7 +117,7 @@ public enum SMPPropertyEnum { SSO_CAS_TOKEN_VALIDATION_PARAMS("smp.sso.cas.token.validation.params", "acceptStrengths:BASIC,CLIENT_CERT|assuranceLevel:TOP", "The CAS token validation key:value properties separated with '|'.Ex: 'acceptStrengths:BASIC,CLIENT_CERT|assuranceLevel:TOP'", false, false, true, MAP_STRING), SSO_CAS_TOKEN_VALIDATION_GROUPS("smp.sso.cas.token.validation.groups", "DIGIT_SMP|DIGIT_ADMIN", "'|' separated CAS groups user must belong to.", false, false, true, LIST_STRING), - MAIL_SERVER_HOST("mail.smtp.host", "mail.server.com", "Email server - configuration for submitting the emails.", false,false, false, STRING), + MAIL_SERVER_HOST("mail.smtp.host", "", "Email server - configuration for submitting the emails.", false,false, false, STRING), MAIL_SERVER_PORT("mail.smtp.port", "25", "Smtp mail port - configuration for submitting the emails.", false,false, false,INTEGER), MAIL_SERVER_PROTOCOL("mail.smtp.protocol", "smtp", "smtp mail protocol- configuration for submitting the emails.", false,false,false, STRING), MAIL_SERVER_USERNAME("mail.smtp.username", "", "smtp mail protocol- username for submitting the emails.", false,false,false, STRING), @@ -217,13 +217,14 @@ public enum SMPPropertyEnum { String property; String defValue; String desc; + String valuePattern; boolean isEncrypted; boolean isMandatory; boolean restartNeeded; SMPPropertyTypeEnum propertyType; - SMPPropertyEnum(String property, String defValue, String desc, boolean isMandatory, boolean isEncrypted, boolean restartNeeded, SMPPropertyTypeEnum propertyType) { + SMPPropertyEnum(String property, String defValue, String desc, boolean isMandatory, boolean isEncrypted, boolean restartNeeded, SMPPropertyTypeEnum propertyType,String valuePattern) { this.property = property; this.defValue = defValue; this.desc = desc; @@ -231,6 +232,12 @@ public enum SMPPropertyEnum { this.isMandatory = isMandatory; this.restartNeeded = restartNeeded; this.propertyType = propertyType; + this.valuePattern = valuePattern; + } + + SMPPropertyEnum(String property, String defValue, String desc, boolean isMandatory, boolean isEncrypted, boolean restartNeeded, SMPPropertyTypeEnum propertyType) { + this(property, defValue, desc, isMandatory, isEncrypted, restartNeeded, propertyType, propertyType.errorTemplate); + } public String getProperty() { @@ -272,6 +279,10 @@ public enum SMPPropertyEnum { public static List<SMPPropertyEnum> getRestartOnChangeProperties() { return Arrays.asList(values()).stream().filter(val -> val.isRestartNeeded()).collect(Collectors.toList()); } + + public String getValuePattern() { + return valuePattern; + } } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyTypeEnum.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyTypeEnum.java index 8e4bcae33663cb11fc38ce5b73e8ad74dac504dc..ad19834547a57755f863f1b9b44e465d49bd8e23 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyTypeEnum.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/data/ui/enums/SMPPropertyTypeEnum.java @@ -1,23 +1,26 @@ package eu.europa.ec.edelivery.smp.data.ui.enums; public enum SMPPropertyTypeEnum { - STRING ("Property [%s] is not valid String type!"), - LIST_STRING("Property [%s] is not valid LIST_STRING type!"), - MAP_STRING("Property [%s] is not valid MAP_STRING type!"), - INTEGER("Property [%s] is not valid Integer!"), - BOOLEAN("Property [%s] is not valid Boolean type!"), - REGEXP("Property [%s] is not valid Regular Expression type!"), - CRON_EXPRESSION("Property [%s] is not valid Cron Expression type!"), - EMAIL("Property [%s] is not valid Email address type!"), - FILENAME("Property [%s] is not valid Filename type or it does not exists!"), - PATH("Property [%s] is not valid Path type or it does not exists!"), - URL("Property [%s] is not valid URL type or it does not exists!"), + STRING (".*","Property [%s] is not valid String type!"), + LIST_STRING(".*","Property [%s] is not valid LIST_STRING type!"), + MAP_STRING(".*","Property [%s] is not valid MAP_STRING type!"), + INTEGER("\\d*","Property [%s] is not valid Integer!"), + BOOLEAN("true|false","Property [%s] is not valid Boolean type!"), + REGEXP(".*", "Property [%s] is not valid Regular Expression type!"), + CRON_EXPRESSION(".*","Property [%s] is not valid Cron Expression type!"), + EMAIL(".*","Property [%s] is not valid Email address type!"), + FILENAME(".*","Property [%s] is not valid Filename type or it does not exists!"), + PATH(".*","Property [%s] is not valid Path type or it does not exists!"), + URL(".*","Property [%s] is not valid URL type or it does not exists!"), ; String errorTemplate; + String defValidationRegExp; - SMPPropertyTypeEnum(String errorTemplate) { + SMPPropertyTypeEnum(String defValidationRegExp, String errorTemplate ) { + this.defValidationRegExp = defValidationRegExp; this.errorTemplate =errorTemplate; + } public String getErrorMessage(String property) { diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/AlertService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/AlertService.java index b16650985cba19200d27657cfda209757b401e42..d53bc26bf938a0311ec5cef6ffe477d010ee70b7 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/AlertService.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/AlertService.java @@ -54,9 +54,9 @@ public class AlertService { AlertLevelEnum alertLevel = configurationService.getAlertBeforeExpirePasswordLevel(); AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_IMMINENT_EXPIRATION; - alertCredentialExpiration(mailSubject, mailTo, - credentialType, credentialId, expiredOn, - alertLevel, alertType); + DBAlert alert = createAlert(mailSubject, mailTo, alertLevel, alertType); + + alertCredentialExpiration(alert, credentialType, credentialId, expiredOn); } public void alertUsernamePasswordExpired(DBUser user) { @@ -73,9 +73,9 @@ public class AlertService { AlertLevelEnum alertLevel = configurationService.getAlertExpiredPasswordLevel(); AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_EXPIRED; - alertCredentialExpiration(mailSubject, mailTo, - credentialType, credentialId, expiredOn, - alertLevel, alertType); + DBAlert alert = createAlert(mailSubject, mailTo, alertLevel, alertType); + + alertCredentialExpiration(alert, credentialType, credentialId, expiredOn); } public void alertBeforeAccessTokenExpire(DBUser user) { @@ -94,9 +94,8 @@ public class AlertService { AlertLevelEnum alertLevel = configurationService.getAlertBeforeExpireAccessTokenLevel(); AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_IMMINENT_EXPIRATION; - alertCredentialExpiration(mailSubject, mailTo, - credentialType, credentialId, expiredOn, - alertLevel, alertType); + DBAlert alert = createAlert(mailSubject, mailTo, alertLevel, alertType); + alertCredentialExpiration(alert, credentialType, credentialId, expiredOn); } public void alertAccessTokenExpired(DBUser user) { @@ -115,17 +114,15 @@ public class AlertService { AlertLevelEnum alertLevel = configurationService.getAlertExpiredAccessTokenLevel(); AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_EXPIRED; - alertCredentialExpiration(mailSubject, mailTo, - credentialType, credentialId, expiredOn, - alertLevel, alertType); + DBAlert alert = createAlert(mailSubject, mailTo, alertLevel, alertType); + alertCredentialExpiration(alert, credentialType, credentialId, expiredOn); } public void alertBeforeCertificateExpire(DBUser user) { - LOG.info("Alert Certificate [{}] for user [{}] is about to expire on [{}]", + LOG.info("Alert Certificate [{}] for user [{}] is about to expire", user.getCertificate().getCertificateId(), - user.getUsername(), - ISO_LOCAL_DATE_TIME.format(user.getAccessTokenExpireOn())); + user.getUsername()); String mailTo = user.getEmailAddress(); CredentialTypeEnum credentialType = CredentialTypeEnum.CERTIFICATE; @@ -137,16 +134,14 @@ public class AlertService { AlertLevelEnum alertLevel = configurationService.getAlertBeforeExpireCertificateLevel(); AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_IMMINENT_EXPIRATION; - alertCredentialExpiration(mailSubject, mailTo, - credentialType, credentialId, expiredOn, - alertLevel, alertType); + DBAlert alert = createAlert(mailSubject, mailTo, alertLevel, alertType); + alertCredentialExpiration(alert, credentialType, credentialId, expiredOn); } public void alertCertificateExpired(DBUser user) { - LOG.info("Alert Certificate [{}] for user [{}] expired on [{}]", + LOG.info("Alert Certificate [{}] for user [{}] expired", user.getCertificate().getCertificateId(), - user.getUsername(), - ISO_LOCAL_DATE_TIME.format(user.getAccessTokenExpireOn())); + user.getUsername()); String mailTo = user.getEmailAddress(); CredentialTypeEnum credentialType = CredentialTypeEnum.CERTIFICATE; @@ -158,168 +153,184 @@ public class AlertService { AlertLevelEnum alertLevel = configurationService.getAlertExpiredCertificateLevel(); AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_EXPIRED; - alertCredentialExpiration(mailSubject, mailTo, - credentialType, credentialId, expiredOn, - alertLevel, alertType); - } - - - public void alertCredentialExpiration(String mailSubject, - String mailTo, - CredentialTypeEnum credentialType, - String credentialId, - OffsetDateTime expirationDate, - AlertLevelEnum level, - AlertTypeEnum alertType) { - - // create alert - OffsetDateTime reportDate = OffsetDateTime.now(); - String serverName = HttpUtils.getServerAddress(); - - DBAlert alert = new DBAlert(); - alert.setProcessed(false); - alert.setMailSubject(mailSubject); - alert.setMailTo(mailTo); - alert.setReportingTime(reportDate); - alert.setAlertType(alertType); - alert.setAlertLevel(level); - alert.addProperty(CredentialsExpirationProperties.CREDENTIAL_TYPE.name(), credentialType.name()); - alert.addProperty(CredentialsExpirationProperties.CREDENTIAL_ID.name(), credentialId); - alert.addProperty(CredentialsExpirationProperties.EXPIRATION_DATETIME.name(), expirationDate); - alert.addProperty(CredentialsExpirationProperties.REPORTING_DATETIME.name(), reportDate); - alert.addProperty(CredentialsExpirationProperties.ALERT_LEVEL.name(), level.name()); - alert.addProperty(CredentialsExpirationProperties.SERVER_NAME.name(), serverName); - alertDao.persistFlushDetach(alert); - // submit alerts - submitAlertMail(alert); - } - - public void submitAlertMail(DBAlert alert) { - String mailTo = alert.getMailTo(); - if (StringUtils.isBlank(mailTo)) { - LOG.warn("Can not send mail (empty mail) for alert [{}]!", alert); - return; - } - - String mailFrom = configurationService.getAlertEmailFrom(); - PropertiesMailModel props = new PropertiesMailModel(alert); - mailService.sendMail(props, mailFrom, alert.getMailTo()); - - alert.setProcessed(true); - alert.setProcessedTime(OffsetDateTime.now()); - alertDao.update(alert); + DBAlert alert = createAlert(mailSubject, mailTo, alertLevel, alertType); + alertCredentialExpiration(alert, credentialType, credentialId, expiredOn); } - public void alertCredentialVerificationFailed(DBUser user,CredentialTypeEnum credentialType) { + public void alertCredentialVerificationFailed(DBUser user, CredentialTypeEnum credentialType) { Boolean loginFailureEnabled = configurationService.getAlertUserLoginFailureEnabled(); if (!loginFailureEnabled) { - LOG.debug("Alert Login failure is disabled!" ); + LOG.debug("Alert Login failure is disabled!"); return; } String mailTo = user.getEmailAddress(); - String mailSubject = configurationService.getAlertBeforeUserSuspendedSubject(); - AlertLevelEnum level = configurationService.getAlertUserSuspendedLevel(); + String mailSubject = configurationService.getAlertUserLoginFailureSubject(); + AlertLevelEnum alertLevel = configurationService.getAlertUserLoginFailureLevel(); AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_VERIFICATION_FAILED; - Integer failureCount = user.getSequentialLoginFailureCount(); - OffsetDateTime lastFailedLoginDate = user.getLastFailedLoginAttempt(); - String credentialId = user.getUsername(); - alertCredentialVerificationFailed(mailSubject, mailTo, + Integer failureCount; + OffsetDateTime lastFailedLoginDate; + String credentialId; + + if(credentialType == CredentialTypeEnum.ACCESS_TOKEN) { + failureCount = user.getSequentialTokenLoginFailureCount(); + lastFailedLoginDate = user.getLastTokenFailedLoginAttempt(); + credentialId = user.getAccessTokenIdentifier(); + }else if(credentialType == CredentialTypeEnum.USERNAME_PASSWORD) { + failureCount = user.getSequentialLoginFailureCount(); + lastFailedLoginDate = user.getLastFailedLoginAttempt(); + credentialId = user.getUsername(); + } else { + LOG.error("Alert for suspended credentials type [{}] is not supported", credentialType); + return; + } + DBAlert alert = createAlert(mailSubject, mailTo, alertLevel, alertType); + alertCredentialVerificationFailed(alert, credentialType, credentialId, - failureCount, lastFailedLoginDate, - level, alertType); + failureCount, lastFailedLoginDate); } public void alertCredentialsSuspended(DBUser user, CredentialTypeEnum credentialType) { Boolean suspensionAlertEnabled = configurationService.getAlertUserSuspendedEnabled(); if (!suspensionAlertEnabled) { - LOG.debug("Alert suspended is disabled!" ); + LOG.debug("Alert suspended is disabled!"); return; } String mailTo = user.getEmailAddress(); - String mailSubject = configurationService.getAlertBeforeUserSuspendedSubject(); - AlertLevelEnum level = configurationService.getAlertUserSuspendedLevel(); + String mailSubject = configurationService.getAlertUserSuspendedSubject(); + AlertLevelEnum alertLevel = configurationService.getAlertUserSuspendedLevel(); AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_SUSPENDED; - Integer failureCount = user.getSequentialLoginFailureCount(); - OffsetDateTime lastFailedLoginDate = user.getLastFailedLoginAttempt(); - OffsetDateTime suspendedUtil = lastFailedLoginDate.plusSeconds(configurationService.getLoginSuspensionTimeInSeconds()); - String credentialId = user.getUsername(); - alertCredentialSuspended(mailSubject, mailTo, + Integer failureCount; + OffsetDateTime lastFailedLoginDate; + OffsetDateTime suspendedUtil; + String credentialId; + if(credentialType == CredentialTypeEnum.ACCESS_TOKEN) { + failureCount = user.getSequentialTokenLoginFailureCount(); + lastFailedLoginDate = user.getLastTokenFailedLoginAttempt(); + suspendedUtil = lastFailedLoginDate.plusSeconds(configurationService.getAccessTokenLoginSuspensionTimeInSeconds()); + credentialId = user.getAccessTokenIdentifier(); + }else if(credentialType == CredentialTypeEnum.USERNAME_PASSWORD) { + failureCount = user.getSequentialLoginFailureCount(); + lastFailedLoginDate = user.getLastFailedLoginAttempt(); + suspendedUtil = lastFailedLoginDate.plusSeconds(configurationService.getLoginSuspensionTimeInSeconds()); + credentialId = user.getUsername(); + } else { + LOG.error("Alert for suspended credentials type [{}] is not supported", credentialType); + return; + } + DBAlert alert = createAlert(mailSubject, mailTo, alertLevel, alertType); + + alertCredentialSuspended(alert, credentialType, credentialId, - failureCount, lastFailedLoginDate, suspendedUtil, - level, alertType); + failureCount, lastFailedLoginDate, suspendedUtil); } - public void alertCredentialVerificationFailed(String mailSubject, - String mailTo, - CredentialTypeEnum credentialType, - String credentialId, - Integer failedLoginCount, - OffsetDateTime lastFailedLoginDate, - AlertLevelEnum level, - AlertTypeEnum alertType) { - - Boolean suspensionAlertEnabled = configurationService.getAlertUserLoginFailureEnabled(); - if (!suspensionAlertEnabled) { - LOG.debug("Alert suspended is disabled!" ); - return; - } + public void alertCredentialExpiration(DBAlert alert, + CredentialTypeEnum credentialType, + String credentialId, + OffsetDateTime expirationDate + ) { - OffsetDateTime reportDate = OffsetDateTime.now(); String serverName = HttpUtils.getServerAddress(); + // add alert properties + alert.addProperty(CredentialsExpirationProperties.CREDENTIAL_TYPE.name(), credentialType.name()); + alert.addProperty(CredentialsExpirationProperties.CREDENTIAL_ID.name(), credentialId); + alert.addProperty(CredentialsExpirationProperties.EXPIRATION_DATETIME.name(), expirationDate); + alert.addProperty(CredentialsExpirationProperties.REPORTING_DATETIME.name(), alert.getReportingTime()); + alert.addProperty(CredentialsExpirationProperties.ALERT_LEVEL.name(), alert.getAlertLevel().name()); + alert.addProperty(CredentialsExpirationProperties.SERVER_NAME.name(), serverName); + alertDao.persistFlushDetach(alert); + // submit alerts + submitAlertMail(alert); + } - DBAlert alert = new DBAlert(); - alert.setProcessed(false); - alert.setMailSubject(mailSubject); - alert.setMailTo(mailTo); - alert.setReportingTime(reportDate); - alert.setAlertType(alertType); - alert.setAlertLevel(level); + public void alertCredentialVerificationFailed(DBAlert alert, + CredentialTypeEnum credentialType, + String credentialId, + Integer failedLoginCount, + OffsetDateTime lastFailedLoginDate + ) { + String serverName = HttpUtils.getServerAddress(); + // add alert properties alert.addProperty(CredentialVerificationFailedProperties.CREDENTIAL_TYPE.name(), credentialType.name()); alert.addProperty(CredentialVerificationFailedProperties.CREDENTIAL_ID.name(), credentialId); alert.addProperty(CredentialVerificationFailedProperties.FAILED_LOGIN_ATTEMPT.name(), failedLoginCount.toString()); alert.addProperty(CredentialVerificationFailedProperties.LAST_LOGIN_FAILURE_DATETIME.name(), lastFailedLoginDate); - alert.addProperty(CredentialVerificationFailedProperties.REPORTING_DATETIME.name(), reportDate); - alert.addProperty(CredentialVerificationFailedProperties.ALERT_LEVEL.name(), level.name()); + alert.addProperty(CredentialVerificationFailedProperties.REPORTING_DATETIME.name(), alert.getReportingTime()); + alert.addProperty(CredentialVerificationFailedProperties.ALERT_LEVEL.name(), alert.getAlertLevel().name()); alert.addProperty(CredentialVerificationFailedProperties.SERVER_NAME.name(), serverName); alertDao.persistFlushDetach(alert); // submit alerts submitAlertMail(alert); } - public void alertCredentialSuspended(String mailSubject, - String mailTo, + + public void alertCredentialSuspended(DBAlert alert, CredentialTypeEnum credentialType, String credentialId, Integer failedLoginCount, OffsetDateTime lastFailedLoginDate, - OffsetDateTime suspendedUtil, - AlertLevelEnum level, - AlertTypeEnum alertType) { + OffsetDateTime suspendedUtil) { - OffsetDateTime reportDate = OffsetDateTime.now(); String serverName = HttpUtils.getServerAddress(); - - DBAlert alert = new DBAlert(); - alert.setProcessed(false); - alert.setMailSubject(mailSubject); - alert.setMailTo(mailTo); - alert.setReportingTime(reportDate); - alert.setAlertType(alertType); - alert.setAlertLevel(level); + // add alert properties alert.addProperty(CredentialSuspendedProperties.CREDENTIAL_TYPE.name(), credentialType.name()); alert.addProperty(CredentialSuspendedProperties.CREDENTIAL_ID.name(), credentialId); alert.addProperty(CredentialSuspendedProperties.FAILED_LOGIN_ATTEMPT.name(), failedLoginCount.toString()); alert.addProperty(CredentialSuspendedProperties.LAST_LOGIN_FAILURE_DATETIME.name(), lastFailedLoginDate); alert.addProperty(CredentialSuspendedProperties.SUSPENDED_UNTIL_DATETIME.name(), suspendedUtil); - alert.addProperty(CredentialSuspendedProperties.REPORTING_DATETIME.name(), reportDate); - alert.addProperty(CredentialSuspendedProperties.ALERT_LEVEL.name(), level.name()); + alert.addProperty(CredentialSuspendedProperties.REPORTING_DATETIME.name(), alert.getReportingTime()); + alert.addProperty(CredentialSuspendedProperties.ALERT_LEVEL.name(), alert.getAlertLevel().name()); alert.addProperty(CredentialSuspendedProperties.SERVER_NAME.name(), serverName); alertDao.persistFlushDetach(alert); // submit alerts submitAlertMail(alert); } + /** + * Create Alert DB entity + * + * @param mailSubject + * @param mailTo + * @param level + * @param alertType + * @return + */ + protected DBAlert createAlert(String mailSubject, + String mailTo, + AlertLevelEnum level, + AlertTypeEnum alertType) { + + DBAlert alert = new DBAlert(); + alert.setProcessed(false); + alert.setMailSubject(mailSubject); + alert.setMailTo(mailTo); + alert.setReportingTime(OffsetDateTime.now()); + alert.setAlertType(alertType); + alert.setAlertLevel(level); + return alert; + } + + /** + * Submit mail for the alert + * @param alert + */ + public void submitAlertMail(DBAlert alert) { + String mailTo = alert.getMailTo(); + if (StringUtils.isBlank(mailTo)) { + LOG.warn("Can not send mail (empty mail) for alert [{}]!", alert); + return; + } + + String mailFrom = configurationService.getAlertEmailFrom(); + PropertiesMailModel props = new PropertiesMailModel(alert); + mailService.sendMail(props, mailFrom, alert.getMailTo()); + + alert.setProcessed(true); + alert.setProcessedTime(OffsetDateTime.now()); + alertDao.update(alert); + } + } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java index 3d26225b4c5849a49a709bf23fb5055d357b00c9..c923ac99035bf6bbe25dd3328f2276cac3f7fc44 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ConfigurationService.java @@ -1,6 +1,7 @@ package eu.europa.ec.edelivery.smp.services; import eu.europa.ec.edelivery.smp.auth.enums.SMPUserAuthenticationTypes; +import eu.europa.ec.edelivery.smp.config.FileProperty; import eu.europa.ec.edelivery.smp.data.dao.ConfigurationDao; import eu.europa.ec.edelivery.smp.data.ui.enums.AlertLevelEnum; import eu.europa.ec.edelivery.smp.data.ui.enums.AlertSuspensionMomentEnum; @@ -85,8 +86,8 @@ public class ConfigurationService { } public Integer getLoginFailDelayInMilliSeconds() { - Integer delay =(Integer) configurationDAO.getCachedPropertyValue(USER_LOGIN_FAIL_DELAY); - return delay==null? 1000:delay; + Integer delay = (Integer) configurationDAO.getCachedPropertyValue(USER_LOGIN_FAIL_DELAY); + return delay == null ? 1000 : delay; } public Integer getAccessTokenLoginMaxAttempts() { @@ -98,8 +99,8 @@ public class ConfigurationService { } public Integer getAccessTokenLoginFailDelayInMilliSeconds() { - Integer delay =(Integer) configurationDAO.getCachedPropertyValue(ACCESS_TOKEN_FAIL_DELAY); - return delay==null? 1000:delay; + Integer delay = (Integer) configurationDAO.getCachedPropertyValue(ACCESS_TOKEN_FAIL_DELAY); + return delay == null ? 1000 : delay; } public Integer getHttpHeaderHstsMaxAge() { @@ -336,7 +337,7 @@ public class ConfigurationService { return AlertLevelEnum.valueOf(level); } - public String getAlertBeforeUserLoginFailureSubject() { + public String getAlertUserLoginFailureSubject() { return (String) configurationDAO.getCachedPropertyValue(ALERT_USER_LOGIN_FAILURE_MAIL_SUBJECT); } @@ -351,7 +352,7 @@ public class ConfigurationService { return AlertLevelEnum.valueOf(level); } - public String getAlertBeforeUserSuspendedSubject() { + public String getAlertUserSuspendedSubject() { return (String) configurationDAO.getCachedPropertyValue(ALERT_USER_SUSPENDED_MAIL_SUBJECT); } @@ -504,5 +505,13 @@ public class ConfigurationService { return (String) configurationDAO.getCachedPropertyValue(SMP_ALERT_MAIL_FROM); } + /** + * Property is set in "file property configuration and can not be changed via database! + * @return true if smp server is started in development mode + */ + public boolean isSMPStartupInDevMode() { + return Boolean.parseBoolean(configurationDAO.getCachedProperty(FileProperty.PROPERTY_SMP_MODE_DEVELOPMENT, "false")); + } + } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/CredentialValidatorService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/CredentialValidatorService.java index cac8e963afe81a2d479305f263f9c2d2283f5812..a67b37d9aef513c86b75ef84d570cd410224c1aa 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/CredentialValidatorService.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/CredentialValidatorService.java @@ -67,7 +67,7 @@ public class CredentialValidatorService { } protected void validateCredentialsForExpiredUsernames() { - Boolean alertExpired = configurationService.getAlertBeforeExpirePasswordEnabled(); + Boolean alertExpired = configurationService.getAlertExpiredPasswordEnabled(); if (alertExpired == null || !alertExpired) { LOG.debug("Expire user password validation is disabled"); return; @@ -94,7 +94,7 @@ public class CredentialValidatorService { } protected void validateCredentialsForExpiredAccessToken() { - Boolean alertExpired = configurationService.getAlertBeforeExpireAccessTokenEnabled(); + Boolean alertExpired = configurationService.getAlertExpiredAccessTokenEnabled(); if (alertExpired == null || !alertExpired) { LOG.debug("Expire user AccessToken validation is disabled"); return; @@ -122,7 +122,7 @@ public class CredentialValidatorService { } protected void validateCredentialsForExpiredCertificate() { - Boolean alertExpired = configurationService.getAlertBeforeExpireCertificateEnabled(); + Boolean alertExpired = configurationService.getAlertExpiredCertificateEnabled(); if (alertExpired == null || !alertExpired) { LOG.debug("Expire user Certificate validation is disabled"); return; diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/DomainService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/DomainService.java index 07e3aa15dd237fe399b3171a1929f324c6451074..952eb5346373619ec4bb502116e588fb7f99fd24 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/DomainService.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/DomainService.java @@ -54,7 +54,7 @@ public class DomainService { /** - * Method checks if domain is in right format. Domain must contains only alphanomeric chars and it shoud + * Method checks if domain is in right format. Domain must contains only alphanomeric chars and it must * not be longer than 50 chars. * * @param domain diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/PayloadValidatorService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/PayloadValidatorService.java index 17dc306ec188686f8635e42f6afd03646db1f673..239509e48bcd593037e5535327c4fe95f61dce41 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/PayloadValidatorService.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/PayloadValidatorService.java @@ -53,7 +53,4 @@ public class PayloadValidatorService { throw new SMPRuntimeException(ErrorCode.INVALID_REQUEST, "Content validation failed", ExceptionUtils.getRootCauseMessage(e),e); } } - - ; - } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIPropertyService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIPropertyService.java index 0ba7dcdffd51b6d47cb845e475bea1e5ecb65666..f200b8798882aba05701fbfac5cde706e65b2bf2 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIPropertyService.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIPropertyService.java @@ -4,22 +4,26 @@ import eu.europa.ec.edelivery.smp.cron.SMPDynamicCronTrigger; import eu.europa.ec.edelivery.smp.data.dao.ConfigurationDao; import eu.europa.ec.edelivery.smp.data.model.DBConfiguration; import eu.europa.ec.edelivery.smp.data.ui.PropertyRO; +import eu.europa.ec.edelivery.smp.data.ui.PropertyValidationRO; import eu.europa.ec.edelivery.smp.data.ui.ServiceResultProperties; import eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum; +import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException; 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.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.RequestBody; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.io.File; +import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import static eu.europa.ec.edelivery.smp.cron.CronTriggerConfig.TRIGGER_BEAN_PROPERTY_REFRESH; +import static eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum.CONFIGURATION_DIR; import static eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum.SMP_CLUSTER_ENABLED; import static org.apache.commons.lang3.time.DateFormatUtils.ISO_8601_EXTENDED_DATETIME_FORMAT; @@ -66,8 +70,8 @@ public class UIPropertyService { .collect(Collectors.toMap(DBConfiguration::getProperty, Function.identity())); List<PropertyRO> properties = filteredProperties.stream() - .skip( page * (long)pageSize) - .limit(pageSize) + .skip( page<0?0:page * (long)pageSize) + .limit(pageSize<0?SMPPropertyEnum.values().length:pageSize) .map(prop -> createProperty(prop, changedProps)) .collect(Collectors.toList()); @@ -76,11 +80,13 @@ public class UIPropertyService { result.setCount((long) filteredProperties.size()); result.setPage(page); result.setPageSize(pageSize); + result.setFilter(filterByProperty); result.setServerRestartNeeded(configurationDao.isServerRestartNeeded()); return result; } public PropertyRO createProperty(SMPPropertyEnum propertyType, Map<String, DBConfiguration> changedProps) { + PropertyRO property = new PropertyRO(propertyType.getProperty(), configurationDao.getCachedProperty(propertyType), propertyType.getPropertyType().name(), @@ -89,6 +95,7 @@ public class UIPropertyService { property.setEncrypted(propertyType.isEncrypted()); property.setRestartNeeded(propertyType.isRestartNeeded()); property.setMandatory(propertyType.isMandatory()); + property.setValuePattern(property.getValuePattern()); if (changedProps.containsKey(property.getProperty())) { property.setNewValue(changedProps.get(propertyType.getProperty()).getValue()); @@ -110,4 +117,38 @@ public class UIPropertyService { } configurationDao.reloadPropertiesFromDatabase(); } + + public PropertyValidationRO validateProperty(PropertyRO propertyRO) { + LOG.info("Validate property: [{}]", propertyRO.getProperty()); + PropertyValidationRO propertyValidationRO = new PropertyValidationRO(); + propertyValidationRO.setProperty(propertyRO.getProperty()); + propertyValidationRO.setValue(propertyRO.getValue()); + + Optional<SMPPropertyEnum> optPropertyEnum = SMPPropertyEnum.getByProperty(propertyRO.getProperty()); + if (!optPropertyEnum.isPresent()) { + LOG.debug("Property: [{}] is not SMP property!", propertyRO.getProperty()); + propertyValidationRO.setErrorMessage("Property [" + propertyRO.getProperty() + "] is not SMP property!"); + propertyValidationRO.setPropertyValid(false); + return propertyValidationRO; + } + SMPPropertyEnum propertyEnum = optPropertyEnum.get(); + if (StringUtils.isBlank(propertyRO.getValue()) && propertyEnum.isMandatory()) { + propertyValidationRO.setErrorMessage("Property [" + propertyRO.getProperty() + "] must not be NULL OR empty!"); + propertyValidationRO.setPropertyValid(false); + return propertyValidationRO; + } + + // try to parse value + try { + File confDir = (File) configurationDao.getCachedPropertyValue(CONFIGURATION_DIR); + PropertyUtils.parseProperty(propertyEnum, propertyRO.getValue(), confDir); + } catch (SMPRuntimeException ex) { + propertyValidationRO.setErrorMessage(ex.getMessage()); + propertyValidationRO.setPropertyValid(false); + return propertyValidationRO; + } + + propertyValidationRO.setPropertyValid(true); + return propertyValidationRO; + } } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java index 88e757865730f24520b568f2969928194d0f7b41..29debdc146a9adc8c2cf825f25f7068b018c1f16 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/services/ui/UIUserService.java @@ -116,14 +116,15 @@ public class UIUserService extends UIServiceBase<DBUser, UserRO> { if (!BCrypt.checkpw(currentPassword, dbUser.getPassword())) { throw new BadCredentialsException("Password change failed; Invalid current password!"); } - // setup new daes - AccessTokenRO token = SecurityUtils.generateAccessToken(); + Boolean testMode = configurationService.isSMPStartupInDevMode(); + AccessTokenRO token = SecurityUtils.generateAccessToken(testMode); OffsetDateTime generatedTime = token.getGeneratedOn(); token.setExpireOn(generatedTime.plusDays(configurationService.getAccessTokenPolicyValidDays())); dbUser.setAccessTokenIdentifier(token.getIdentifier()); dbUser.setAccessToken(BCryptPasswordHash.hashPassword(token.getValue())); dbUser.setAccessTokenGeneratedOn(generatedTime); - dbUser.setPasswordExpireOn(token.getExpireOn()); + dbUser.setAccessTokenExpireOn(token.getExpireOn()); + return token; } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/sml/SmlConnector.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/sml/SmlConnector.java index 403a0e5880c9475cbda4e062a9250dd659957aff..8e8cbcc3f5fe276c5729bf138adbfd0f597faa11 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/sml/SmlConnector.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/sml/SmlConnector.java @@ -362,6 +362,7 @@ public class SmlConnector implements ApplicationContextAware { tlsParams.setUseHttpsURLConnectionDefaultHostnameVerifier(false); tlsParams.setCertConstraints(createCertConstraint(configurationService.getSMLIntegrationServerCertSubjectRegExpPattern())); tlsParams.setDisableCNCheck(configurationService.smlDisableCNCheck()); + tlsParams.setTrustManagers(truststoreService.getTrustManagers()); if (!clientCertAuthentication) { LOG.info("SML X509 certificate authentication with alias {}.", smlClientAuthentication); diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/ExtLibraryClassLoader.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/ExtLibraryClassLoader.java index faaeb1dba3c29516937994f282ab2ef6c465fcbc..8d4ac7eae932c563f6ea6cf0e6e7221566325d10 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/ExtLibraryClassLoader.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/ExtLibraryClassLoader.java @@ -1,6 +1,5 @@ package eu.europa.ec.edelivery.smp.utils; -import com.google.common.collect.Lists; import eu.europa.ec.edelivery.smp.logging.SMPLogger; import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory; @@ -9,14 +8,15 @@ import java.net.MalformedURLException; import java.net.URI; import java.net.URL; import java.net.URLClassLoader; -import java.util.*; +import java.util.Arrays; +import java.util.List; import java.util.stream.Collectors; /** * @author Cosmin Baciu * @author Joze Rihtarsic * @since 4.2 - * + * <p> * ExtLibraryClassLoader extends URLClassLoader for loading the SMP's SPI extensions. * The class loader implementation is heavily inspired by the Domibus PluginClassLoader. */ diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/HttpForwardedHeaders.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/HttpForwardedHeaders.java index 2316cd63c6eaa3497446c2029f27aee17ccc740a..13aa13fe2b888a624726dcf71e43ba6eafdce207 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/HttpForwardedHeaders.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/HttpForwardedHeaders.java @@ -8,7 +8,7 @@ import javax.servlet.http.HttpServletRequest; /** * This class is initialized from HttpServletRequest's X-Forwarded-* headers. - * + * <p> * The X-Forwarded-Host header defines which Host was used in the Client's request. In some RP implementations, it has only domain/ip * 'example.com' and (non-standard) X-Forwarded-Port is used for submitting port some implementations is combined with the port * as an example 'example.com:443' @@ -24,14 +24,12 @@ public class HttpForwardedHeaders { private static final char HOST_PORT_SEPARATOR = ':'; - enum ForwardedHeaderNameEnum { + public enum ForwardedHeaderNameEnum { HOST("X-Forwarded-Host"), PROTO("X-Forwarded-Proto"), FOR("X-Forwarded-For"), // non standard headers - PORT("X-Forwarded-Port"), - PREFIX("X-Forwarded-Prefix"), - SSL("X-Forwarded-Ssl"); + PORT("X-Forwarded-Port"); final String headerName; @@ -44,12 +42,10 @@ public class HttpForwardedHeaders { } } - final String host; final String port; final String proto; final String forClientHost; - final String ssl; public HttpForwardedHeaders(HttpServletRequest request) { @@ -58,7 +54,6 @@ public class HttpForwardedHeaders { port = null; proto = null; forClientHost = null; - ssl = null; return; } // read the values @@ -67,36 +62,34 @@ public class HttpForwardedHeaders { String portPrivate = getNormalizedHeader(request, ForwardedHeaderNameEnum.PORT); proto = getNormalizedHeader(request, ForwardedHeaderNameEnum.PROTO); forClientHost = getNormalizedHeader(request, ForwardedHeaderNameEnum.FOR); - ssl = getNormalizedHeader(request, ForwardedHeaderNameEnum.SSL); // normalize - if (StringUtils.contains(hostPrivate,HOST_PORT_SEPARATOR)) { + if (StringUtils.contains(hostPrivate, HOST_PORT_SEPARATOR)) { String hostCombined = hostPrivate; - hostPrivate = StringUtils.substringBefore(hostCombined,HOST_PORT_SEPARATOR); - portPrivate = validatePort(portPrivate,StringUtils.substringAfter(hostCombined,HOST_PORT_SEPARATOR)); + hostPrivate = StringUtils.substringBefore(hostCombined, HOST_PORT_SEPARATOR); + portPrivate = validatePort(portPrivate, StringUtils.substringAfter(hostCombined, HOST_PORT_SEPARATOR)); } host = hostPrivate; port = portPrivate; } private String getNormalizedHeader(HttpServletRequest request, ForwardedHeaderNameEnum header) { - return StringUtils.lowerCase(StringUtils.trim(request.getHeader(header.getHeaderName()))); } - private String validatePort(String headerPort, String hostPort){ + private String validatePort(String headerPort, String hostPort) { - if (StringUtils.isBlank(headerPort)){ - LOG.debug("Header X-Forwarded-Port is empty. Use port from X-Forwarded-Host [{}].",hostPort); + if (StringUtils.isBlank(headerPort)) { + LOG.debug("Header X-Forwarded-Port is empty. Use port from X-Forwarded-Host [{}].", hostPort); return hostPort; } - if (StringUtils.equals(headerPort, hostPort)){ - LOG.debug("Header X-Forwarded-Port is and port from X-Forwarded-Host [{}] are equal.",hostPort); + if (StringUtils.equals(headerPort, hostPort)) { + LOG.debug("Header X-Forwarded-Port is and port from X-Forwarded-Host [{}] are equal.", hostPort); return headerPort; } LOG.warn("Header X-Forwarded-Port [{}] is and port from X-Forwarded-Host [{}] mismatch. Fix the RP/load balancer configuration! " + - "Host port will be used as default value!",headerPort, hostPort); + "Host port will be used as default value!", headerPort, hostPort); return headerPort; } @@ -112,13 +105,13 @@ public class HttpForwardedHeaders { /** * Method returns null if the port is default port for given proto/schema. * For HTTP default port is 80 and for HTTPS default port is 443 - + * * @return non default ports or null */ public String getNonDefaultPort() { if (StringUtils.equals("http", proto) && StringUtils.equals("80", port) - || StringUtils.equals("https", proto) && StringUtils.equals("443", port)) { - LOG.debug("Ignore default port [{}] for proto/schema [{}].",port, proto); + || StringUtils.equals("https", proto) && StringUtils.equals("443", port)) { + LOG.debug("Ignore default port [{}] for proto/schema [{}].", port, proto); return null; } return port; @@ -132,10 +125,6 @@ public class HttpForwardedHeaders { return forClientHost; } - public String getSsl() { - return ssl; - } - @Override public String toString() { return "HttpForwardedHeaders{" + @@ -143,7 +132,6 @@ public class HttpForwardedHeaders { ", port='" + port + '\'' + ", proto='" + proto + '\'' + ", forClientHost='" + forClientHost + '\'' + - ", ssl='" + ssl + '\'' + '}'; } } 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 66406391c6d2afe5461aa12da07eedc4f875d1fa..f12a899acee8abdb4c411fae4a60607a225d2357 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 @@ -7,6 +7,7 @@ import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException; import eu.europa.ec.edelivery.smp.logging.SMPLogger; 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.springframework.scheduling.support.CronExpression; @@ -15,6 +16,7 @@ import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; +import java.util.Optional; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; import java.util.stream.Collectors; @@ -24,8 +26,10 @@ import static org.apache.commons.lang3.StringUtils.*; public class PropertyUtils { + private static final String MASKED_VALUE = "*******"; private static final SMPLogger LOG = SMPLoggerFactory.getLogger(PropertyUtils.class); - private static final String REG_EXP_SEPARATOR = "\\|"; + private static final String REG_EXP_VALUE_SEPARATOR = "\\|"; + private static final String REG_EXP_MAP_SEPARATOR = ":"; private static UrlValidator urlValidator = new UrlValidator(new String[]{"http", "https"}, UrlValidator.ALLOW_LOCAL_URLS); @@ -36,7 +40,6 @@ public class PropertyUtils { if (prop.isMandatory()) { throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Empty mandatory property: " + prop.getProperty()); } - ; return null; } @@ -44,64 +47,26 @@ public class PropertyUtils { return parsePropertyType(type, value, rootFolder); } - public static boolean isValidProperty(SMPPropertyEnum prop, String value) { + public static boolean isValidProperty(SMPPropertyEnum prop, String value, File confFolder) { if (StringUtils.isBlank(value)) { // empty/ null value is invalid return !prop.isMandatory(); } SMPPropertyTypeEnum type = prop.getPropertyType(); - return isValidPropertyType(type, value); + return isValidPropertyType(type, value, confFolder); } - public static boolean isValidPropertyType(SMPPropertyTypeEnum type, String value) { + public static boolean isValidPropertyType(SMPPropertyTypeEnum type, String value, File confFolder) { if (StringUtils.isBlank(value)) { return false; } - - switch (type) { - case BOOLEAN: - return value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false"); - case EMAIL: - return EmailValidator.getInstance().isValid(value); - case REGEXP: - try { - Pattern.compile(value); - return true; - } catch (PatternSyntaxException exception) { - return false; - } - case CRON_EXPRESSION: - return CronExpression.isValidExpression(value); - case INTEGER: - try { - Integer.parseInt(value); - return true; - } catch (NumberFormatException exception) { - return false; - } - case PATH: { - File f = new File(value); - if (!f.exists()) { - LOG.warn("Folder {} not exists. Try to create the folder.", f.getAbsolutePath()); - if (f.mkdirs()) { - LOG.info("Folder {} created.", f.getAbsolutePath()); - } - ; - } - return f.exists() && f.isDirectory(); - } - // nothing to validate - case URL: - return urlValidator.isValid(value); - case LIST_STRING: - case MAP_STRING: - case FILENAME: - case STRING: - return true; + try { + parsePropertyType(type, value, confFolder); + return true; + } catch (SMPRuntimeException ex) { + LOG.debug("Invalid property value [{}] for type [{}]. Error: " , value, type, ExceptionUtils.getRootCauseMessage(ex)); + return false; } - // property va - - return true; } public static Object parsePropertyType(SMPPropertyTypeEnum type, String value, File rootFolder) { @@ -111,50 +76,99 @@ public class PropertyUtils { switch (type) { case BOOLEAN: - return Boolean.valueOf(value.trim()); + if(StringUtils.equalsAnyIgnoreCase(trim(value),"true","false")) { + return Boolean.valueOf(value.trim()); + } + throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Invalid boolean value: [" + + value + "]. Error: Only {true, false} are allowed!"); case REGEXP: try { return Pattern.compile(value); - } catch (PatternSyntaxException exception) { - throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Invalid regular expression: " + value); + } catch (PatternSyntaxException ex) { + throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Invalid regular expression: [" + + value + "]. Error:" + ExceptionUtils.getRootCauseMessage(ex), ex); } case INTEGER: try { return Integer.parseInt(value); - } catch (NumberFormatException exception) { - throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Invalid integer: " + value); + } catch (NumberFormatException ex) { + throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Invalid integer: [" + + value + "]. Error:" + ExceptionUtils.getRootCauseMessage(ex), ex); } case LIST_STRING: { - return Arrays.asList(value.split(REG_EXP_SEPARATOR)); + return Arrays.asList(value.split(REG_EXP_VALUE_SEPARATOR)); } case MAP_STRING: { - return Arrays.asList(value.split(REG_EXP_SEPARATOR)).stream().collect(Collectors.toMap( - val -> trim(substringBefore(val, ":")), val -> trim(substringAfter(val, ":")))); + if (!value.contains(value)) { + throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Invalid map: [" + + value + "]. Error: Map must have at least one key:value entry!"); + } + return Arrays.asList(value.split(REG_EXP_VALUE_SEPARATOR)).stream().collect(Collectors.toMap( + val -> trim(substringBefore(val, REG_EXP_MAP_SEPARATOR)), val -> trim(substringAfter(val, REG_EXP_MAP_SEPARATOR)))); } case PATH: { + File file = new File(rootFolder, value); + if (!file.exists() && !file.mkdirs()) { + throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Folder: [" + + value + "] does not exist, and can not be created!"); + } + if (!file.isDirectory()) { + throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Path: [" + value + "] is not folder!"); + } return new File(value); } // nothing to validate case FILENAME: - return new File(rootFolder, value); + File file = new File(rootFolder, value); + if (!file.exists()) { + LOG.warn("File: [{}] does not exist. Full path: [{}].",value, file.getAbsolutePath()); + } + return file; case EMAIL: String trimVal = value.trim(); if (EmailValidator.getInstance().isValid(trimVal)) { return trimVal; } else { - throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Invalid email address: " + value); + throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Invalid email address: [" + value + "]."); } case URL: try { return new URL(value.trim()); - } catch (MalformedURLException e) { - throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Invalid URL address: " + value); + } catch (MalformedURLException ex) { + throw new SMPRuntimeException(ErrorCode.CONFIGURATION_ERROR, "Invalid URL address: [" + + value + "]. Error:" + ExceptionUtils.getRootCauseMessage(ex), ex); } case STRING: return value; } - // property va - return null; } + + + /** + * Return true for properties with sensitive data. For example the property value must not be logged + * or returned via WS! + * + * @param property - value to validate if contains sensitive data + * @return true if data is sensitive, else return false + */ + public static boolean isSensitiveData(String property) { + Optional<SMPPropertyEnum> propOpt = SMPPropertyEnum.getByProperty(trim(property)); + 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; + } + + /** + * Method returns 'masked' value for sensitive property data + * + * @param property + * @param value + * @return masked value for sensitive properties. Else it returns value! + */ + public static String getMaskedData(String property, String value) { + return isSensitiveData(property) ? MASKED_VALUE : value; + } } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SecurityUtils.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SecurityUtils.java index 0c99cd58d5d3c6b7e385f7b35be01a441a980440..7f056e4c0fb0cd5e2a7d3788434a470fbd4728be 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SecurityUtils.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SecurityUtils.java @@ -2,6 +2,8 @@ package eu.europa.ec.edelivery.smp.utils; import eu.europa.ec.edelivery.smp.data.ui.AccessTokenRO; import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException; +import eu.europa.ec.edelivery.smp.logging.SMPLogger; +import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory; import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; @@ -21,10 +23,12 @@ import java.time.OffsetDateTime; import java.util.Arrays; import java.util.Base64; import java.util.Enumeration; +import java.util.Random; import static eu.europa.ec.edelivery.smp.exceptions.ErrorCode.INTERNAL_ERROR; public class SecurityUtils { + public static final SMPLogger LOG = SMPLoggerFactory.getLogger(SecurityUtils.class); public static class Secret { final byte[] vector; @@ -112,13 +116,13 @@ public class SecurityUtils { return newAlias; } - public static String generateAuthenticationToken() { - String newKeyPassword; + public static String generateAuthenticationToken(boolean devMode) { + String newKeyPassword; try { newKeyPassword = RandomStringUtils.random(DEFAULT_PASSWORD_LENGTH, 0, VALID_PW_CHARS.length(), false, false, - VALID_PW_CHARS.toCharArray(), SecureRandom.getInstanceStrong()); + VALID_PW_CHARS.toCharArray(), devMode ? new Random() : SecureRandom.getInstanceStrong()); } catch (NoSuchAlgorithmException e) { String msg = "Error occurred while generation test password: No strong random algorithm. Error:" @@ -143,11 +147,11 @@ public class SecurityUtils { return newKeyPassword; } - public static AccessTokenRO generateAccessToken() { + public static AccessTokenRO generateAccessToken(boolean testMode) { AccessTokenRO accessToken = new AccessTokenRO(); accessToken.setGeneratedOn(OffsetDateTime.now()); accessToken.setIdentifier(generateAuthenticationTokenIdentifier()); - accessToken.setValue(generateAuthenticationToken()); + accessToken.setValue(generateAuthenticationToken(testMode)); return accessToken; } diff --git a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SessionSecurityUtils.java b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SessionSecurityUtils.java index ae803480f1f6696fdc911651d5292d75445ed9b2..4753cda3ce87dfc05129d750ed7a97076b41f9e2 100644 --- a/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SessionSecurityUtils.java +++ b/smp-server-library/src/main/java/eu/europa/ec/edelivery/smp/utils/SessionSecurityUtils.java @@ -27,7 +27,7 @@ public class SessionSecurityUtils { * ' * Currently authentication tokens supported to create na UI session. */ - public static final List<Class> sessionAuthenticationClasses = Arrays.asList(SMPAuthenticationToken.class, + protected static final List<Class> sessionAuthenticationClasses = Arrays.asList(SMPAuthenticationToken.class, CasAuthenticationToken.class); /** diff --git a/smp-server-library/src/main/resources/alert-mail-templates/credential_expired.ftl b/smp-server-library/src/main/resources/alert-mail-templates/credential_expired.ftl index 465446ce8d23eb6aaae276539d2a90057f717b91..0e33f951d41ce81c546cdfeabf040d02a3255d9d 100644 --- a/smp-server-library/src/main/resources/alert-mail-templates/credential_expired.ftl +++ b/smp-server-library/src/main/resources/alert-mail-templates/credential_expired.ftl @@ -107,7 +107,6 @@ <!-- / MARGIN RIGHT --> </tr> </table> - </td> </tr> </table> diff --git a/smp-server-library/src/main/resources/alert-mail-templates/credential_suspended.ftl b/smp-server-library/src/main/resources/alert-mail-templates/credential_suspended.ftl index 53c653cf13f909294c90fae482451d8e2fba56e6..b12b3a20d74c164f4210cd747b28c0ae8d620681 100644 --- a/smp-server-library/src/main/resources/alert-mail-templates/credential_suspended.ftl +++ b/smp-server-library/src/main/resources/alert-mail-templates/credential_suspended.ftl @@ -59,7 +59,7 @@ <!-- TITLE --> <tr> <td valign="top" align="left" style=" font-size: 20px; font-family: Arial, Helvetica, sans-serif; color: #000;"><br/> - Account is suspended</td> + Account is temporarily suspended</td> </tr> <!-- / TITLE --> @@ -83,7 +83,7 @@ <p><strong>Failed login attempt count:</strong> ${FAILED_LOGIN_ATTEMPT}</p> <p><strong>Last failed login time:</strong> ${LAST_LOGIN_FAILURE_DATETIME}</p> <p><strong>Suspended util</strong> ${SUSPENDED_UNTIL_DATETIME}</p> - <p><strong>Reporting time:</strong> ${REPORTING_TIME}</p> + <p><strong>Reporting time:</strong> ${REPORTING_DATETIME}</p> <p><strong>Alert level:</strong> ${ALERT_LEVEL}</p> <p><strong>Server name:</strong> ${SERVER_NAME}</p> </td> diff --git a/smp-server-library/src/main/resources/alert-mail-templates/credential_verification_failed.ftl b/smp-server-library/src/main/resources/alert-mail-templates/credential_verification_failed.ftl index 9f3de0870dd7c9758cc1b93f61a9fe22e63e89af..f51e982892cc030af5e324f0a608e65684770ce1 100644 --- a/smp-server-library/src/main/resources/alert-mail-templates/credential_verification_failed.ftl +++ b/smp-server-library/src/main/resources/alert-mail-templates/credential_verification_failed.ftl @@ -59,7 +59,7 @@ <!-- TITLE --> <tr> <td valign="top" align="left" style=" font-size: 20px; font-family: Arial, Helvetica, sans-serif; color: #000;"><br/> - Account is temporarly suspended</td> + Mail verification failed!</td> </tr> <!-- / TITLE --> @@ -82,7 +82,7 @@ <p><strong>Credential id:</strong> ${CREDENTIAL_ID}</p> <p><strong>Failed login attempt count:</strong> ${FAILED_LOGIN_ATTEMPT}</p> <p><strong>Last failed login time:</strong> ${LAST_LOGIN_FAILURE_DATETIME}</p> - <p><strong>Reporting time:</strong> ${REPORTING_TIME}</p> + <p><strong>Reporting time:</strong> ${REPORTING_DATETIME}</p> <p><strong>Alert level:</strong> ${ALERT_LEVEL}</p> <p><strong>Server name:</strong> ${SERVER_NAME}</p> </td> diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/config/DatabaseConfigTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/config/DatabaseConfigTest.java index 1a642977801ecb68469e12500e117e54c7a21fab..e3b1945097030e96c9472d0d1a1e17d38c1f5506 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/config/DatabaseConfigTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/config/DatabaseConfigTest.java @@ -14,13 +14,19 @@ import static org.junit.Assert.*; public class DatabaseConfigTest { + public static final String DATABASE_DRIVER="org.h2.Driver"; + public static final String DATABASE_DIALECT="org.hibernate.dialect.H2Dialect"; + public static final String DATABASE_URL="jdbc:h2:file:./target/myDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE;AUTO_SERVER=TRUE"; + public static final String DATABASE_USERNAME="smp-dev"; + public static final String DATABASE_PASS="smp-dev"; + DatabaseConfig testInstance = new DatabaseConfig(){{ // test properties from persistence-test-h2.properties jndiDatasourceName =null; - driver = "org.h2.Driver"; - url = "jdbc:h2:file:./target/myDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE;AUTO_SERVER=TRUE"; - username = "smp-dev"; - password = "smp-dev"; + driver = DATABASE_DRIVER; + url = DATABASE_URL; + username =DATABASE_USERNAME; + password =DATABASE_PASS; }}; @Test diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/config/FilePropertyTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/config/FilePropertyTest.java new file mode 100644 index 0000000000000000000000000000000000000000..d09f9c066e7e5dd09404b94a68ee8b3369199d07 --- /dev/null +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/config/FilePropertyTest.java @@ -0,0 +1,39 @@ +package eu.europa.ec.edelivery.smp.config; + +import org.junit.Test; + +import java.util.Properties; + +import static eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum.CLIENT_CERT_HEADER_ENABLED_DEPRECATED; +import static eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum.EXTERNAL_TLS_AUTHENTICATION_CLIENT_CERT_HEADER_ENABLED; +import static org.junit.Assert.*; + +public class FilePropertyTest { + + @Test + public void updateDeprecatedValues() { + String testValue = "test"; + Properties prop = new Properties(); + prop.setProperty(CLIENT_CERT_HEADER_ENABLED_DEPRECATED.getProperty(), testValue); + + Properties result = FileProperty.updateDeprecatedValues(prop); + + assertTrue(result.containsKey(EXTERNAL_TLS_AUTHENTICATION_CLIENT_CERT_HEADER_ENABLED.getProperty())); + assertEquals(testValue, result.getProperty(EXTERNAL_TLS_AUTHENTICATION_CLIENT_CERT_HEADER_ENABLED.getProperty())); + } + + @Test + public void getFileProperties() { + Properties result = FileProperty.getFileProperties("/test-smp.config.properties"); + assertNotNull(result); + assertEquals("This property is from custom file",result.getProperty("test.read.property")); + } + + @Test + public void getFilePropertiesLegacyFallback() { + Properties result = FileProperty.getFileProperties("/prop-not-exists.properties"); + assertNotNull(result); + // in the legacy fallback file the property is defined as: ${jdbc.user} + assertEquals("This property is from fallback legacy file",result.getProperty("test.read.property")); + } +} diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/config/PropertyInitializationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/config/PropertyInitializationTest.java index a65752040d09de685bc6214f98bfac95b51c52dd..8b0530351435477d9198fe1756a6e6d5dc276966 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/config/PropertyInitializationTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/config/PropertyInitializationTest.java @@ -3,25 +3,32 @@ package eu.europa.ec.edelivery.smp.config; import eu.europa.ec.edelivery.smp.data.model.DBConfiguration; import eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum; import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException; +import org.junit.Before; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaDialect; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import javax.sql.DataSource; import java.util.Properties; +import static eu.europa.ec.edelivery.smp.config.DatabaseConfigTest.*; +import static eu.europa.ec.edelivery.smp.config.FileProperty.*; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -public class PropertyInitializationTest { +public class PropertyInitializationTest { PropertyInitialization testInstance = new PropertyInitialization(); @Rule public ExpectedException expectedEx = ExpectedException.none(); - @Test public void testValidateProperties() { // when @@ -60,7 +67,7 @@ public class PropertyInitializationTest { public void getDatasourceBadConfigurationWithUrl() { // when Properties properties = new Properties(); - properties.setProperty(FileProperty.PROPERTY_DB_URL, "schema:/no@exists/db"); + properties.setProperty(PROPERTY_DB_URL, "schema:/no@exists/db"); expectedEx.expect(IllegalArgumentException.class); expectedEx.expectMessage("Property 'driverClassName' must not be empty"); @@ -71,10 +78,7 @@ public class PropertyInitializationTest { @Test public void getDatasourceByUrl() { - // when - Properties properties = new Properties(); - properties.setProperty(FileProperty.PROPERTY_DB_URL, "jdbc:h2:file:./target/myDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE;AUTO_SERVER=TRUE"); - properties.setProperty(FileProperty.PROPERTY_DB_DRIVER, "org.h2.Driver"); + Properties properties = getTestFileProperties(); DataSource dataSource = testInstance.getDatasource(properties); @@ -102,4 +106,28 @@ public class PropertyInitializationTest { assertEquals(SMPPropertyEnum.CS_DOCUMENTS.getDesc(), entry.getDescription()); } + @Test + public void getDatabaseProperties(){ + Properties properties = getTestFileProperties(); + + Properties databaseProperties = testInstance.getDatabaseProperties(properties); + + assertNotNull(databaseProperties); + + } + + protected Properties getTestFileProperties(){ + // create test database with SMP_CONFIGURATION TABLE + String url="jdbc:h2:mem:testdb;INIT=RUNSCRIPT FROM 'classpath:/create-configuration-table-h2.ddl'"; + Properties properties = new Properties(); + properties.setProperty(SMPPropertyEnum.CONFIGURATION_DIR.getProperty(), "./target/prop-init-test"); + properties.setProperty(PROPERTY_DB_URL, url); + properties.setProperty(PROPERTY_DB_DIALECT, DATABASE_DIALECT); + properties.setProperty(FileProperty.PROPERTY_DB_DRIVER, DATABASE_DRIVER); + properties.setProperty(FileProperty.PROPERTY_DB_USER, DATABASE_USERNAME); + properties.setProperty(FileProperty.PROPERTY_DB_TOKEN, ""); + properties.setProperty(FileProperty.PROPERTY_SMP_MODE_DEVELOPMENT, "true"); + return properties; + } + } \ No newline at end of file diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/config/PropertyUpdateListenerTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/config/PropertyUpdateListenerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..90dfa6071db5e0fd8c6e1834790f13b981ae6862 --- /dev/null +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/config/PropertyUpdateListenerTest.java @@ -0,0 +1,49 @@ +package eu.europa.ec.edelivery.smp.config; + +import eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; + +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import static eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum.ACCESS_TOKEN_FAIL_DELAY; +import static eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum.SMP_PROPERTY_REFRESH_CRON; +import static org.junit.Assert.*; + +public class PropertyUpdateListenerTest { + + PropertyUpdateListener testInstance = Mockito.spy(new PropertyUpdateListener() { + @Override + public void updateProperties(Map<SMPPropertyEnum, Object> properties) { + } + + @Override + public List<SMPPropertyEnum> handledProperties() { + return Collections.singletonList(ACCESS_TOKEN_FAIL_DELAY); + } + }); + + @Test + public void handlesProperty() { + assertTrue(testInstance.handlesProperty(ACCESS_TOKEN_FAIL_DELAY)); + assertFalse(testInstance.handlesProperty(SMP_PROPERTY_REFRESH_CRON)); + } + + @Test + public void updateProperty() { + Mockito.doNothing().when(testInstance).updateProperties(Mockito.anyMap()); + SMPPropertyEnum property = ACCESS_TOKEN_FAIL_DELAY; + String testValue = "test"; + + testInstance.updateProperty(property, testValue); + + ArgumentCaptor<Map<SMPPropertyEnum, Object>> propertyCapture = ArgumentCaptor.forClass(Map.class); + Mockito.verify(testInstance, Mockito.times(1)).updateProperties(propertyCapture.capture()); + assertEquals(1, propertyCapture.getValue().size()); + assertTrue(propertyCapture.getValue().containsKey(ACCESS_TOKEN_FAIL_DELAY)); + assertEquals(testValue, propertyCapture.getValue().get(ACCESS_TOKEN_FAIL_DELAY)); + } +} \ No newline at end of file diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/UserDaoIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/UserDaoIntegrationTest.java index 1e016c0af0e8f2e7ffa63fb662aba2c8d06c4539..68be572b22cf279c4f6babf84a7f6600bd3bbd90 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/UserDaoIntegrationTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/data/dao/UserDaoIntegrationTest.java @@ -136,7 +136,7 @@ public class UserDaoIntegrationTest extends AbstractBaseDao { testInstance.persistFlushDetach(u); //test - Optional<DBUser> ou = testInstance.findUserByIdentifier(TestConstants.USERNAME_1); + Optional<DBUser> ou = testInstance.findUserByIdentifier(TestConstants.USERNAME_TOKEN_1); assertNotSame(u , ou.get()); assertEquals(u, ou.get()); assertEquals(u.getEmailAddress(), ou.get().getEmailAddress()); diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceIntegrationTest.java index 1544e94e4d475cd6088585c6a2d25cd41e9f177e..9bd050a3b8ec55f4ef04d1912c7ca3a3eb9ed2ab 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceIntegrationTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AbstractServiceIntegrationTest.java @@ -11,6 +11,7 @@ import eu.europa.ec.edelivery.smp.data.model.DBServiceGroup; import eu.europa.ec.edelivery.smp.data.model.DBServiceMetadata; import eu.europa.ec.edelivery.smp.data.model.DBUser; import eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum; +import eu.europa.ec.edelivery.smp.services.mail.MailService; import eu.europa.ec.edelivery.smp.services.ui.UIKeystoreService; import eu.europa.ec.edelivery.smp.services.ui.UITruststoreService; import eu.europa.ec.edelivery.smp.sml.SmlConnector; @@ -41,13 +42,14 @@ import static eu.europa.ec.edelivery.smp.testutil.TestConstants.*; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = {H2JPATestConfig.class, - CaseSensitivityNormalizer.class,SmlConnector.class,ServiceMetadataSigner.class, + CaseSensitivityNormalizer.class,SmlConnector.class,ServiceMetadataSigner.class, MailService.class, ServiceGroupService.class, DomainService.class, ServiceMetadataService.class, - ServiceGroupDao.class,ServiceMetadataDao.class, DomainDao.class, UserDao.class,DBAssertion.class, ConfigurationDao.class, + ServiceGroupDao.class,ServiceMetadataDao.class, DomainDao.class, UserDao.class,DBAssertion.class, ConfigurationDao.class, AlertDao.class, UITruststoreService.class, UIKeystoreService.class, ConversionTestConfig.class, SMLIntegrationService.class, CRLVerifierService.class, ConfigurationService.class, - ServicesBeansConfiguration.class}) + ServicesBeansConfiguration.class, + AlertService.class}) @Sql(scripts = {"classpath:cleanup-database.sql", "classpath:basic_conf_data-h2.sql" }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD, config = @SqlConfig diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AlertServiceTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AlertServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..7822c704fb5ba3aa8ff1550a5cd6d90c140bf397 --- /dev/null +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/AlertServiceTest.java @@ -0,0 +1,402 @@ +package eu.europa.ec.edelivery.smp.services; + +import eu.europa.ec.edelivery.smp.data.dao.AlertDao; +import eu.europa.ec.edelivery.smp.data.model.DBAlert; +import eu.europa.ec.edelivery.smp.data.model.DBUser; +import eu.europa.ec.edelivery.smp.data.ui.enums.AlertLevelEnum; +import eu.europa.ec.edelivery.smp.data.ui.enums.AlertTypeEnum; +import eu.europa.ec.edelivery.smp.data.ui.enums.CredentialTypeEnum; +import eu.europa.ec.edelivery.smp.services.mail.MailModel; +import eu.europa.ec.edelivery.smp.services.mail.MailService; +import eu.europa.ec.edelivery.smp.services.mail.prop.CredentialSuspendedProperties; +import eu.europa.ec.edelivery.smp.services.mail.prop.CredentialVerificationFailedProperties; +import eu.europa.ec.edelivery.smp.services.mail.prop.CredentialsExpirationProperties; +import eu.europa.ec.edelivery.smp.testutil.TestDBUtils; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; + +import java.time.OffsetDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.Properties; +import java.util.stream.Collectors; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +public class AlertServiceTest { + + AlertDao alertDao = Mockito.mock(AlertDao.class); + MailService mailService = Mockito.mock(MailService.class); + ConfigurationService configurationService = Mockito.mock(ConfigurationService.class); + + + AlertService testInstance = new AlertService(alertDao, mailService, configurationService); + + @Test + public void testCreateAlert() { + String mailSubject = "mailSubject"; + String mailTo = "mailTo"; + AlertLevelEnum level = AlertLevelEnum.MEDIUM; + AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_EXPIRED; + + DBAlert alert = testInstance.createAlert(mailSubject, mailTo, level, alertType); + + assertNotNull(alert); + assertNull(alert.getId()); + assertEquals(mailSubject, alert.getMailSubject()); + assertEquals(mailTo, alert.getMailTo()); + assertEquals(level, alert.getAlertLevel()); + assertEquals(alertType, alert.getAlertType()); + assertFalse(alert.isProcessed()); + assertNotNull(alert.getReportingTime()); + + } + + @Test + public void testSubmitAlertMailNoMail() { + + DBAlert alert = new DBAlert(); + + testInstance.submitAlertMail(alert); + + verify(mailService, Mockito.never()).sendMail(Mockito.any(), Mockito.anyString(), Mockito.anyString()); + } + + @Test + public void alertBeforeUsernamePasswordExpire() { + // given + DBUser user = TestDBUtils.createDBUser("alertBeforeUsernamePasswordExpire"); + String mailSubject = "mail subject"; + String mailFrom = "mail.from@test.eu"; + AlertLevelEnum alertLevel = AlertLevelEnum.MEDIUM; + user.setPasswordExpireOn(OffsetDateTime.now().plusDays(1)); + doReturn(mailSubject).when(configurationService).getAlertBeforeExpirePasswordMailSubject(); + doReturn(alertLevel).when(configurationService).getAlertBeforeExpirePasswordLevel(); + doReturn(mailFrom).when(configurationService).getAlertEmailFrom(); + + AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_IMMINENT_EXPIRATION; + List<String> expectedTemplateProperties = Arrays.asList(CredentialsExpirationProperties.values()).stream() + .map(CredentialsExpirationProperties::name).collect(Collectors.toList()); + // when + testInstance.alertBeforeUsernamePasswordExpire(user); + // then + assertAlertSend(alertType, user.getEmailAddress(), mailFrom, mailSubject, + expectedTemplateProperties); + + verify(configurationService, times(1)).getAlertBeforeExpirePasswordMailSubject(); + verify(configurationService, times(1)).getAlertBeforeExpirePasswordLevel(); + verify(configurationService, times(1)).getAlertEmailFrom(); + } + + @Test + public void alertUsernamePasswordExpired() { + // given + DBUser user = TestDBUtils.createDBUser("alertUsernamePasswordExpired"); + String mailSubject = "mail subject"; + String mailFrom = "mail.from@test.eu"; + AlertLevelEnum alertLevel = AlertLevelEnum.MEDIUM; + user.setPasswordExpireOn(OffsetDateTime.now().plusDays(1)); + doReturn(mailSubject).when(configurationService).getAlertExpiredPasswordMailSubject(); + doReturn(alertLevel).when(configurationService).getAlertExpiredPasswordLevel(); + doReturn(mailFrom).when(configurationService).getAlertEmailFrom(); + AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_EXPIRED; + List<String> expectedTemplateProperties = Arrays.asList(CredentialsExpirationProperties.values()).stream() + .map(CredentialsExpirationProperties::name).collect(Collectors.toList()); + // when + testInstance.alertUsernamePasswordExpired(user); + // then + assertAlertSend(alertType, user.getEmailAddress(), mailFrom, mailSubject, + expectedTemplateProperties); + + verify(configurationService, times(1)).getAlertExpiredPasswordMailSubject(); + verify(configurationService, times(1)).getAlertExpiredPasswordLevel(); + verify(configurationService, times(1)).getAlertEmailFrom(); + } + + @Test + public void alertBeforeAccessTokenExpire() { + // given + DBUser user = TestDBUtils.createDBUser("alertBeforeAccessTokenExpire"); + String mailSubject = "mail subject"; + String mailFrom = "mail.from@test.eu"; + AlertLevelEnum alertLevel = AlertLevelEnum.MEDIUM; + user.setAccessTokenExpireOn(OffsetDateTime.now().plusDays(1)); + doReturn(mailSubject).when(configurationService).getAlertBeforeExpireAccessTokenMailSubject(); + doReturn(alertLevel).when(configurationService).getAlertBeforeExpireAccessTokenLevel(); + doReturn(mailFrom).when(configurationService).getAlertEmailFrom(); + + AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_IMMINENT_EXPIRATION; + List<String> expectedTemplateProperties = Arrays.asList(CredentialsExpirationProperties.values()).stream() + .map(CredentialsExpirationProperties::name).collect(Collectors.toList()); + // when + testInstance.alertBeforeAccessTokenExpire(user); + // then + assertAlertSend(alertType, user.getEmailAddress(), mailFrom, mailSubject, + expectedTemplateProperties); + + verify(configurationService, times(1)).getAlertBeforeExpireAccessTokenMailSubject(); + verify(configurationService, times(1)).getAlertBeforeExpireAccessTokenLevel(); + verify(configurationService, times(1)).getAlertEmailFrom(); + } + + @Test + public void alertAccessTokenExpired() { + // given + DBUser user = TestDBUtils.createDBUser("alertAccessTokenExpired"); + String mailSubject = "mail subject"; + String mailFrom = "mail.from@test.eu"; + AlertLevelEnum alertLevel = AlertLevelEnum.MEDIUM; + user.setAccessTokenExpireOn(OffsetDateTime.now().plusDays(1)); + doReturn(mailSubject).when(configurationService).getAlertExpiredAccessTokenMailSubject(); + doReturn(alertLevel).when(configurationService).getAlertExpiredAccessTokenLevel(); + doReturn(mailFrom).when(configurationService).getAlertEmailFrom(); + AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_EXPIRED; + List<String> expectedTemplateProperties = Arrays.asList(CredentialsExpirationProperties.values()).stream() + .map(CredentialsExpirationProperties::name).collect(Collectors.toList()); + // when + testInstance.alertAccessTokenExpired(user); + // then + assertAlertSend(alertType, user.getEmailAddress(), mailFrom, mailSubject, + expectedTemplateProperties); + + verify(configurationService, times(1)).getAlertExpiredAccessTokenMailSubject(); + verify(configurationService, times(1)).getAlertExpiredAccessTokenLevel(); + verify(configurationService, times(1)).getAlertEmailFrom(); + } + + @Test + public void alertBeforeCertificateExpire() { + // given + DBUser user = TestDBUtils.createDBUser("user", "alertBeforeCertificateExpire"); + String mailSubject = "mail subject"; + String mailFrom = "mail.from@test.eu"; + AlertLevelEnum alertLevel = AlertLevelEnum.MEDIUM; + doReturn(mailSubject).when(configurationService).getAlertBeforeExpireCertificateMailSubject(); + doReturn(alertLevel).when(configurationService).getAlertBeforeExpireCertificateLevel(); + doReturn(mailFrom).when(configurationService).getAlertEmailFrom(); + AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_IMMINENT_EXPIRATION; + List<String> expectedTemplateProperties = Arrays.asList(CredentialsExpirationProperties.values()).stream() + .map(CredentialsExpirationProperties::name).collect(Collectors.toList()); + // when + testInstance.alertBeforeCertificateExpire(user); + // then + assertAlertSend(alertType, user.getEmailAddress(), mailFrom, mailSubject, + expectedTemplateProperties); + + verify(configurationService, times(1)).getAlertBeforeExpireCertificateMailSubject(); + verify(configurationService, times(1)).getAlertBeforeExpireCertificateLevel(); + verify(configurationService, times(1)).getAlertEmailFrom(); + } + + @Test + public void alertCertificateExpired() { + // given + DBUser user = TestDBUtils.createDBUser("user", "alertCertificateExpired"); + String mailSubject = "mail subject"; + String mailFrom = "mail.from@test.eu"; + AlertLevelEnum alertLevel = AlertLevelEnum.MEDIUM; + doReturn(mailSubject).when(configurationService).getAlertExpiredCertificateMailSubject(); + doReturn(alertLevel).when(configurationService).getAlertExpiredCertificateLevel(); + doReturn(mailFrom).when(configurationService).getAlertEmailFrom(); + AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_EXPIRED; + List<String> expectedTemplateProperties = Arrays.asList(CredentialsExpirationProperties.values()).stream() + .map(CredentialsExpirationProperties::name).collect(Collectors.toList()); + + // when + testInstance.alertCertificateExpired(user); + // then + assertAlertSend(alertType, user.getEmailAddress(), mailFrom, mailSubject, + expectedTemplateProperties); + + verify(configurationService, times(1)).getAlertExpiredCertificateMailSubject(); + verify(configurationService, times(1)).getAlertExpiredCertificateLevel(); + verify(configurationService, times(1)).getAlertEmailFrom(); + } + + @Test + public void submitAlertMail() { + String mailTo = "test.mail@domain.eu"; + String mailFrom = "test.mail@domain.eu"; + String mailSubject = "mailSubject"; + AlertTypeEnum template = AlertTypeEnum.CREDENTIAL_IMMINENT_EXPIRATION; + DBAlert alert = new DBAlert(); + alert.setAlertType(template); + alert.setMailTo(mailTo); + alert.setMailSubject(mailSubject); + alert.addProperty("test", "testValue"); + doReturn(mailFrom).when(configurationService).getAlertEmailFrom(); + + testInstance.submitAlertMail(alert); + + ArgumentCaptor<MailModel<Properties>> argModel = ArgumentCaptor.forClass(MailModel.class); + ArgumentCaptor<String> argMailTo = ArgumentCaptor.forClass(String.class); + ArgumentCaptor<String> argFrom = ArgumentCaptor.forClass(String.class); + + verify(mailService, times(1)) + .sendMail(argModel.capture(), argFrom.capture(), argMailTo.capture()); + verify(alertDao, times(1)).update(alert); + + assertEquals(mailTo, argMailTo.getValue()); + assertEquals(mailFrom, argFrom.getValue()); + assertEquals(mailSubject, argModel.getValue().getSubject()); + assertEquals(template.getTemplate(), argModel.getValue().getTemplatePath()); + assertEquals(1, argModel.getValue().getModel().size()); + } + + @Test + public void alertUsernameCredentialVerificationFailed() { + DBUser user = TestDBUtils.createDBUser("user"); + String mailSubject = "mail subject"; + String mailFrom = "mail.from@test.eu"; + user.setSequentialLoginFailureCount(5); + user.setLastFailedLoginAttempt(OffsetDateTime.now()); + AlertLevelEnum alertLevel = AlertLevelEnum.MEDIUM; + + doReturn(true).when(configurationService).getAlertUserLoginFailureEnabled(); + doReturn(mailSubject).when(configurationService).getAlertUserLoginFailureSubject(); + doReturn(alertLevel).when(configurationService).getAlertUserLoginFailureLevel(); + doReturn(mailFrom).when(configurationService).getAlertEmailFrom(); + + AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_VERIFICATION_FAILED; + List<String> expectedTemplateProperties = Arrays.asList(CredentialVerificationFailedProperties.values()).stream() + .map(CredentialVerificationFailedProperties::name).collect(Collectors.toList()); + + // when + testInstance.alertCredentialVerificationFailed(user, CredentialTypeEnum.USERNAME_PASSWORD); + // then + assertAlertSend(alertType, user.getEmailAddress(), mailFrom, mailSubject, + expectedTemplateProperties); + + verify(configurationService, times(1)).getAlertUserLoginFailureEnabled(); + verify(configurationService, times(1)).getAlertUserLoginFailureSubject(); + verify(configurationService, times(1)).getAlertUserLoginFailureLevel(); + verify(configurationService, times(1)).getAlertEmailFrom(); + } + + @Test + public void alertTokenCredentialVerificationFailed() { + DBUser user = TestDBUtils.createDBUser("user", "alertCertificateExpired"); + String mailSubject = "mail subject"; + String mailFrom = "mail.from@test.eu"; + user.setSequentialTokenLoginFailureCount(5); + user.setLastTokenFailedLoginAttempt(OffsetDateTime.now()); + AlertLevelEnum alertLevel = AlertLevelEnum.MEDIUM; + + doReturn(true).when(configurationService).getAlertUserLoginFailureEnabled(); + doReturn(mailSubject).when(configurationService).getAlertUserLoginFailureSubject(); + doReturn(alertLevel).when(configurationService).getAlertUserLoginFailureLevel(); + doReturn(mailFrom).when(configurationService).getAlertEmailFrom(); + //doReturn(123456).when(configurationService).getLoginSuspensionTimeInSeconds(); + AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_VERIFICATION_FAILED; + List<String> expectedTemplateProperties = Arrays.asList(CredentialVerificationFailedProperties.values()).stream() + .map(CredentialVerificationFailedProperties::name).collect(Collectors.toList()); + + // when + testInstance.alertCredentialVerificationFailed(user, CredentialTypeEnum.ACCESS_TOKEN); + // then + assertAlertSend(alertType, user.getEmailAddress(), mailFrom, mailSubject, + expectedTemplateProperties); + + verify(configurationService, times(1)).getAlertUserLoginFailureEnabled(); + verify(configurationService, times(1)).getAlertUserLoginFailureSubject(); + verify(configurationService, times(1)).getAlertUserLoginFailureLevel(); + verify(configurationService, times(1)).getAlertEmailFrom(); + } + + @Test + public void alertUsernameCredentialsSuspended() { + DBUser user = TestDBUtils.createDBUser("user", "alertCertificateExpired"); + String mailSubject = "mail subject"; + String mailFrom = "mail.from@test.eu"; + user.setSequentialLoginFailureCount(5); + user.setLastFailedLoginAttempt(OffsetDateTime.now()); + AlertLevelEnum alertLevel = AlertLevelEnum.MEDIUM; + + doReturn(true).when(configurationService).getAlertUserSuspendedEnabled(); + doReturn(mailSubject).when(configurationService).getAlertUserSuspendedSubject(); + doReturn(alertLevel).when(configurationService).getAlertUserSuspendedLevel(); + doReturn(mailFrom).when(configurationService).getAlertEmailFrom(); + doReturn(123456).when(configurationService).getLoginSuspensionTimeInSeconds(); + AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_SUSPENDED; + List<String> expectedTemplateProperties = Arrays.asList(CredentialSuspendedProperties.values()).stream() + .map(CredentialSuspendedProperties::name).collect(Collectors.toList()); + + // when + testInstance.alertCredentialsSuspended(user, CredentialTypeEnum.USERNAME_PASSWORD); + // then + assertAlertSend(alertType, user.getEmailAddress(), mailFrom, mailSubject, + expectedTemplateProperties); + + verify(configurationService, times(1)).getAlertUserSuspendedEnabled(); + verify(configurationService, times(1)).getAlertUserSuspendedSubject(); + verify(configurationService, times(1)).getAlertUserSuspendedLevel(); + verify(configurationService, times(1)).getAlertEmailFrom(); + } + + @Test + public void alertTokenCredentialsSuspended() { + DBUser user = TestDBUtils.createDBUser("user", "alertCertificateExpired"); + String mailSubject = "mail subject"; + String mailFrom = "mail.from@test.eu"; + user.setSequentialTokenLoginFailureCount(5); + user.setLastTokenFailedLoginAttempt(OffsetDateTime.now()); + AlertLevelEnum alertLevel = AlertLevelEnum.MEDIUM; + + doReturn(true).when(configurationService).getAlertUserSuspendedEnabled(); + doReturn(mailSubject).when(configurationService).getAlertUserSuspendedSubject(); + doReturn(alertLevel).when(configurationService).getAlertUserSuspendedLevel(); + doReturn(mailFrom).when(configurationService).getAlertEmailFrom(); + doReturn(123456).when(configurationService).getLoginSuspensionTimeInSeconds(); + AlertTypeEnum alertType = AlertTypeEnum.CREDENTIAL_SUSPENDED; + List<String> expectedTemplateProperties = Arrays.asList(CredentialSuspendedProperties.values()).stream() + .map(CredentialSuspendedProperties::name).collect(Collectors.toList()); + + // when + testInstance.alertCredentialsSuspended(user, CredentialTypeEnum.ACCESS_TOKEN); + // then + assertAlertSend(alertType, user.getEmailAddress(), mailFrom, mailSubject, + expectedTemplateProperties); + + verify(configurationService, times(1)).getAlertUserSuspendedEnabled(); + verify(configurationService, times(1)).getAlertUserSuspendedSubject(); + verify(configurationService, times(1)).getAlertUserSuspendedLevel(); + verify(configurationService, times(1)).getAlertEmailFrom(); + } + + + public void assertAlertSend(AlertTypeEnum alertType, String mailTo, String mailFrom, String mailSubject, + List<String> templateProperties) { + + ArgumentCaptor<MailModel<Properties>> argModel = ArgumentCaptor.forClass(MailModel.class); + ArgumentCaptor<String> argMailFrom = ArgumentCaptor.forClass(String.class); + ArgumentCaptor<String> argMailTo = ArgumentCaptor.forClass(String.class); + ArgumentCaptor<DBAlert> argAlert = ArgumentCaptor.forClass(DBAlert.class); + ArgumentCaptor<DBAlert> argAlertUpdate = ArgumentCaptor.forClass(DBAlert.class); + + + verify(alertDao, times(1)).persistFlushDetach(argAlert.capture()); + verify(mailService, times(1)) + .sendMail(argModel.capture(), argMailFrom.capture(), argMailTo.capture()); + + verify(alertDao, times(1)).update(argAlertUpdate.capture()); + + assertEquals(mailTo, argMailTo.getValue()); + assertEquals(mailFrom, argMailFrom.getValue()); + + + MailModel<Properties> model = argModel.getValue(); + assertEquals(alertType.getTemplate(), model.getTemplatePath()); + assertEquals(mailSubject, model.getSubject()); + + // test to contain all properties + for (String prop : templateProperties) { + + assertTrue(prop, model.getModel().keySet().contains(prop)); + } + assertEquals(templateProperties.size(), model.getModel().size()); + + + } +} \ No newline at end of file diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ConfigurationServiceAllGetMethodsTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ConfigurationServiceAllGetMethodsTest.java index 5ae9b715809f214efcd95a80afebd03d2beb69c2..0cafecf101b35bbf2229f03f42fc3055ac9900e7 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ConfigurationServiceAllGetMethodsTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ConfigurationServiceAllGetMethodsTest.java @@ -1,6 +1,7 @@ package eu.europa.ec.edelivery.smp.services; import eu.europa.ec.edelivery.smp.data.dao.ConfigurationDao; +import eu.europa.ec.edelivery.smp.data.ui.enums.AlertLevelEnum; import eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum; import org.apache.commons.lang3.exception.ExceptionUtils; import org.apache.commons.lang3.reflect.MethodUtils; @@ -34,9 +35,6 @@ public class ConfigurationServiceAllGetMethodsTest { } } - - - ConfigurationDao configurationDaoMock = mock(ConfigurationDao.class); ConfigurationService testInstance = new ConfigurationService(configurationDaoMock); @@ -50,13 +48,14 @@ public class ConfigurationServiceAllGetMethodsTest { //{HTTP_FORWARDED_HEADERS_ENABLED, Boolean.TRUE, "", true}, {HTTP_HSTS_MAX_AGE, 1234, "getHttpHeaderHstsMaxAge", true}, {HTTP_HEADER_SEC_POLICY, TEST_STRING, "getHttpHeaderContentSecurityPolicy", true}, - //{HTTP_PROXY_HOST,TEST_STRING, "", true}, - {HTTP_NO_PROXY_HOSTS, TEST_STRING, "getHttpNoProxyHosts", false}, + {HTTP_NO_PROXY_HOSTS,TEST_STRING, "getHttpNoProxyHosts", false}, + {HTTP_PROXY_HOST, TEST_STRING, "getHttpProxyHost", false}, {HTTP_PROXY_PASSWORD, TEST_STRING, "getProxyCredentialToken", true}, - //{HTTP_PROXY_PORT, TEST_STRING, "", true}, + {HTTP_PROXY_PORT, 8800, "getHttpProxyPort", true}, {HTTP_PROXY_USER, TEST_STRING, "getProxyUsername", true}, {PARTC_SCH_REGEXP, TEST_REXEXP,"getParticipantIdentifierSchemeRexExp", true}, - {PARTC_SCH_REGEXP_MSG, TEST_STRING, "getParticipantIdentifierSchemeRexExpMessage", true}, + {PARTC_SCH_REGEXP, TEST_STRING, "getParticipantIdentifierSchemeRexExpPattern", false}, + {PARTC_EBCOREPARTYID_CONCATENATE, Boolean.FALSE, "getForceConcatenateEBCorePartyId", true}, {CS_PARTICIPANTS, TEST_STRING_LIST, "getCaseSensitiveParticipantScheme", true}, {CS_DOCUMENTS, TEST_STRING_LIST, "getCaseSensitiveDocumentScheme", true}, {SML_ENABLED, Boolean.FALSE, "isSMLIntegrationEnabled", true}, @@ -87,6 +86,11 @@ public class ConfigurationServiceAllGetMethodsTest { {PASSWORD_POLICY_REGULAR_EXPRESSION, TEST_REXEXP, "getPasswordPolicyRexExp", true}, {PASSWORD_POLICY_MESSAGE, TEST_STRING, "getPasswordPolicyValidationMessage", false}, {PASSWORD_POLICY_VALID_DAYS, 2, "getPasswordPolicyValidDays", true}, + {PASSWORD_POLICY_REGULAR_EXPRESSION, TEST_STRING, "getPasswordPolicyRexExpPattern", false}, + {PASSWORD_POLICY_WARNING_DAYS_BEFORE_EXPIRE, 10, "getPasswordPolicyUIWarningDaysBeforeExpire", true}, + {PASSWORD_POLICY_FORCE_CHANGE_EXPIRED, Boolean.TRUE, "getPasswordPolicyForceChangeIfExpired", true}, + {USER_LOGIN_FAIL_DELAY,1000, "getLoginFailDelayInMilliSeconds", true}, + {ACCESS_TOKEN_FAIL_DELAY,1000, "getAccessTokenLoginFailDelayInMilliSeconds", true}, {USER_MAX_FAILED_ATTEMPTS, 55, "getLoginMaxAttempts", true}, {USER_SUSPENSION_TIME, 3600, "getLoginSuspensionTimeInSeconds", true}, {ACCESS_TOKEN_POLICY_VALID_DAYS, 1212, "getAccessTokenPolicyValidDays", true}, @@ -101,6 +105,45 @@ public class ConfigurationServiceAllGetMethodsTest { {SSO_CAS_TOKEN_VALIDATION_URLPATH, TEST_STRING, "getCasURLTokenValidation", true}, {SSO_CAS_TOKEN_VALIDATION_PARAMS, TEST_MAP, "getCasTokenValidationParams", true}, {SSO_CAS_TOKEN_VALIDATION_GROUPS, TEST_STRING_LIST, "getCasURLTokenValidationGroups", true}, + {PARTC_EBCOREPARTYID_CONCATENATE, Boolean.FALSE, "getForceConcatenateEBCorePartyId", true}, + {PARTC_SCH_MANDATORY, Boolean.FALSE, "getParticipantSchemeMandatory", true}, + {SMP_CLUSTER_ENABLED, Boolean.FALSE, "isClusterEnabled", true}, + {ENCODED_SLASHES_ALLOWED_IN_URL, Boolean.FALSE, "encodedSlashesAllowedInUrl", true}, + {SMP_ALERT_CREDENTIALS_SERVER, TEST_STRING, "getTargetServerForCredentialValidation", true}, + {SML_TLS_SERVER_CERT_SUBJECT_REGEXP, TEST_STRING, "getSMLIntegrationServerCertSubjectRegExpPattern", false}, + {SSO_CAS_SMP_LOGIN_URI, TEST_STRING, "getCasSMPLoginRelativePath", true}, + {ALERT_USER_LOGIN_FAILURE_ENABLED, Boolean.FALSE, "getAlertUserLoginFailureEnabled", true}, + {ALERT_USER_SUSPENDED_ENABLED, Boolean.FALSE, "getAlertUserSuspendedEnabled", true}, + {ALERT_USER_SUSPENDED_MAIL_SUBJECT, TEST_STRING, "getAlertUserSuspendedSubject", true}, + {ALERT_PASSWORD_BEFORE_EXPIRATION_ENABLED, Boolean.FALSE, "getAlertBeforeExpirePasswordEnabled", true}, + {ALERT_PASSWORD_BEFORE_EXPIRATION_PERIOD, 10, "getAlertBeforeExpirePasswordPeriod", true}, + {ALERT_PASSWORD_BEFORE_EXPIRATION_INTERVAL, 10, "getAlertBeforeExpirePasswordInterval", true}, + {ALERT_PASSWORD_BEFORE_EXPIRATION_MAIL_SUBJECT, TEST_STRING, "getAlertBeforeExpirePasswordMailSubject", true}, + {ALERT_PASSWORD_EXPIRED_ENABLED, Boolean.FALSE, "getAlertExpiredPasswordEnabled", true}, + {ALERT_PASSWORD_EXPIRED_PERIOD, 10, "getAlertExpiredPasswordPeriod", true}, + {ALERT_PASSWORD_EXPIRED_INTERVAL, 10, "getAlertExpiredPasswordInterval", true}, + {ALERT_PASSWORD_EXPIRED_MAIL_SUBJECT, TEST_STRING, "getAlertExpiredPasswordMailSubject", true}, + {ALERT_ACCESS_TOKEN_BEFORE_EXPIRATION_ENABLED, Boolean.FALSE, "getAlertBeforeExpireAccessTokenEnabled", true}, + {ALERT_ACCESS_TOKEN_BEFORE_EXPIRATION_PERIOD, 10, "getAlertBeforeExpireAccessTokenPeriod", true}, + {ALERT_ACCESS_TOKEN_BEFORE_EXPIRATION_INTERVAL, 10, "getAlertBeforeExpireAccessTokenInterval", true}, + {ALERT_ACCESS_TOKEN_BEFORE_EXPIRATION_MAIL_SUBJECT, TEST_STRING, "getAlertBeforeExpireAccessTokenMailSubject", true}, + {ALERT_ACCESS_TOKEN_EXPIRED_ENABLED, Boolean.FALSE, "getAlertExpiredAccessTokenEnabled", true}, + {ALERT_ACCESS_TOKEN_EXPIRED_PERIOD, 10, "getAlertExpiredAccessTokenPeriod", true}, + {ALERT_ACCESS_TOKEN_EXPIRED_INTERVAL, 10, "getAlertExpiredAccessTokenInterval", true}, + {ALERT_ACCESS_TOKEN_EXPIRED_MAIL_SUBJECT, TEST_STRING, "getAlertExpiredAccessTokenMailSubject", true}, + + {ALERT_CERTIFICATE_BEFORE_EXPIRATION_ENABLED, Boolean.FALSE, "getAlertBeforeExpireCertificateEnabled", true}, + {ALERT_CERTIFICATE_BEFORE_EXPIRATION_PERIOD, 10, "getAlertBeforeExpireCertificatePeriod", true}, + {ALERT_CERTIFICATE_BEFORE_EXPIRATION_INTERVAL, 10, "getAlertBeforeExpireCertificateInterval", true}, + {ALERT_CERTIFICATE_BEFORE_EXPIRATION_MAIL_SUBJECT, TEST_STRING, "getAlertBeforeExpireCertificateMailSubject", true}, + + {ALERT_CERTIFICATE_EXPIRED_ENABLED, Boolean.FALSE, "getAlertExpiredCertificateEnabled", true}, + {ALERT_CERTIFICATE_EXPIRED_PERIOD, 10, "getAlertExpiredCertificatePeriod", true}, + {ALERT_CERTIFICATE_EXPIRED_INTERVAL, 10, "getAlertExpiredCertificateInterval", true}, + {ALERT_CERTIFICATE_EXPIRED_MAIL_SUBJECT, TEST_STRING, "getAlertExpiredCertificateMailSubject", true}, + {SMP_ALERT_BATCH_SIZE, 10, "getAlertCredentialsBatchSize", true}, + {SMP_ALERT_MAIL_FROM, TEST_STRING, "getAlertEmailFrom", true}, + }); } private final SMPPropertyEnum property; @@ -124,7 +167,10 @@ public class ConfigurationServiceAllGetMethodsTest { doReturn(value).when(configurationDaoMock).getCachedProperty(property); } Object result = MethodUtils.invokeExactMethod(testInstance, methodName); - - assertEquals(value, result); + if (result instanceof Optional){ + assertEquals(value, ((Optional<?>) result).get()); + }else { + assertEquals(value, result); + } } } \ No newline at end of file diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/CredentialValidatorServiceTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/CredentialValidatorServiceTest.java index 8feea6c635334a0e5766c32c6fd16f17184b8b61..8db66fa83699f50bf62ca264782d502b1b27e81a 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/CredentialValidatorServiceTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/CredentialValidatorServiceTest.java @@ -1,15 +1,18 @@ package eu.europa.ec.edelivery.smp.services; import eu.europa.ec.edelivery.smp.data.dao.UserDao; +import eu.europa.ec.edelivery.smp.data.model.DBUser; import eu.europa.ec.edelivery.smp.utils.HttpUtils; import org.junit.Assert; import org.junit.Test; +import org.mockito.ArgumentCaptor; import org.mockito.Mockito; +import java.util.Collections; import java.util.regex.Pattern; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; @@ -48,4 +51,202 @@ public class CredentialValidatorServiceTest { assertFalse(result); verify(mockConfigService, Mockito.times(1)).getTargetServerForCredentialValidation(); } + + @Test + public void validateCredentialsForBeforeExpireUsernames() { + DBUser user = Mockito.mock(DBUser.class); + Integer iPeriod = 10; + Integer iInterval = 15; + Integer iBatchSize = 20; + + doReturn(true).when(mockConfigService).getAlertBeforeExpirePasswordEnabled(); + doReturn(iPeriod).when(mockConfigService).getAlertBeforeExpirePasswordPeriod(); + doReturn(iInterval).when(mockConfigService).getAlertBeforeExpirePasswordInterval(); + doReturn(iBatchSize).when(mockConfigService).getAlertCredentialsBatchSize(); + doReturn(Collections.singletonList(user)).when(mockUserDao).getBeforePasswordExpireUsersForAlerts(anyInt(), anyInt(), anyInt()); + + testInstance.validateCredentialsForBeforeExpireUsernames(); + + + ArgumentCaptor<Integer> period = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> interval = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> batchSize = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<DBUser> userCapture = ArgumentCaptor.forClass(DBUser.class); + + + verify(mockUserDao, Mockito.times(1)) + .getBeforePasswordExpireUsersForAlerts(period.capture(), interval.capture(), batchSize.capture()); + verify(mockAlertService, Mockito.times(1)) + .alertBeforeUsernamePasswordExpire(userCapture.capture()); + + assertEquals(iPeriod, period.getValue()); + assertEquals(iInterval, interval.getValue()); + assertEquals(iBatchSize, batchSize.getValue()); + assertEquals(user, userCapture.getValue()); + } + + @Test + public void validateCredentialsForExpiredUsernames() { + DBUser user = Mockito.mock(DBUser.class); + Integer iPeriod = 10; + Integer iInterval = 15; + Integer iBatchSize = 20; + + doReturn(true).when(mockConfigService).getAlertExpiredPasswordEnabled(); + doReturn(iPeriod).when(mockConfigService).getAlertExpiredPasswordPeriod(); + doReturn(iInterval).when(mockConfigService).getAlertExpiredPasswordInterval(); + doReturn(iBatchSize).when(mockConfigService).getAlertCredentialsBatchSize(); + doReturn(Collections.singletonList(user)).when(mockUserDao).getPasswordExpiredUsersForAlerts(anyInt(), anyInt(), anyInt()); + + testInstance.validateCredentialsForExpiredUsernames(); + + + ArgumentCaptor<Integer> period = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> interval = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> batchSize = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<DBUser> userCapture = ArgumentCaptor.forClass(DBUser.class); + + + verify(mockUserDao, Mockito.times(1)) + .getPasswordExpiredUsersForAlerts(period.capture(), interval.capture(), batchSize.capture()); + verify(mockAlertService, Mockito.times(1)) + .alertUsernamePasswordExpired(userCapture.capture()); + + assertEquals(iPeriod, period.getValue()); + assertEquals(iInterval, interval.getValue()); + assertEquals(iBatchSize, batchSize.getValue()); + assertEquals(user, userCapture.getValue()); + } + + @Test + public void validateCredentialsForBeforeExpireAccessToken() { + DBUser user = Mockito.mock(DBUser.class); + Integer iPeriod = 10; + Integer iInterval = 15; + Integer iBatchSize = 20; + + doReturn(true).when(mockConfigService).getAlertBeforeExpireAccessTokenEnabled(); + doReturn(iPeriod).when(mockConfigService).getAlertBeforeExpireAccessTokenPeriod(); + doReturn(iInterval).when(mockConfigService).getAlertBeforeExpireAccessTokenInterval(); + doReturn(iBatchSize).when(mockConfigService).getAlertCredentialsBatchSize(); + doReturn(Collections.singletonList(user)).when(mockUserDao).getBeforeAccessTokenExpireUsersForAlerts(anyInt(), anyInt(), anyInt()); + + testInstance.validateCredentialsForBeforeExpireAccessToken(); + + + ArgumentCaptor<Integer> period = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> interval = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> batchSize = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<DBUser> userCapture = ArgumentCaptor.forClass(DBUser.class); + + + verify(mockUserDao, Mockito.times(1)) + .getBeforeAccessTokenExpireUsersForAlerts(period.capture(), interval.capture(), batchSize.capture()); + verify(mockAlertService, Mockito.times(1)) + .alertBeforeAccessTokenExpire(userCapture.capture()); + + assertEquals(iPeriod, period.getValue()); + assertEquals(iInterval, interval.getValue()); + assertEquals(iBatchSize, batchSize.getValue()); + assertEquals(user, userCapture.getValue()); + } + + @Test + public void validateCredentialsForExpiredAccessToken() { + DBUser user = Mockito.mock(DBUser.class); + Integer iPeriod = 10; + Integer iInterval = 15; + Integer iBatchSize = 20; + + doReturn(true).when(mockConfigService).getAlertExpiredAccessTokenEnabled(); + doReturn(iPeriod).when(mockConfigService).getAlertExpiredAccessTokenPeriod(); + doReturn(iInterval).when(mockConfigService).getAlertExpiredAccessTokenInterval(); + doReturn(iBatchSize).when(mockConfigService).getAlertCredentialsBatchSize(); + doReturn(Collections.singletonList(user)).when(mockUserDao).getAccessTokenExpiredUsersForAlerts(anyInt(), anyInt(), anyInt()); + + testInstance.validateCredentialsForExpiredAccessToken(); + + + ArgumentCaptor<Integer> period = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> interval = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> batchSize = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<DBUser> userCapture = ArgumentCaptor.forClass(DBUser.class); + + + verify(mockUserDao, Mockito.times(1)) + .getAccessTokenExpiredUsersForAlerts(period.capture(), interval.capture(), batchSize.capture()); + verify(mockAlertService, Mockito.times(1)) + .alertAccessTokenExpired(userCapture.capture()); + + assertEquals(iPeriod, period.getValue()); + assertEquals(iInterval, interval.getValue()); + assertEquals(iBatchSize, batchSize.getValue()); + assertEquals(user, userCapture.getValue()); + } + + @Test + public void validateCredentialsForBeforeExpireCertificate() { + DBUser user = Mockito.mock(DBUser.class); + Integer iPeriod = 10; + Integer iInterval = 15; + Integer iBatchSize = 20; + + doReturn(true).when(mockConfigService).getAlertBeforeExpireCertificateEnabled(); + doReturn(iPeriod).when(mockConfigService).getAlertBeforeExpireCertificatePeriod(); + doReturn(iInterval).when(mockConfigService).getAlertBeforeExpireCertificateInterval(); + doReturn(iBatchSize).when(mockConfigService).getAlertCredentialsBatchSize(); + doReturn(Collections.singletonList(user)).when(mockUserDao).getBeforeCertificateExpireUsersForAlerts(anyInt(), anyInt(), anyInt()); + + testInstance.validateCredentialsForBeforeExpireCertificate(); + + + ArgumentCaptor<Integer> period = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> interval = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> batchSize = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<DBUser> userCapture = ArgumentCaptor.forClass(DBUser.class); + + + verify(mockUserDao, Mockito.times(1)) + .getBeforeCertificateExpireUsersForAlerts(period.capture(), interval.capture(), batchSize.capture()); + verify(mockAlertService, Mockito.times(1)) + .alertBeforeCertificateExpire(userCapture.capture()); + + assertEquals(iPeriod, period.getValue()); + assertEquals(iInterval, interval.getValue()); + assertEquals(iBatchSize, batchSize.getValue()); + assertEquals(user, userCapture.getValue()); + } + + @Test + public void validateCredentialsForExpiredCertificate() { + DBUser user = Mockito.mock(DBUser.class); + Integer iPeriod = 10; + Integer iInterval = 15; + Integer iBatchSize = 20; + + doReturn(true).when(mockConfigService).getAlertExpiredCertificateEnabled(); + doReturn(iPeriod).when(mockConfigService).getAlertExpiredCertificatePeriod(); + doReturn(iInterval).when(mockConfigService).getAlertExpiredCertificateInterval(); + doReturn(iBatchSize).when(mockConfigService).getAlertCredentialsBatchSize(); + doReturn(Collections.singletonList(user)).when(mockUserDao).getCertificateExpiredUsersForAlerts(anyInt(), anyInt(), anyInt()); + + testInstance.validateCredentialsForExpiredCertificate(); + + + ArgumentCaptor<Integer> period = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> interval = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<Integer> batchSize = ArgumentCaptor.forClass(Integer.class); + ArgumentCaptor<DBUser> userCapture = ArgumentCaptor.forClass(DBUser.class); + + + verify(mockUserDao, Mockito.times(1)) + .getCertificateExpiredUsersForAlerts(period.capture(), interval.capture(), batchSize.capture()); + verify(mockAlertService, Mockito.times(1)) + .alertCertificateExpired(userCapture.capture()); + + assertEquals(iPeriod, period.getValue()); + assertEquals(iInterval, interval.getValue()); + assertEquals(iBatchSize, batchSize.getValue()); + assertEquals(user, userCapture.getValue()); + } } \ No newline at end of file diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/PayloadValidatorServiceTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/PayloadValidatorServiceTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5cdf7798831ef79a2f00f5d6cd3b1b4b3fa49e0e --- /dev/null +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/PayloadValidatorServiceTest.java @@ -0,0 +1,82 @@ +package eu.europa.ec.edelivery.smp.services; + +import eu.europa.ec.edelivery.smp.exceptions.ErrorCode; +import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException; +import eu.europa.ec.smp.spi.PayloadValidatorSpi; +import eu.europa.ec.smp.spi.exceptions.PayloadValidatorSpiException; +import org.hamcrest.CoreMatchers; +import org.hamcrest.MatcherAssert; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.util.MimeTypeUtils; + +import java.io.InputStream; +import java.util.Arrays; +import java.util.Collections; +import java.util.Optional; + +import static org.junit.Assert.*; + +public class PayloadValidatorServiceTest { + + @Test + public void validateUploadedContentNoValidatorsMostNotFail() { + PayloadValidatorService testInstance = new PayloadValidatorService(Optional.empty()); + InputStream inputStream = Mockito.mock(InputStream.class); + + testInstance.validateUploadedContent(inputStream, MimeTypeUtils.APPLICATION_JSON.getType()); + // no error should accrue + } + + @Test + public void validateUploadedContentNoValidatorsMostNotFailEmpty() { + PayloadValidatorService testInstance = new PayloadValidatorService(Optional.of(Collections.emptyList())); + InputStream inputStream = Mockito.mock(InputStream.class); + + testInstance.validateUploadedContent(inputStream, MimeTypeUtils.APPLICATION_JSON.getType()); + // no error should accrue + } + + @Test + public void validateUploadedContent() throws PayloadValidatorSpiException { + PayloadValidatorSpi validatorSpi1 = Mockito.mock(PayloadValidatorSpi.class); + PayloadValidatorSpi validatorSpi2 = Mockito.mock(PayloadValidatorSpi.class); + PayloadValidatorService testInstance = new PayloadValidatorService(Optional.of(Arrays.asList(validatorSpi1,validatorSpi2))); + InputStream inputStream = Mockito.mock(InputStream.class); + String mimeType = MimeTypeUtils.APPLICATION_JSON.getType(); + + + testInstance.validateUploadedContent(inputStream, mimeType); + // no error should accrue + ArgumentCaptor<InputStream> streamCapture1 = ArgumentCaptor.forClass(InputStream.class); + ArgumentCaptor<String> mimeTypeCapture1 = ArgumentCaptor.forClass(String.class); + ArgumentCaptor<InputStream> streamCapture2 = ArgumentCaptor.forClass(InputStream.class); + ArgumentCaptor<String> mimeTypeCapture2 = ArgumentCaptor.forClass(String.class); + Mockito.verify(validatorSpi1, Mockito.times(1)).validatePayload(streamCapture1.capture(), mimeTypeCapture1.capture()); + Mockito.verify(validatorSpi2,Mockito.times(1)).validatePayload(streamCapture2.capture(), mimeTypeCapture2.capture()); + + assertEquals(inputStream, streamCapture1.getValue()); + assertEquals(inputStream, streamCapture2.getValue()); + assertEquals(mimeType, mimeTypeCapture1.getValue()); + assertEquals(mimeType, mimeTypeCapture2.getValue()); + } + + @Test + public void validateUploadedContentThrowException() throws PayloadValidatorSpiException { + PayloadValidatorSpi validatorSpi1 = Mockito.mock(PayloadValidatorSpi.class); + PayloadValidatorService testInstance = new PayloadValidatorService(Optional.of(Arrays.asList(validatorSpi1))); + InputStream inputStream = Mockito.mock(InputStream.class); + String mimeType = MimeTypeUtils.APPLICATION_JSON.getType(); + PayloadValidatorSpiException spiException = new PayloadValidatorSpiException("TestError"); + Mockito.doThrow(spiException).when(validatorSpi1).validatePayload(Mockito.any(),Mockito.any()); + + + SMPRuntimeException smpRuntimeException = + assertThrows(SMPRuntimeException.class, () -> testInstance.validateUploadedContent(inputStream, mimeType)); + + assertEquals(ErrorCode.INVALID_REQUEST, smpRuntimeException.getErrorCode()); + MatcherAssert.assertThat(smpRuntimeException.getMessage(), CoreMatchers.containsString(spiException.getMessage())); + } +} \ No newline at end of file diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceMultipleDomainsIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceMultipleDomainsIntegrationTest.java index 6e4a2491570500913de4d3fab8a1787ff150a891..48ab3062600c9980592357cc4a1e2839b62518a5 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceMultipleDomainsIntegrationTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceMultipleDomainsIntegrationTest.java @@ -85,8 +85,8 @@ public class ServiceGroupServiceMultipleDomainsIntegrationTest extends AbstractS assertFalse(dbsg.isPresent()); // test if exists - it must not :) // when - boolean bCreated = testInstance.saveServiceGroup(inServiceGroup, TEST_DOMAIN_CODE_2, TestConstants.USERNAME_1, - TestConstants.USERNAME_1); + boolean bCreated = testInstance.saveServiceGroup(inServiceGroup, TEST_DOMAIN_CODE_2, TestConstants.USERNAME_TOKEN_1, + TestConstants.USERNAME_TOKEN_1); Optional<DBServiceGroup> optRes = dbAssertion.findAndInitServiceGroup(TEST_SG_ID_PL, TEST_SG_SCHEMA_2); // then @@ -111,8 +111,8 @@ public class ServiceGroupServiceMultipleDomainsIntegrationTest extends AbstractS assertNotEquals(extension, newExtension); // extension updated // when - boolean bCreated = testInstance.saveServiceGroup(inServiceGroup, TEST_DOMAIN_CODE_1, TestConstants.USERNAME_1, - TestConstants.USERNAME_1); + boolean bCreated = testInstance.saveServiceGroup(inServiceGroup, TEST_DOMAIN_CODE_1, ""+ TestConstants.USERNAME_TOKEN_1, + TestConstants.USERNAME_TOKEN_1); serviceGroupDao.clearPersistenceContext(); Optional<DBServiceGroup> optRes = dbAssertion.findAndInitServiceGroup(TEST_SG_ID_2, TEST_SG_SCHEMA_2); diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceSingleDomainIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceSingleDomainIntegrationTest.java index 8d450fa490127a7de350039bae9d7fc22a69c6e3..5c61019cf9c16f74d489bac760e41026618520fd 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceSingleDomainIntegrationTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ServiceGroupServiceSingleDomainIntegrationTest.java @@ -100,8 +100,8 @@ public class ServiceGroupServiceSingleDomainIntegrationTest extends AbstractServ DBDomain domain = domainDao.getTheOnlyDomain().get(); assertNotNull(domain); // when - boolean bCreated = testInstance.saveServiceGroup(inServiceGroup, null, TestConstants.USERNAME_1, - TestConstants.USERNAME_1); + boolean bCreated = testInstance.saveServiceGroup(inServiceGroup, null, TestConstants.USERNAME_TOKEN_1, + TestConstants.USERNAME_TOKEN_1); Optional<DBServiceGroup> optRes= serviceGroupDao.findServiceGroup(TEST_SG_ID_PL, TEST_SG_SCHEMA_2); @@ -122,8 +122,8 @@ public class ServiceGroupServiceSingleDomainIntegrationTest extends AbstractServ assertNotNull(domain); // when - boolean bCreated = testInstance.saveServiceGroup(inServiceGroup, domain.getDomainCode(), TestConstants.USERNAME_1, - TestConstants.USERNAME_1); + boolean bCreated = testInstance.saveServiceGroup(inServiceGroup, domain.getDomainCode(), TestConstants.USERNAME_TOKEN_1, + TestConstants.USERNAME_TOKEN_1); Optional<DBServiceGroup> optRes= serviceGroupDao.findServiceGroup(TEST_SG_ID_PL, TEST_SG_SCHEMA_2); @@ -148,8 +148,8 @@ public class ServiceGroupServiceSingleDomainIntegrationTest extends AbstractServ assertFalse(Arrays.equals(extension, newExtension)); // extension updated // when - boolean bCreated = testInstance.saveServiceGroup(inServiceGroup, domain.getDomainCode(), TestConstants.USERNAME_1, - TestConstants.USERNAME_1); + boolean bCreated = testInstance.saveServiceGroup(inServiceGroup, domain.getDomainCode(), TestConstants.USERNAME_TOKEN_1, + TestConstants.USERNAME_TOKEN_1); Optional<DBServiceGroup> optRes= serviceGroupDao.findServiceGroup(TEST_SG_ID_PL, TEST_SG_SCHEMA_2); @@ -174,8 +174,8 @@ public class ServiceGroupServiceSingleDomainIntegrationTest extends AbstractServ public void saveAndDeletePositiveScenario() throws IOException { // given ServiceGroup inServiceGroup = unmarshal(loadDocumentAsString(TestConstants.SERVICE_GROUP_POLAND_XML_PATH)); - boolean bCreated = testInstance.saveServiceGroup(inServiceGroup, null, TestConstants.USERNAME_1, - TestConstants.USERNAME_1); + boolean bCreated = testInstance.saveServiceGroup(inServiceGroup, null, TestConstants.USERNAME_TOKEN_1, + TestConstants.USERNAME_TOKEN_1); assertTrue(bCreated); serviceGroupDao.clearPersistenceContext(); @@ -277,7 +277,7 @@ public class ServiceGroupServiceSingleDomainIntegrationTest extends AbstractServ expectedExeption.expectMessage(DOMAIN_NOT_EXISTS.getMessage(domain)); //execute - testInstance.saveServiceGroup(inServiceGroup, domain, USERNAME_1, USERNAME_1); + testInstance.saveServiceGroup(inServiceGroup, domain, USERNAME_TOKEN_1, USERNAME_TOKEN_1); } @Test @@ -290,7 +290,7 @@ public class ServiceGroupServiceSingleDomainIntegrationTest extends AbstractServ DomainService.DOMAIN_ID_PATTERN.pattern())); //execute - testInstance.saveServiceGroup(inServiceGroup, domain, USERNAME_1, USERNAME_1); + testInstance.saveServiceGroup(inServiceGroup, domain, USERNAME_TOKEN_1, USERNAME_TOKEN_1); } @Test diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIPropertyServiceIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIPropertyServiceIntegrationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..bfabe011c619250ece09af20f505b42dcb8bf86d --- /dev/null +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIPropertyServiceIntegrationTest.java @@ -0,0 +1,150 @@ +package eu.europa.ec.edelivery.smp.services.ui; + +import eu.europa.ec.edelivery.smp.cron.CronTriggerConfig; +import eu.europa.ec.edelivery.smp.cron.SMPDynamicCronTrigger; +import eu.europa.ec.edelivery.smp.data.dao.ConfigurationDao; +import eu.europa.ec.edelivery.smp.data.model.DBConfiguration; +import eu.europa.ec.edelivery.smp.data.ui.PropertyRO; +import eu.europa.ec.edelivery.smp.data.ui.PropertyValidationRO; +import eu.europa.ec.edelivery.smp.data.ui.ServiceResultProperties; +import eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum; +import eu.europa.ec.edelivery.smp.services.AbstractServiceIntegrationTest; +import org.apache.commons.lang3.StringUtils; +import org.hamcrest.CoreMatchers; +import org.hamcrest.MatcherAssert; +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.test.context.ContextConfiguration; + +import java.util.Collections; +import java.util.Map; + +import static eu.europa.ec.edelivery.smp.cron.CronTriggerConfig.TRIGGER_BEAN_PROPERTY_REFRESH; +import static eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum.SMP_CLUSTER_ENABLED; +import static eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum.SMP_PROPERTY_REFRESH_CRON; +import static org.junit.Assert.*; + +@ContextConfiguration(classes = {UIPropertyService.class, CronTriggerConfig.class}) +public class UIPropertyServiceIntegrationTest extends AbstractServiceIntegrationTest { + + + @Autowired + protected UIPropertyService testInstance; + @Autowired @Qualifier(TRIGGER_BEAN_PROPERTY_REFRESH) + SMPDynamicCronTrigger refreshPropertiesTrigger; + + + + @Test + public void getTableListAll() { + + //when + ServiceResultProperties res = testInstance.getTableList(-1, -1, null, null, null); + // then + assertNotNull(res); + assertEquals(SMPPropertyEnum.values().length, res.getCount().intValue()); + assertEquals(-1, res.getPage().intValue()); + assertEquals(-1, res.getPageSize().intValue()); + assertEquals(SMPPropertyEnum.values().length, res.getServiceEntities().size()); + assertNull(res.getFilter()); + } + + @Test + public void getTableListFilterByCas() { + + //when + String filter = ".cas"; + ServiceResultProperties res = testInstance.getTableList(-1, -1, null, null, filter); + // then + assertNotNull(res); + assertTrue(res.getCount().intValue() < SMPPropertyEnum.values().length); + assertEquals(-1, res.getPage().intValue()); + assertEquals(-1, res.getPageSize().intValue()); + for (PropertyRO propertyRO : res.getServiceEntities()) { + assertTrue(StringUtils.containsIgnoreCase(propertyRO.getProperty(), filter)); + } + assertEquals(filter, res.getFilter()); + } + + @Test + public void createPropertyPendingToUpdate() { + SMPPropertyEnum propertyType = SMP_PROPERTY_REFRESH_CRON; + DBConfiguration dbConfiguration = new DBConfiguration(); + dbConfiguration.setProperty(propertyType.getProperty()); + dbConfiguration.setValue("1 1 * * * *"); + + Map<String, DBConfiguration> dbProperties = Collections.singletonMap(propertyType.getProperty(), dbConfiguration); + PropertyRO propertyRO = testInstance.createProperty(propertyType, dbProperties); + + assertEquals(dbConfiguration.getProperty(), propertyRO.getProperty()); + assertEquals(propertyType.getDesc(), propertyRO.getDesc()); + assertEquals(configurationDao.getCachedProperty(propertyType), propertyRO.getValue()); + + assertEquals(dbConfiguration.getValue(), propertyRO.getNewValue()); + assertEquals(refreshPropertiesTrigger.getNextExecutionDate(), propertyRO.getUpdateDate()); + + assertEquals(propertyType.isEncrypted(), propertyRO.isEncrypted()); + assertEquals(propertyType.isMandatory(), propertyRO.isMandatory()); + assertEquals(propertyType.isRestartNeeded(), propertyRO.isRestartNeeded()); +} + + @Test + public void updatePropertyList() { + configurationDao.setPropertyToDatabase(SMP_PROPERTY_REFRESH_CRON.getProperty(), SMP_PROPERTY_REFRESH_CRON.getDefValue()); + // set non cluster - to enable instant refresh + configurationDao.setPropertyToDatabase(SMP_CLUSTER_ENABLED.getProperty(), "false"); + configurationDao.reloadPropertiesFromDatabase(); + + SMPPropertyEnum propertyType = SMP_PROPERTY_REFRESH_CRON; + String value = "2 1 * * * *"; + PropertyRO propertyRO = new PropertyRO(propertyType.getProperty(), value); + assertNotEquals(value, configurationDao.getCachedProperty(propertyType)); + + testInstance.updatePropertyList(Collections.singletonList(propertyRO)); + assertEquals(value, configurationDao.getCachedProperty(propertyType)); + + } + @Test + public void validatePropertyNotExists() { + String propertyName="DoesNotExist"; + String propertyValue="DoesNotExistValue"; + PropertyRO property = new PropertyRO(propertyName, propertyValue); + + PropertyValidationRO result = testInstance.validateProperty(property); + assertNotNull(result); + assertEquals(propertyName, result.getProperty()); + assertEquals(propertyValue, result.getValue()); + assertFalse(result.isPropertyValid()); + MatcherAssert.assertThat(result.getErrorMessage(), CoreMatchers.containsString("Property ["+propertyName+"] is not SMP property!")); + } + + @Test + public void validatePropertyInvalidValue() { + String propertyName=SMPPropertyEnum.ACCESS_TOKEN_FAIL_DELAY.getProperty(); + String propertyValue="NotANumber"; + PropertyRO property = new PropertyRO(propertyName, propertyValue); + + PropertyValidationRO result = testInstance.validateProperty(property); + assertNotNull(result); + assertEquals(propertyName, result.getProperty()); + assertEquals(propertyValue, result.getValue()); + assertFalse(result.isPropertyValid()); + MatcherAssert.assertThat(result.getErrorMessage(), CoreMatchers.containsString("Invalid integer: ["+propertyValue+"]. Error:NumberFormatException: For input string: \""+propertyValue+"\"!")); + } + + @Test + public void validatePropertyOK() { + String propertyName=SMPPropertyEnum.ACCESS_TOKEN_FAIL_DELAY.getProperty(); + String propertyValue="1223232"; + PropertyRO property = new PropertyRO(propertyName, propertyValue); + + PropertyValidationRO result = testInstance.validateProperty(property); + assertNotNull(result); + assertEquals(propertyName, result.getProperty()); + assertEquals(propertyValue, result.getValue()); + assertTrue(result.isPropertyValid()); + assertNull(result.getErrorMessage()); + } + +} \ No newline at end of file diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIUserServiceIntegrationTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIUserServiceIntegrationTest.java index ce1333c7c7e5d6233c5dcc85bb7bb959fcee3ccb..4ff730c833db882ec1656056b8f42994b655d0c6 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIUserServiceIntegrationTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/services/ui/UIUserServiceIntegrationTest.java @@ -4,6 +4,7 @@ package eu.europa.ec.edelivery.smp.services.ui; import eu.europa.ec.edelivery.smp.config.ConversionTestConfig; import eu.europa.ec.edelivery.smp.data.model.DBCertificate; import eu.europa.ec.edelivery.smp.data.model.DBUser; +import eu.europa.ec.edelivery.smp.data.ui.AccessTokenRO; import eu.europa.ec.edelivery.smp.data.ui.CertificateRO; import eu.europa.ec.edelivery.smp.data.ui.ServiceResult; import eu.europa.ec.edelivery.smp.data.ui.UserRO; @@ -16,6 +17,7 @@ import org.junit.rules.ExpectedException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.crypto.bcrypt.BCrypt; import org.springframework.test.context.ContextConfiguration; +import org.springframework.transaction.annotation.Transactional; import java.time.OffsetDateTime; import java.time.temporal.ChronoUnit; @@ -38,6 +40,8 @@ public class UIUserServiceIntegrationTest extends AbstractServiceIntegrationTest @Autowired protected UIUserService testInstance; + + protected void insertDataObjects(int size) { for (int i = 0; i < size; i++) { DBUser d = TestDBUtils.createDBUserByUsername("user" + i); @@ -266,7 +270,31 @@ public class UIUserServiceIntegrationTest extends AbstractServiceIntegrationTest assertEquals(urTest.getServiceEntities().size() - 1, iCntNew); assertFalse(rmUsr.isPresent()); + } + + @Test + @Transactional + public void testGenerateAccessTokenForUser() { + String userPassword=UUID.randomUUID().toString(); + DBUser user = new DBUser(); + user.setPassword(BCrypt.hashpw(userPassword, BCrypt.gensalt())); + user.setUsername(UUID.randomUUID().toString()); + user.setEmailAddress(UUID.randomUUID().toString()); + user.setRole("ROLE"); + userDao.persistFlushDetach(user); + + + AccessTokenRO token = testInstance.generateAccessTokenForUser(user.getId(), userPassword); + Optional<DBUser> optResult = userDao.findUserByAuthenticationToken(token.getIdentifier()); + assertTrue(optResult.isPresent()); + assertNotNull(token); + DBUser result = optResult.get(); + assertEquals(user.getUsername(), result.getUsername()); + assertEquals(result.getAccessTokenIdentifier(), token.getIdentifier()); + assertTrue(BCrypt.checkpw(token.getValue(), result.getAccessToken())); + assertNotNull(result.getAccessTokenExpireOn()); + assertNotNull(result.getAccessTokenGeneratedOn()); } } diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestConstants.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestConstants.java index 1b5f3d9f1f868dcffd8fdbf2fb0f4f9318e01a19..f027304a457fee8416314387732e283199041384 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestConstants.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestConstants.java @@ -18,33 +18,33 @@ public class TestConstants { public static final String TEST_SG_ID_3 = "0007:002:utest"; public static final String TEST_SG_ID_4 = "0007:004:utest"; public static final String TEST_SG_ID_NO_SCHEME = "No-Scheme-Party-Id"; - public static final String TEST_SG_ID_PL= "urn:poland:ncpb:utest"; - public static final String TEST_SG_ID_PL2= "urn:Poland:ncpb"; - + public static final String TEST_SG_ID_PL = "urn:poland:ncpb:utest"; + public static final String TEST_SG_ID_PL2 = "urn:Poland:ncpb"; public static final String TEST_SG_SCHEMA_1 = "iso6523-actorid-upis"; public static final String TEST_SG_SCHEMA_2 = "ehealth-actorid-qns"; public static final String TEST_SG_SCHEMA_PL2 = "eHealth-participantId-qns"; - - - public static final String TEST_DOC_SCHEMA_1 = "busdox-docid-qns"; public static final String TEST_DOC_SCHEMA_2 = "ehealth-resid-qns"; - public static final String TEST_DOC_SCHEMA_PL2="eHealth-resId-qns"; + public static final String TEST_DOC_SCHEMA_PL2 = "eHealth-resId-qns"; public static final String TEST_DOC_ID_1 = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-12::Invoice##urn:www.cenbii.eu:transaction:biicoretrdm010:ver1.0:#urn:www.peppol.eu:bis:peppol4a:ver1.0::2.0"; public static final String TEST_DOC_ID_2 = "docid.007"; public static final String TEST_DOC_ID_PL2 = "DocId.007"; + public static final String TOKEN_PREFIX = "token-"; public static final String USERNAME_1 = "test-user_001"; public static final String USERNAME_2 = "test-user_002"; public static final String USERNAME_3 = "test-user_003"; + public static final String USERNAME_TOKEN_1 = TOKEN_PREFIX + USERNAME_1; + public static final String USERNAME_TOKEN_2 = TOKEN_PREFIX + USERNAME_2; + public static final String USERNAME_TOKEN_3 = TOKEN_PREFIX + USERNAME_3; - public static final String USER_CERT_1="CN=utest common name 01,O=org,C=BE:0000000000000066"; - public static final String USER_CERT_2="CN=utest common name 02,O=org,C=BE:0000000000000077"; - public static final String USER_CERT_3="CN=utest common name 03,O=org,C=BE:0000000000000077"; + public static final String USER_CERT_1 = "CN=utest common name 01,O=org,C=BE:0000000000000066"; + public static final String USER_CERT_2 = "CN=utest common name 02,O=org,C=BE:0000000000000077"; + public static final String USER_CERT_3 = "CN=utest common name 03,O=org,C=BE:0000000000000077"; public static final String SERVICE_GROUP_POLAND_XML_PATH = "/examples/services/ServiceGroupPoland.xml"; @@ -52,16 +52,16 @@ public class TestConstants { public static final String SERVICE_METADATA_XML_PATH = "/examples/services/ServiceMetadataPoland.xml"; public static final String SIGNED_SERVICE_METADATA_XML_PATH = "/examples/services/SignedServiceMetadataPoland.xml"; - public static final ParticipantIdentifierType SERVICE_GROUP_ID = asParticipantId("participant-scheme-qns::urn:eu:ncpb",false); + public static final ParticipantIdentifierType SERVICE_GROUP_ID = asParticipantId("participant-scheme-qns::urn:eu:ncpb", false); public static final String ADMIN_USERNAME = "test_admin"; - public static final String CERT_USER="CN=common name,O=org,C=BE:0000000000000066"; - public static final String CERT_USER_ENCODED="CN%3Dcommon%20name%2CO%3Dorg%2CC%3DBE%3A0000000000000066"; + public static final String CERT_USER = "CN=common name,O=org,C=BE:0000000000000066"; + public static final String CERT_USER_ENCODED = "CN%3Dcommon%20name%2CO%3Dorg%2CC%3DBE%3A0000000000000066"; // parameter: custom string as content public static final String SIMPLE_EXTENSION_XML ="<Extension xmlns=\"http://docs.oasis-open.org/bdxr/ns/SMP/2016/05\"><ex:dummynode xmlns:ex=\"http://test.eu\">Sample not mandatory extension: %s</ex:dummynode></Extension>"; //5 parameters: ParticipantScheme, ParticipantIdentifier, DocumentScheme, DocumentIdentifier, custom value - public static final String SIMPLE_DOCUMENT_XML ="<ServiceMetadata xmlns=\"http://docs.oasis-open.org/bdxr/ns/SMP/2016/05\"><ServiceInformation><ParticipantIdentifier scheme=\"%s\">%s</ParticipantIdentifier><DocumentIdentifier scheme=\"%s\">%s</DocumentIdentifier><ProcessList><Process><ProcessIdentifier scheme=\"cenbii-procid-ubl\">urn:www.cenbii.eu:profile:bii04:ver1.0</ProcessIdentifier><ServiceEndpointList><Endpoint transportProfile=\"bdxr-transport-ebms3-as4-v1p0\"><EndpointURI>http://localhost:8080/domibus-weblogic/services/msh</EndpointURI><RequireBusinessLevelSignature>true</RequireBusinessLevelSignature><ServiceActivationDate>2003-01-01T00:00:00</ServiceActivationDate><ServiceExpirationDate>2099-05-01T00:00:00</ServiceExpirationDate>" + + public static final String SIMPLE_DOCUMENT_XML = "<ServiceMetadata xmlns=\"http://docs.oasis-open.org/bdxr/ns/SMP/2016/05\"><ServiceInformation><ParticipantIdentifier scheme=\"%s\">%s</ParticipantIdentifier><DocumentIdentifier scheme=\"%s\">%s</DocumentIdentifier><ProcessList><Process><ProcessIdentifier scheme=\"cenbii-procid-ubl\">urn:www.cenbii.eu:profile:bii04:ver1.0</ProcessIdentifier><ServiceEndpointList><Endpoint transportProfile=\"bdxr-transport-ebms3-as4-v1p0\"><EndpointURI>http://localhost:8080/domibus-weblogic/services/msh</EndpointURI><RequireBusinessLevelSignature>true</RequireBusinessLevelSignature><ServiceActivationDate>2003-01-01T00:00:00</ServiceActivationDate><ServiceExpirationDate>2099-05-01T00:00:00</ServiceExpirationDate>" + "<Certificate>VGhpcyBpcyB0ZXN0IGNlcnRpZmljYXRlIGlzIHlvdSBiZWxpZXZlIG9yIG5vdC4=</Certificate><ServiceDescription>Sample description of %s</ServiceDescription><TechnicalContactUrl>https://example.com</TechnicalContactUrl></Endpoint></ServiceEndpointList></Process></ProcessList></ServiceInformation></ServiceMetadata>"; public static final String SIMPLE_REDIRECT_DOCUMENT_XML ="<ServiceMetadata xmlns=\"http://docs.oasis-open.org/bdxr/ns/SMP/2016/05\">" + diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java index 0ba18573bcf0992ecc7e49abaec8d8a16a52f620..d5c888ea4861a8ea019d6c156f7526474333ef91 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/testutil/TestDBUtils.java @@ -107,10 +107,10 @@ public class TestDBUtils { DBUser dbuser = new DBUser(); dbuser.setUsername(userName); dbuser.setRole("test"); - dbuser.setEmailAddress("test@test.eu"); + dbuser.setEmailAddress(userName + "@test.eu"); dbuser.setPasswordChanged(OffsetDateTime.now()); dbuser.setPassword(UUID.randomUUID().toString()); - dbuser.setAccessTokenIdentifier(userName); + dbuser.setAccessTokenIdentifier(TOKEN_PREFIX + userName); dbuser.setAccessToken(UUID.randomUUID().toString()); return dbuser; } @@ -136,7 +136,7 @@ public class TestDBUtils { } public static DBUser createDBUserByCertificate(String certId, OffsetDateTime validFrom, OffsetDateTime validTo) { - return createDBUser("test-" + certId, certId, validFrom,validTo); + return createDBUser("test-" + certId, certId, validFrom, validTo); } public static DBUser createDBUser(String userName, String certId) { diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/ExtLibraryClassLoaderTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/ExtLibraryClassLoaderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b597b97f83b1f12a1dafa52ea3f1dbcb28588ceb --- /dev/null +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/ExtLibraryClassLoaderTest.java @@ -0,0 +1,32 @@ +package eu.europa.ec.edelivery.smp.utils; + +import org.junit.Test; + +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static org.junit.Assert.*; + +public class ExtLibraryClassLoaderTest { + + @Test + public void discoverLibraries() throws MalformedURLException { + Path path = Paths.get("src", "test","resources","test-libs"); + URL[] result = ExtLibraryClassLoader.discoverLibraries(path.toFile()); + assertNotNull(result); + assertEquals(2, result.length); + } + + @Test + public void getLibraryFolder() throws MalformedURLException { + Path path = Paths.get("src", "test","resources","test-libs"); + ExtLibraryClassLoader loader = new ExtLibraryClassLoader(path.toFile(), ClassLoader.getSystemClassLoader()); + URL url = loader.getResource("test-load-library.xml"); + URL urlNotExists = loader.getResource("test-load-library-notExists.xml"); + assertEquals(path.toFile(), loader.getLibraryFolder()); + assertNotNull(url); + assertNull(urlNotExists); + } +} \ No newline at end of file diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/HttpForwardedHeadersTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/HttpForwardedHeadersTest.java new file mode 100644 index 0000000000000000000000000000000000000000..cfeadee567824836303f258bf9a247ad719fe053 --- /dev/null +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/HttpForwardedHeadersTest.java @@ -0,0 +1,76 @@ +package eu.europa.ec.edelivery.smp.utils; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.mockito.Mockito; +import org.springframework.http.HttpMethod; + +import javax.servlet.http.HttpServletRequest; + +import java.util.Collection; +import java.util.List; + +import static eu.europa.ec.edelivery.smp.utils.HttpForwardedHeaders.ForwardedHeaderNameEnum.*; +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; + +@RunWith(Parameterized.class) +public class HttpForwardedHeadersTest { + + @Parameterized.Parameters(name = "{index}: {0}") + public static Collection cookieWriterTestParameters() { + return asList(new Object[][]{ + {"test-host", "8181","http","172.1.0.1", "test-host", "8181", "8181", "http","172.1.0.1"}, + {"NormaLIZE-hOst", "8181","http","172.1.0.1", "normalize-host", "8181", "8181", "http","172.1.0.1"}, + {"default-http", "80","http","172.1.0.1", "default-http", "80", null, "http","172.1.0.1"}, + {"default-https", "443","https","172.1.0.1", "default-https", "443", null, "https","172.1.0.1"}, + {"https-host", "8443","https","172.1.0.1", "https-host", "8443", "8443", "https","172.1.0.1"}, + {"normalize-scheme", "8443","hTTps","172.1.0.1", "normalize-scheme", "8443", "8443", "https","172.1.0.1"}, + {"host-port:773", null,"https","172.1.0.1", "host-port", "773", "773", "https","172.1.0.1"}, + {"host-port-equal:773", "773","https","172.1.0.1", "host-port-equal", "773", "773", "https","172.1.0.1"}, + {"header-port-priority:773", "8843","https","172.1.0.1", "header-port-priority", "8843", "8843", "https","172.1.0.1"}, + }); + } + + @Parameterized.Parameter(0) + public String hostName; + @Parameterized.Parameter(1) + public String port; + @Parameterized.Parameter(2) + public String scheme; + @Parameterized.Parameter(3) + public String forCall; + @Parameterized.Parameter(4) + public String resultHostName; + @Parameterized.Parameter(5) + public String resultPort; + @Parameterized.Parameter(6) + public String resultDefaultPort; + @Parameterized.Parameter(7) + public String resultScheme; + @Parameterized.Parameter(8) + public String resultForCall; + + + @Test + public void getReadForwardHeadersFromRequest() { + + + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + Mockito.doReturn(hostName).when(request).getHeader(HOST.getHeaderName()); + Mockito.doReturn(scheme).when(request).getHeader(PROTO.getHeaderName()); + Mockito.doReturn(forCall).when(request).getHeader(FOR.getHeaderName()); + Mockito.doReturn(port).when(request).getHeader(PORT.getHeaderName()); + + HttpForwardedHeaders testInstance = new HttpForwardedHeaders(request); + + assertEquals(resultHostName, testInstance.getHost()); + assertEquals(resultPort, testInstance.getPort()); + assertEquals(resultDefaultPort, testInstance.getNonDefaultPort()); + assertEquals(resultScheme, testInstance.getProto()); + assertEquals(resultForCall, testInstance.getForClientHost()); + + } + +} \ No newline at end of file diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/PropertyUtilsTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/PropertyUtilsTest.java index 2a44831d7302b546788becc9151d88b89cf11540..9f689426eff1206df46a02b3987f85c956dfc4a4 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/PropertyUtilsTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/PropertyUtilsTest.java @@ -10,6 +10,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import java.io.File; +import java.nio.file.Paths; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.regex.Pattern; @@ -21,23 +23,34 @@ import static org.junit.Assert.*; @RunWith(JUnitParamsRunner.class) public class PropertyUtilsTest { + + private static final List<SMPPropertyEnum> SENSITIVE_PROPERTIES = Arrays.asList( + HTTP_PROXY_PASSWORD, + KEYSTORE_PASSWORD, + TRUSTSTORE_PASSWORD, + KEYSTORE_PASSWORD_DECRYPTED, + TRUSTSTORE_PASSWORD_DECRYPTED, + MAIL_SERVER_PASSWORD); + private static final File ROOT_FOLDER = Paths.get("target").toFile(); + + private static final Object[] testTypeValues() { return new Object[][]{ - {STRING, "this is a string", true, true}, - {INTEGER, "1345", true, true}, - {INTEGER, " 1e345", false, false}, - {BOOLEAN, "true", true, true}, - {BOOLEAN, "false", true, true}, - {BOOLEAN, "fALse", true, true}, - {BOOLEAN, "fale ", false, true}, - {REGEXP, ".*", true, true}, - {REGEXP, ".*(**]", false, false}, - {EMAIL, "test@mail.com", true, true}, - {EMAIL, "test@2222.comsfs", false, false}, - {EMAIL, "test@coms.fs", false, false}, - {FILENAME, "myfilename.txt", true, true}, - {PATH, "./", true, true}, - {PATH, "./notexits", true, true}, // path will be created + {STRING, "this is a string", true}, + {INTEGER, "1345", true}, + {INTEGER, " 1e345", false}, + {BOOLEAN, "true", true}, + {BOOLEAN, "false", true}, + {BOOLEAN, "fALse", true}, + {BOOLEAN, "fale ", false}, + {REGEXP, ".*", true}, + {REGEXP, ".*(**]", false}, + {EMAIL, "test@mail.com", true}, + {EMAIL, "test@2222.comsfs", false}, + {EMAIL, "test@coms.fs", false}, + {FILENAME, "myfilename.txt", true}, + {PATH, "./", true}, + {PATH, "./notexits", true}, // path will be created }; } @@ -75,20 +88,17 @@ public class PropertyUtilsTest { @Test @Parameters(method = "testParsePropertiesToType") public void testParsePropertiesToType(SMPPropertyEnum property, String value, Class cls) { - // given - File folder = new File("./target"); //when then - Object obj = PropertyUtils.parseProperty(property, value, folder); + Object obj = PropertyUtils.parseProperty(property, value, ROOT_FOLDER); Assert.assertTrue(cls.isInstance(obj)); } @Test @Parameters(method = "testTypeValues") - public void testIsValidPropertyType(SMPPropertyTypeEnum propertyType, String value, boolean expected, - boolean isNotNull) { + public void testIsValidPropertyType(SMPPropertyTypeEnum propertyType, String value, boolean expected) { //when - boolean result = PropertyUtils.isValidPropertyType(propertyType, value); + boolean result = PropertyUtils.isValidPropertyType(propertyType, value, ROOT_FOLDER); //then assertEquals(expected, result); @@ -99,14 +109,15 @@ public class PropertyUtilsTest { public void testDefaultValues() { for (SMPPropertyEnum prop : SMPPropertyEnum.values()) { - assertTrue("Invalid: " + prop.getProperty() + " - " + prop.getDesc() + " value: " + prop.getDefValue(), PropertyUtils.isValidProperty(prop, prop.getDefValue())); + assertTrue( PropertyUtils.isValidProperty(prop, prop.getDefValue(), ROOT_FOLDER)); } } @Test public void testParseDefaultValues() { + for (SMPPropertyEnum prop : SMPPropertyEnum.values()) { - Object obj = PropertyUtils.parseProperty(prop, prop.getDefValue(), null); + Object obj = PropertyUtils.parseProperty(prop, prop.getDefValue(), ROOT_FOLDER); assertType(prop, obj); } } @@ -114,31 +125,19 @@ public class PropertyUtilsTest { @Test @Parameters(method = "testTypeValues") - public void testParsePropertyType(SMPPropertyTypeEnum propertyType, String value, boolean isValid, - boolean isNotNull) { - // given - File folder = new File("./target"); - //when then - Object obj = null; - try { - obj = PropertyUtils.parsePropertyType(propertyType, value, folder); - assertTrue(isNotNull); - assertNotNull(obj); - } catch (SMPRuntimeException ex) { - assertFalse(isNotNull); - assertNull(obj); + public void testParsePropertyType(SMPPropertyTypeEnum propertyType, String value, boolean expectParseOk) { + if (expectParseOk) { + Object result = PropertyUtils.parsePropertyType(propertyType, value, ROOT_FOLDER); + assertNotNull(result); + assertType(propertyType, result); } - } - - - public static void assertType(SMPPropertyEnum prop, Object value) { - if (value == null) { - if (prop.isMandatory()) { - Assert.fail("Default value for property: " + prop.getProperty() + " must not be empty!"); - } - return; + else { + SMPRuntimeException exception = assertThrows(SMPRuntimeException.class, ()->PropertyUtils.parsePropertyType(propertyType, value, ROOT_FOLDER)); + assertNotNull(exception.getErrorCode()); } - switch (prop.getPropertyType()) { + } + public static void assertType(SMPPropertyTypeEnum prop, Object value) { + switch (prop) { case BOOLEAN: Assert.assertEquals(Boolean.class, value.getClass()); break; @@ -171,4 +170,30 @@ public class PropertyUtilsTest { fail("Unknown property type"); } } + + public static void assertType(SMPPropertyEnum prop, Object value) { + if (value == null) { + if (prop.isMandatory()) { + Assert.fail("Default value for property: " + prop.getProperty() + " must not be empty!"); + } + return; + } + assertType(prop.getPropertyType(), value); + } + + @Test + public void testIsSensitiveData() { + for (SMPPropertyEnum smpPropertyEnum: SMPPropertyEnum.values()){ + Assert.assertEquals(SENSITIVE_PROPERTIES.contains(smpPropertyEnum), PropertyUtils.isSensitiveData(smpPropertyEnum.getProperty())); + } + } + + @Test + public void getMaskedData() { + String testValue = "TestValue"; + for (SMPPropertyEnum smpPropertyEnum: SMPPropertyEnum.values()){ + String expectedValue = SENSITIVE_PROPERTIES.contains(smpPropertyEnum)?"*******":testValue; + Assert.assertEquals(expectedValue, PropertyUtils.getMaskedData(smpPropertyEnum.getProperty(),testValue)); + } + } } \ No newline at end of file diff --git a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/SecurityUtilsTest.java b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/SecurityUtilsTest.java index a4e500a893789b3e4f22c04090f90c65e074839c..03e4381cc2a72500be25b551cee04e8a76024508 100644 --- a/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/SecurityUtilsTest.java +++ b/smp-server-library/src/test/java/eu/europa/ec/edelivery/smp/utils/SecurityUtilsTest.java @@ -52,7 +52,7 @@ public class SecurityUtilsTest { @Test public void testGenerateAccessToken(){ // given-when - AccessTokenRO accessToken = SecurityUtils.generateAccessToken(); + AccessTokenRO accessToken = SecurityUtils.generateAccessToken(true); // then assertNotNull(accessToken); assertNotNull(accessToken.getGeneratedOn()); diff --git a/smp-server-library/src/test/resources/config.properties b/smp-server-library/src/test/resources/config.properties index c90e33adec0c4fcd58db89190011fc4e0f73bbc5..5c4f05199fb155a1334eb8c3723be14379f3de00 100644 --- a/smp-server-library/src/test/resources/config.properties +++ b/smp-server-library/src/test/resources/config.properties @@ -42,6 +42,7 @@ xmldsig.keystore.password = mock ##jdbc.read-connections.max = ${jdbc.read-connections.max} +test.read.property=This property is from fallback legacy file # Used by FileConfig tests: element1=string diff --git a/smp-server-library/src/test/resources/create-configuration-table-h2.ddl b/smp-server-library/src/test/resources/create-configuration-table-h2.ddl new file mode 100644 index 0000000000000000000000000000000000000000..89c3f584562712a5ea73947598a85662e8d6ca7f --- /dev/null +++ b/smp-server-library/src/test/resources/create-configuration-table-h2.ddl @@ -0,0 +1,26 @@ +create table SMP_CONFIGURATION ( + PROPERTY varchar(512) not null, + CREATED_ON timestamp not null, + LAST_UPDATED_ON timestamp not null, + DESCRIPTION varchar(4000), + VALUE varchar(4000), + primary key (PROPERTY) +); +create table SMP_CONFIGURATION_AUD ( + PROPERTY varchar(512) not null, + REV bigint not null, + REVTYPE tinyint, + CREATED_ON timestamp, + LAST_UPDATED_ON timestamp, + DESCRIPTION varchar(4000), + VALUE varchar(4000), + primary key (PROPERTY, REV) +); + +create table SMP_REV_INFO ( + id bigint generated by default as identity, + REVISION_DATE timestamp, + timestamp bigint not null, + USERNAME varchar(255), + primary key (id) +); \ No newline at end of file diff --git a/smp-server-library/src/test/resources/test-libs/simple-extension-01.jar b/smp-server-library/src/test/resources/test-libs/simple-extension-01.jar new file mode 100644 index 0000000000000000000000000000000000000000..991ee4cc4660cb706f3ef484d25a4a11132584ab Binary files /dev/null and b/smp-server-library/src/test/resources/test-libs/simple-extension-01.jar differ diff --git a/smp-server-library/src/test/resources/test-libs/simple-extension-02.jar b/smp-server-library/src/test/resources/test-libs/simple-extension-02.jar new file mode 100644 index 0000000000000000000000000000000000000000..cd54a5d9adc661fa9ebf6fc01243eaad123aac7a Binary files /dev/null and b/smp-server-library/src/test/resources/test-libs/simple-extension-02.jar differ diff --git a/smp-server-library/src/test/resources/test-smp.config.properties b/smp-server-library/src/test/resources/test-smp.config.properties new file mode 100644 index 0000000000000000000000000000000000000000..68119a8e20ba824807290023701c0b1cd47dd12a --- /dev/null +++ b/smp-server-library/src/test/resources/test-smp.config.properties @@ -0,0 +1,6 @@ +# JDBC configuration for DB +jdbc.driver = com.mysql.jdbc.Driver +jdbc.url = jdbc:mysql://localhost:3306/smp +jdbc.user = smp-test-read-prop +jdbc.password=**** +test.read.property=This property is from custom file \ No newline at end of file diff --git a/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql b/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql index b2cf07e7fb3fbc086cc8cbca5f604e40625d6ee7..669cadf52f0e7446f4a2abb6bd6bf8d5893ee786 100644 --- a/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql +++ b/smp-soapui-tests/groovy/mysql-4.1_integration_test_data.sql @@ -1,51 +1,51 @@ -insert into SMP_USER (ID, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (1, 'peppol_user', '$2a$10$.pqNZZ4fRDdNbLhNlnEYg.1/d4yAGpLDgeXpJFI0sw7.WtyKphFzu','peppol_user', '$2a$10$.pqNZZ4fRDdNbLhNlnEYg.1/d4yAGpLDgeXpJFI0sw7.WtyKphFzu', 'SMP_ADMIN', 1, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (2, 'the_admin', '','the_admin', '', 'SMP_ADMIN', 1, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (3, 'AdminSMP1TEST', '$2a$06$u6Hym7Zrbsf4gEIeAsJRceK.Kg7tei3kDypwucQQdky0lXOLCkrCO','AdminSMP1TEST', '$2a$06$u6Hym7Zrbsf4gEIeAsJRceK.Kg7tei3kDypwucQQdky0lXOLCkrCO', 'SMP_ADMIN', 1, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (4, 'AdminSMP2TEST', '$2a$10$h8Q3Kjbs6ZrGkU6ditjNueINlJOMDJ/g/OKiqFZy32WmdhLjV5TAi','AdminSMP2TEST', '$2a$10$h8Q3Kjbs6ZrGkU6ditjNueINlJOMDJ/g/OKiqFZy32WmdhLjV5TAi', 'SMP_ADMIN', 1, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (5, 'test', '','test', '', 'SMP_ADMIN', 1, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (6, 'test1', '$2a$06$toKXJgjqQINZdjQqSao3NeWz2n1S64PFPhVU1e8gIHh4xdbwzy1Uy','test1', '$2a$06$toKXJgjqQINZdjQqSao3NeWz2n1S64PFPhVU1e8gIHh4xdbwzy1Uy', 'SMP_ADMIN', 1, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (7, 'system', '$2a$06$FDmjewn/do3C219uysNm9.XG8mIn.ubHnMydAzC8lsv61HsRpOR36','system', '$2a$06$FDmjewn/do3C219uysNm9.XG8mIn.ubHnMydAzC8lsv61HsRpOR36', 'SYSTEM_ADMIN', 1, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (8, 'smp', '$2a$06$FDmjewn/do3C219uysNm9.XG8mIn.ubHnMydAzC8lsv61HsRpOR36','smp', '$2a$06$FDmjewn/do3C219uysNm9.XG8mIn.ubHnMydAzC8lsv61HsRpOR36', 'SMP_ADMIN', 1, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (9, 'user', '$2a$06$FDmjewn/do3C219uysNm9.XG8mIn.ubHnMydAzC8lsv61HsRpOR36','user', '$2a$06$FDmjewn/do3C219uysNm9.XG8mIn.ubHnMydAzC8lsv61HsRpOR36', 'SERVICE_GROUP_ADMIN', 1, NOW(), NOW()); - - -insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (10, 'EHEALTH_SMP_EC', '', 'SERVICE_GROUP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (1, 'peppol_user@test-mail.eu','peppol_user', '$2a$10$.pqNZZ4fRDdNbLhNlnEYg.1/d4yAGpLDgeXpJFI0sw7.WtyKphFzu','peppol_user', '$2a$10$.pqNZZ4fRDdNbLhNlnEYg.1/d4yAGpLDgeXpJFI0sw7.WtyKphFzu', 'SMP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (2, 'the_admin@test-mail.eu','the_admin', '','the_admin', '', 'SMP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (3, 'AdminSMP1TEST@test-mail.eu','AdminSMP1TEST', '$2a$06$u6Hym7Zrbsf4gEIeAsJRceK.Kg7tei3kDypwucQQdky0lXOLCkrCO','AdminSMP1TEST', '$2a$06$u6Hym7Zrbsf4gEIeAsJRceK.Kg7tei3kDypwucQQdky0lXOLCkrCO', 'SMP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (4, 'AdminSMP2TEST@test-mail.eu','AdminSMP2TEST', '$2a$10$h8Q3Kjbs6ZrGkU6ditjNueINlJOMDJ/g/OKiqFZy32WmdhLjV5TAi','AdminSMP2TEST', '$2a$10$h8Q3Kjbs6ZrGkU6ditjNueINlJOMDJ/g/OKiqFZy32WmdhLjV5TAi', 'SMP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (5, 'test@test-mail.eu','test', '','test', '', 'SMP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (6, 'test1@test-mail.eu','test1', '$2a$06$toKXJgjqQINZdjQqSao3NeWz2n1S64PFPhVU1e8gIHh4xdbwzy1Uy','test1', '$2a$06$toKXJgjqQINZdjQqSao3NeWz2n1S64PFPhVU1e8gIHh4xdbwzy1Uy', 'SMP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (7, 'system@test-mail.eu','system', '$2a$06$FDmjewn/do3C219uysNm9.XG8mIn.ubHnMydAzC8lsv61HsRpOR36','system', '$2a$06$FDmjewn/do3C219uysNm9.XG8mIn.ubHnMydAzC8lsv61HsRpOR36', 'SYSTEM_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (8, 'smp@test-mail.eu','smp', '$2a$06$FDmjewn/do3C219uysNm9.XG8mIn.ubHnMydAzC8lsv61HsRpOR36','smp', '$2a$06$FDmjewn/do3C219uysNm9.XG8mIn.ubHnMydAzC8lsv61HsRpOR36', 'SMP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ACCESS_TOKEN_ID, ACCESS_TOKEN, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (9, 'user@test-mail.eu','user', '$2a$06$FDmjewn/do3C219uysNm9.XG8mIn.ubHnMydAzC8lsv61HsRpOR36','user', '$2a$06$FDmjewn/do3C219uysNm9.XG8mIn.ubHnMydAzC8lsv61HsRpOR36', 'SERVICE_GROUP_ADMIN', 1, NOW(), NOW()); + + +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (10,'EHEALTH_SMP_EC@test-mail.eu', 'EHEALTH_SMP_EC', '', 'SERVICE_GROUP_ADMIN', 1, NOW(), NOW()); insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_ON, LAST_UPDATED_ON) values (10, 'CN=EHEALTH_SMP_EC,O=European Commission,C=BE:f71ee8b11cb3b787', date_add(NOW(),interval -1 year), date_add(NOW(),interval 1 year), NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (11, 'EHEALTH_ż_ẞ_Ẅ_,O', '', 'SMP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (11,'EHEALTH_z_ẞ_W@test-mail.eu', 'EHEALTH_ż_ẞ_Ẅ_,O', '', 'SMP_ADMIN', 1, NOW(), NOW()); insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_ON, LAST_UPDATED_ON) values (11, 'CN=EHEALTH_z_ẞ_W_,O=European_z_ẞ_W_Commission,C=BE:f71ee8b11cb3b787', null,null, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (12, 'EHEALTH_SMP_1000000007-1', '', 'SERVICE_GROUP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (12,'EHEALTH_SMP_1000000007-1@test-mail.eu', 'EHEALTH_SMP_1000000007-1', '', 'SERVICE_GROUP_ADMIN', 1, NOW(), NOW()); insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_ON, LAST_UPDATED_ON) values (12, 'CN=EHEALTH_SMP_1000000007,O=DG-DIGIT,C=BE:000000000123ABCD', null,null, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (14, 'EHEALTH_SMP_1000000007-2', '', 'SMP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (14,'EHEALTH_SMP_1000000007-2@test-mail.eu', 'EHEALTH_SMP_1000000007-2', '', 'SMP_ADMIN', 1, NOW(), NOW()); insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_ON, LAST_UPDATED_ON) values (14, 'CN=EHEALTH_SMP_1000000007,O=DG-DIGIT,C=BE', null,null, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (15, 'EHEALTH&SMP_EC', '', 'SMP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (15,'EHEALTH-SMP_EC@test-mail.eu', 'EHEALTH&SMP_EC', '', 'SMP_ADMIN', 1, NOW(), NOW()); insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_ON, LAST_UPDATED_ON) values (15, 'CN=EHEALTH&SMP_EC,O=European&Commission,C=B&E:f71ee8b11cb3b787', null,null, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (16, 'EHEALTH_SMP_EC2', '', 'SMP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (16,'EHEALTH_SMP_EC2@test-mail.eu', 'EHEALTH_SMP_EC2', '', 'SMP_ADMIN', 1, NOW(), NOW()); insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_ON, LAST_UPDATED_ON) values (16, 'CN=EHEALTH_SMP_EC,O=European Commission,C=BE:000000000000100f', null,null, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (17, 'SMP_1000000007-3', '', 'SMP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (17,'SMP_1000000007-3@test-mail.eu', 'SMP_1000000007-3', '', 'SMP_ADMIN', 1, NOW(), NOW()); insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_ON, LAST_UPDATED_ON) values (17, 'CN=SMP_1000000007,O=DG-DIGIT,C=BE', null,null, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (18, 'SMP_1000000007-4', '', 'SMP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (18,'SMP_1000000007-4@test-mail.eu', 'SMP_1000000007-4', '', 'SMP_ADMIN', 1, NOW(), NOW()); insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_ON, LAST_UPDATED_ON) values (18, 'CN=SMP_1000000007,O=DG-DIGIT,C=BE:000000000123ABCD', null,null, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (19, 'SMP_1000000181,O=DIGIT,C=DK:123456789', '$2a$10$v2d/2E99dWHBM2ipTIip1enyaRKBTi.Xj/Iz0K8g0gjHBWdKRsHaC', 'SMP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (19,'SMP_1000000181@test-mail.eu', 'SMP_1000000181,O=DIGIT,C=DK:123456789', '$2a$10$v2d/2E99dWHBM2ipTIip1enyaRKBTi.Xj/Iz0K8g0gjHBWdKRsHaC', 'SMP_ADMIN', 1, NOW(), NOW()); insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_ON, LAST_UPDATED_ON) values (19, 'CN=SMP_1000000181,O=DIGIT,C=DK:123456789', null,null, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (20, 'red_gw', '', 'SERVICE_GROUP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (20,'red_gw@test-mail.eu', 'red_gw', '', 'SERVICE_GROUP_ADMIN', 1, NOW(), NOW()); insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_ON, LAST_UPDATED_ON) values (20, 'CN=red_gw,O=eDelivery,C=BE:9792CE69BC89F14C', null,null, NOW(), NOW()); -insert into SMP_USER (ID, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (21, 'blue_gw', '', 'SERVICE_GROUP_ADMIN', 1, NOW(), NOW()); +insert into SMP_USER (ID, EMAIL, USERNAME, PASSWORD, ROLE, ACTIVE, CREATED_ON, LAST_UPDATED_ON) values (21,'blue_gw@test-mail.eu', 'blue_gw', '', 'SERVICE_GROUP_ADMIN', 1, NOW(), NOW()); insert into SMP_CERTIFICATE (ID, CERTIFICATE_ID, VALID_FROM, VALID_TO, CREATED_ON, LAST_UPDATED_ON) values (21, 'CN=blue_gw,O=eDelivery,C=BE:e07b6b956330a19a', null,null, NOW(), NOW()); -- insert domain insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SML_SMP_ID, SIGNATURE_KEY_ALIAS, SML_CLIENT_KEY_ALIAS, SML_BLUE_COAT_AUTH,SML_REGISTERED, CREATED_ON, LAST_UPDATED_ON, SML_CLIENT_CERT_HEADER) -values (1, 'domain','','CEF-SMP-002', 'sample_key','sample_key', 1,0, NOW(), NOW(),'sno=1&subject=CN=SMP_TEST-PRE-SET-EXAMPLE, OU=eDelivery, O=DIGITAL, C=BE&validfrom=Dec 6 17:41:42 2016 GMT&validto=Jul 9 23:59:00 2050 GMT&issuer=CN=rootCNTest,OU=B4,O=DIGIT,L=Brussels,ST=BE,C=BE'); +values (1, 'domain','','CEF-SMP-001', 'sample_key','sample_key', 1,1, NOW(), NOW(),'sno=1&subject=CN=SMP_TEST-PRE-SET-EXAMPLE, OU=eDelivery, O=DIGITAL, C=BE&validfrom=Dec 6 17:41:42 2016 GMT&validto=Jul 9 23:59:00 2050 GMT&issuer=CN=rootCNTest,OU=B4,O=DIGIT,L=Brussels,ST=BE,C=BE'); insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SML_SMP_ID, SIGNATURE_KEY_ALIAS, SML_BLUE_COAT_AUTH,SML_REGISTERED, CREATED_ON, LAST_UPDATED_ON) values (2, 'domainB','subdomain002', 'CEF-SMP-002','sample_key',1,0, CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP()); insert into SMP_DOMAIN (ID, DOMAIN_CODE, SML_SUBDOMAIN, SML_SMP_ID, SIGNATURE_KEY_ALIAS, SML_BLUE_COAT_AUTH,SML_REGISTERED, CREATED_ON, LAST_UPDATED_ON) values (3, 'domainC','subdomain003', 'CEF-SMP-003','sample_key',1,0, CURRENT_TIMESTAMP(),CURRENT_TIMESTAMP()); diff --git a/smp-soapui-tests/pom.xml b/smp-soapui-tests/pom.xml index f85a1dbf5774dceb2abb755c755e8919a0c39327..aa9a0be65dbfb66452f59853685c62c5ecf40e4c 100644 --- a/smp-soapui-tests/pom.xml +++ b/smp-soapui-tests/pom.xml @@ -18,6 +18,7 @@ <SMPAdminUser></SMPAdminUser> <SMPAdminPassword></SMPAdminPassword> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> <profiles> @@ -111,27 +112,15 @@ </execution> </executions> </plugin> - <!-- dump jacoco.exec from remote agent and generate report --> + <!-- dump jacoco report from remote agent and generate report --> <plugin> <groupId>org.jacoco</groupId> <artifactId>jacoco-maven-plugin</artifactId> <version>${jacoco.maven.plugin.version}</version> <configuration> - <classDumpDir>${project.build.outputDirectory}</classDumpDir> + <classDumpDir>${project.build.outputDirectory}../target/</classDumpDir> </configuration> <executions> - <!-- execution> - <id>jacoco-agent</id> - <phase>pre-integration-test</phase> - <goals> - <goal>prepare-agent</goal> - </goals> - <configuration> - <destFile>${jacoco.reportPath}</destFile> - <propertyName>jacoco.agent.itArgLine</propertyName> - </configuration> - </execution --> - <execution> <phase>post-integration-test</phase> <goals> diff --git a/smp-spi/pom.xml b/smp-spi/pom.xml index ead4a25ebaf238872c2df608177fc60f3b7ad327..d626978bb7f52e8bb27cf8928adb5cc59651b016 100644 --- a/smp-spi/pom.xml +++ b/smp-spi/pom.xml @@ -20,25 +20,16 @@ <version>4.2-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> - <artifactId>smp-spi</artifactId> <name>smp-spi</name> <description>SMP Service provider interface (SPI). The SMP SPI is an application interface intended to be implemented or extended by a third party as library. The libraries must be added to SMP library directory and are loaded at startup.</description> + <packaging>jar</packaging> <dependencies> - <dependency> - <groupId>ch.qos.logback</groupId> - <artifactId>logback-classic</artifactId> - </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> </dependency> - <dependency> - <groupId>org.hamcrest</groupId> - <artifactId>hamcrest-junit</artifactId> - <scope>test</scope> - </dependency> </dependencies> <build> <plugins> diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPInitializer.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPInitializer.java index 8a6e92192f70c44d7e8f443e80cce6516f55d2e4..a104ac0f3ae558ef0d9ba2bdd47711cd0d357dcd 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPInitializer.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/config/SMPInitializer.java @@ -1,49 +1,43 @@ package eu.europa.ec.edelivery.smp.config; -import eu.europa.ec.edelivery.smp.auth.URLCsrfIgnoreMatcher; -import eu.europa.ec.edelivery.smp.exceptions.ErrorCode; -import eu.europa.ec.edelivery.smp.exceptions.SMPRuntimeException; import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory; import eu.europa.ec.edelivery.smp.utils.ExtLibraryClassLoader; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.exception.ExceptionUtils; -import org.apache.commons.text.StringSubstitutor; import org.slf4j.Logger; import org.springframework.web.WebApplicationInitializer; import javax.servlet.ServletContext; -import javax.servlet.ServletException; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.util.Properties; -import static eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum.CONFIGURATION_DIR; - public class SMPInitializer implements WebApplicationInitializer { private static final String FILE_APPLICATION_PROPERTIES = "/application.properties"; - private static final String PROP_BUILD_NAME = "smp.artifact.name"; - private static final String PROP_BUILD_VERSION = "smp.artifact.version"; - private static final String PROP_BUILD_TIME = "smp.artifact.build.time"; + protected static final String PROP_BUILD_NAME = "smp.artifact.name"; + protected static final String PROP_BUILD_VERSION = "smp.artifact.version"; + protected static final String PROP_BUILD_TIME = "smp.artifact.build.time"; + protected static final String VERSION_LOG_TEMPLATE = "Start application: name: {}, version: {}, build time: {}."; + + private static final Logger LOG = SMPLoggerFactory.getLogger(SMPInitializer.class); - private static final Logger LOG = SMPLoggerFactory.getLogger( - SMPInitializer.class); @Override - public void onStartup(ServletContext servletContext) throws ServletException { + public void onStartup(ServletContext servletContext) { Properties fileProperties = FileProperty.getFileProperties(); - logBuildProperties(); + logBuildProperties(LOG, FILE_APPLICATION_PROPERTIES); // load external libraries String libraryFolderPath = StringUtils.trim(fileProperties.getProperty(FileProperty.PROPERTY_LIB_FOLDER, null)); - if (StringUtils.isNotBlank(libraryFolderPath)){ + if (StringUtils.isNotBlank(libraryFolderPath)) { File fLibraryDir = new File(libraryFolderPath); ExtLibraryClassLoader pluginClassLoader = createLibraryClassLoader(fLibraryDir); - if (pluginClassLoader!=null){ + if (pluginClassLoader != null) { LOG.debug("Add libraries from the folder: [{}]!", libraryFolderPath); Thread.currentThread().setContextClassLoader(pluginClassLoader); } @@ -55,22 +49,22 @@ public class SMPInitializer implements WebApplicationInitializer { /** * Method reads internal 'application.properties' file and prints the build version to the logs */ - protected void logBuildProperties() { - InputStream is = PropertyInitialization.class.getResourceAsStream(FILE_APPLICATION_PROPERTIES); + protected void logBuildProperties(Logger log, String versionResource) { + InputStream is = SMPInitializer.class.getResourceAsStream(versionResource); if (is != null) { Properties applProp = new Properties(); try { applProp.load(is); - LOG.info("*****************************************************************************************"); - LOG.info("Start application: name: {}, version: {}, build time: {}.", applProp.getProperty(PROP_BUILD_NAME) + log.info("*****************************************************************************************"); + log.info(VERSION_LOG_TEMPLATE, applProp.getProperty(PROP_BUILD_NAME) , applProp.getProperty(PROP_BUILD_VERSION) , applProp.getProperty(PROP_BUILD_TIME)); - LOG.info("*****************************************************************************************"); + log.info("*****************************************************************************************"); } catch (IOException e) { - LOG.error("Error occurred while reading application properties. Is file " + FILE_APPLICATION_PROPERTIES + " included in war!", e); + log.error("Error occurred while reading application properties. Is file " + FILE_APPLICATION_PROPERTIES + " included in war!", e); } } else { - LOG.error("Not found application build properties: {}!", FILE_APPLICATION_PROPERTIES); + log.error("Not found application build properties: {}!", FILE_APPLICATION_PROPERTIES); } } @@ -82,11 +76,11 @@ public class SMPInitializer implements WebApplicationInitializer { */ protected ExtLibraryClassLoader createLibraryClassLoader(File smpLibraryFolder) { LOG.info("Load libraries from location [{}]", smpLibraryFolder); - if (!smpLibraryFolder.exists() ) { + if (!smpLibraryFolder.exists()) { LOG.warn("Library folder [{}] does not exist! No libraries are loaded!", smpLibraryFolder.getAbsolutePath()); return null; } - if (!smpLibraryFolder.isDirectory() ) { + if (!smpLibraryFolder.isDirectory()) { LOG.warn("Library folder [{}] is not a folder! No libraries are loaded!", smpLibraryFolder.getAbsolutePath()); return null; } diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/PropertyResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/PropertyResource.java index 3b042080805e1cf844cb50d48fcbebb66a9c5608..cd0f3265992c580cfe25731bc47721682e41d1c0 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/PropertyResource.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/internal/PropertyResource.java @@ -2,11 +2,12 @@ package eu.europa.ec.edelivery.smp.ui.internal; import eu.europa.ec.edelivery.smp.data.ui.PropertyRO; +import eu.europa.ec.edelivery.smp.data.ui.PropertyValidationRO; import eu.europa.ec.edelivery.smp.data.ui.ServiceResult; -import eu.europa.ec.edelivery.smp.data.ui.UserRO; import eu.europa.ec.edelivery.smp.data.ui.auth.SMPAuthority; import eu.europa.ec.edelivery.smp.logging.SMPLogger; import eu.europa.ec.edelivery.smp.logging.SMPLoggerFactory; +import eu.europa.ec.edelivery.smp.services.ConfigurationService; import eu.europa.ec.edelivery.smp.services.ui.UIPropertyService; import org.springframework.security.access.annotation.Secured; import org.springframework.util.MimeTypeUtils; @@ -27,13 +28,15 @@ public class PropertyResource { private static final SMPLogger LOG = SMPLoggerFactory.getLogger(PropertyResource.class); final UIPropertyService uiPropertyService; + final ConfigurationService configurationService; - public PropertyResource(UIPropertyService uiPropertyService) { + public PropertyResource(UIPropertyService uiPropertyService, ConfigurationService configurationService) { this.uiPropertyService = uiPropertyService; + this.configurationService = configurationService; } @GetMapping(produces = {MimeTypeUtils.APPLICATION_JSON_VALUE}) - public ServiceResult<PropertyRO> geDomainList( + public ServiceResult<PropertyRO> gePropertyList( @RequestParam(value = PARAM_PAGINATION_PAGE, defaultValue = "0") int page, @RequestParam(value = PARAM_PAGINATION_PAGE_SIZE, defaultValue = "10") int pageSize, @RequestParam(value = PARAM_PAGINATION_ORDER_BY, required = false) String orderBy, @@ -52,4 +55,11 @@ public class PropertyResource { uiPropertyService.updatePropertyList(Arrays.asList(updateEntities)); } + @PostMapping(path = "/validate", consumes = MimeTypeUtils.APPLICATION_JSON_VALUE, produces = MimeTypeUtils.APPLICATION_JSON_VALUE) + @Secured({SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN}) + public PropertyValidationRO validateProperty(@RequestBody PropertyRO propertyRO) { + LOG.info("Validate property: [{}]", propertyRO.getProperty()); + return uiPropertyService.validateProperty(propertyRO); + } + } diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/config/SMPInitializerTest.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/config/SMPInitializerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..999439ff6fe87ec2038e51c63af65b2371ae5658 --- /dev/null +++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/config/SMPInitializerTest.java @@ -0,0 +1,64 @@ +package eu.europa.ec.edelivery.smp.config; + +import eu.europa.ec.edelivery.smp.utils.ExtLibraryClassLoader; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.slf4j.Logger; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; + +import static org.junit.Assert.*; + +public class SMPInitializerTest { + + SMPInitializer testInstance = new SMPInitializer(); + @Test + public void onStartup() { + } + + @Test + public void logBuildProperties() { + Logger log = Mockito.mock(Logger.class); + testInstance.logBuildProperties(log, "/test-application.properties"); + + ArgumentCaptor<String> template = ArgumentCaptor.forClass(String.class); + ArgumentCaptor<String> name = ArgumentCaptor.forClass(String.class); + ArgumentCaptor<String> version = ArgumentCaptor.forClass(String.class); + ArgumentCaptor<String> date = ArgumentCaptor.forClass(String.class); + + Mockito.verify(log, Mockito.times(2)).info(Mockito.anyString()); + Mockito.verify(log, Mockito.times(1)).info(template.capture(), + name.capture(), + version.capture(), + date.capture() ); + + assertEquals(SMPInitializer.VERSION_LOG_TEMPLATE, template.getValue()); + assertEquals("eDelivery test SMP", name.getValue()); + assertEquals("1.0", version.getValue()); + assertEquals("2022-05-05T12:00:00Z", date.getValue()); + } + + @Test + public void createLibraryClassLoaderNotExists() { + ExtLibraryClassLoader loader= testInstance.createLibraryClassLoader(new File("FileNotExists")); + assertNull(loader); + } + + @Test + public void createLibraryClassLoaderIsNotFolder() { + ExtLibraryClassLoader loader= testInstance.createLibraryClassLoader(new File("./pom.xml")); + assertNull(loader); + } + + @Test + public void createLibraryClassLoader() { + // folder contains one library jar simple-extension.jar with the resource logback-test.xml + Path path = Paths.get("src","test","resources", "test-libs"); + ExtLibraryClassLoader loader= testInstance.createLibraryClassLoader(path.toFile()); + assertNotNull(loader); + assertNotNull(loader.getResource("logback-test.xml")); + } +} \ No newline at end of file diff --git a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/test/PropertiesTestConfig.java b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/test/PropertiesTestConfig.java index cb762ced6b78937a68a9bc20a6622699581b892d..b649d1c9f9a6d5abb85f4308fc859b11be734d03 100644 --- a/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/test/PropertiesTestConfig.java +++ b/smp-webapp/src/test/java/eu/europa/ec/edelivery/smp/test/PropertiesTestConfig.java @@ -13,6 +13,7 @@ package eu.europa.ec.edelivery.smp.test; +import eu.europa.ec.edelivery.smp.config.FileProperty; import eu.europa.ec.edelivery.smp.config.PropertiesConfig; import org.springframework.context.annotation.*; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; @@ -34,17 +35,25 @@ import static eu.europa.ec.edelivery.smp.data.ui.enums.SMPPropertyEnum.*; @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = PropertiesConfig.class)}) public class PropertiesTestConfig { + public static final String DATABASE_URL="jdbc:h2:file:./target/myDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE;AUTO_SERVER=TRUE"; + public static final String DATABASE_USERNAME="smp"; + public static final String DATABASE_PASS="smp"; + public static final String DATABASE_DRIVER="org.h2.Driver"; + public static final String DATABASE_DIALECT="org.hibernate.dialect.H2Dialect"; + + @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { // update keystore PropertySourcesPlaceholderConfigurer propertiesConfig = new PropertySourcesPlaceholderConfigurer(); Properties localProps = new Properties(); - localProps.setProperty("jdbc.driverClassName", "org.h2.Driver"); - localProps.setProperty("jdbc.url", "jdbc:h2:file:./target/myDb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=TRUE;AUTO_SERVER=TRUE"); - localProps.setProperty("jdbc.user", "smp"); - localProps.setProperty("jdbc.pass", "smp"); - localProps.setProperty("spring.jpa.properties.hibernate.dialect", "org.hibernate.dialect.H2Dialect"); + localProps.setProperty(FileProperty.PROPERTY_DB_DIALECT, DATABASE_DIALECT); + localProps.setProperty(FileProperty.PROPERTY_DB_DRIVER, DATABASE_DRIVER); + localProps.setProperty(FileProperty.PROPERTY_DB_URL, DATABASE_URL); + localProps.setProperty(FileProperty.PROPERTY_DB_USER,DATABASE_USERNAME); + localProps.setProperty(FileProperty.PROPERTY_DB_TOKEN, DATABASE_PASS); + // create database objects if not exists for the test localProps.setProperty("spring.jpa.generate-ddl", "true"); localProps.setProperty("spring.jpa.properties.hibernate.hbm2ddl.auto", "create"); diff --git a/smp-webapp/src/test/resources/test-application.properties b/smp-webapp/src/test/resources/test-application.properties new file mode 100644 index 0000000000000000000000000000000000000000..5d005228329b64251d810b94bca2f347bfc41e3e --- /dev/null +++ b/smp-webapp/src/test/resources/test-application.properties @@ -0,0 +1,3 @@ +smp.artifact.name=eDelivery test SMP +smp.artifact.version=1.0 +smp.artifact.build.time=2022-05-05T12:00:00Z \ No newline at end of file diff --git a/smp-webapp/src/test/resources/test-libs/simple-extension.jar b/smp-webapp/src/test/resources/test-libs/simple-extension.jar new file mode 100644 index 0000000000000000000000000000000000000000..991ee4cc4660cb706f3ef484d25a4a11132584ab Binary files /dev/null and b/smp-webapp/src/test/resources/test-libs/simple-extension.jar differ