diff --git a/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-dialog.component.ts b/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-dialog.component.ts index c52d10d668754a98aac2b7cf7c870293ed20c2c4..ff3fe7f49a9c6c38aa0176a224dcff472cd9200d 100644 --- a/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-dialog.component.ts +++ b/smp-angular/src/app/service-group-edit/service-metadata-wizard-dialog/service-metadata-wizard-dialog.component.ts @@ -4,7 +4,7 @@ import {FormBuilder, FormControl, FormGroup, Validators} from "@angular/forms"; import {HttpClient} from "@angular/common/http"; import {SmpConstants} from "../../smp.constants"; import {ServiceMetadataEditRo} from "../service-metadata-edit-ro.model"; - +import {CertificateService} from "../../user/certificate.service"; @Component({ selector: 'service-metadata-wizard-dialog', @@ -17,22 +17,22 @@ export class ServiceMetadataWizardDialogComponent { static readonly EDIT_MODE = 'Edit ServiceMetadata XML'; editMode: boolean; - formTitle: string; current: ServiceMetadataEditRo & { confirmation?: string }; dialogForm: FormGroup; certificateValidationMessage: string; isCertificateValid: string; selectedFile: File; - dummyXML: string = "<!-- Custom element is mandatory by OASIS SMP schema.\n Replace following element with your XML structure. -->\n<ext:example xmlns:ext=\"http://my.namespace.eu\">my mandatory content</ext:example>" - + // dummyXML: string = "<!-- Custom element is mandatory by OASIS SMP schema.\n Replace following element with your XML structure. -->\n<ext:example xmlns:ext=\"http://my.namespace.eu\">my mandatory content</ext:example>" - constructor( protected http: HttpClient, - public dialogRef: MatDialogRef<ServiceMetadataWizardDialogComponent>, - private dialogFormBuilder: FormBuilder) { + constructor( + private http: HttpClient, + private dialogRef: MatDialogRef<ServiceMetadataWizardDialogComponent>, + private dialogFormBuilder: FormBuilder, + private certificateService: CertificateService, + ) { this.dialogForm = dialogFormBuilder.group({ - 'documentIdentifier': new FormControl({value: ''}, [Validators.required]), 'documentIdentifierScheme': new FormControl({value: ''}, null), 'processScheme': new FormControl({value: ''}, [Validators.required]), @@ -49,14 +49,12 @@ export class ServiceMetadataWizardDialogComponent { onUpload() { // this.http is the injected HttpClient - this.http.post(SmpConstants.REST_CERTIFICATE, this.selectedFile) + this.certificateService.uploadCertificate$(this.selectedFile) .subscribe(event => { - console.log(event); // handle event here }); } - getExtensionXML() { /* var xmlString = '<Extension xmlns="http://docs.oasis-open.org/bdxr/ns/SMP/2016/05">' @@ -79,6 +77,4 @@ export class ServiceMetadataWizardDialogComponent { .replace(/>/g, ">") .replace(/"/g, """); } - - } diff --git a/smp-angular/src/app/smp.constants.ts b/smp-angular/src/app/smp.constants.ts index cdded6c53ba93102b76dec3f6ca96984696a77c9..ad7858ded07b5d6992669106f4d4cb785aa28acd 100644 --- a/smp-angular/src/app/smp.constants.ts +++ b/smp-angular/src/app/smp.constants.ts @@ -9,8 +9,6 @@ export class SmpConstants { public static readonly REST_SECURITY_USER = 'rest/security/user'; public static readonly REST_APPLICATION = 'rest/application/info'; - - public static readonly REST_CERTIFICATE = `${SmpConstants.REST_USER}/certdata`; public static readonly REST_USER_VALIDATE_DELETE = `${SmpConstants.REST_USER}/validateDelete`; public static readonly REST_DOMAIN_VALIDATE_DELETE = `${SmpConstants.REST_DOMAIN}/validateDelete`; public static readonly REST_SERVICE_GROUP_EXTENSION = `${SmpConstants.REST_EDIT}/extension`; diff --git a/smp-angular/src/app/user/certificate.service.ts b/smp-angular/src/app/user/certificate.service.ts index 7c969c1800b73f8c0ae1ce43fce1d1e62d322f30..30508bf7b4d4ddb1af24ca42fef359410136f86e 100644 --- a/smp-angular/src/app/user/certificate.service.ts +++ b/smp-angular/src/app/user/certificate.service.ts @@ -3,13 +3,22 @@ import {Observable} from 'rxjs'; import {CertificateRo} from './certificate-ro.model'; import {HttpClient} from '@angular/common/http'; import {SmpConstants} from "../smp.constants"; +import {SecurityService} from "../security/security.service"; +import {User} from "../security/user.model"; @Injectable() export class CertificateService { - constructor(private http: HttpClient) {} + constructor( + private http: HttpClient, + private securityService: SecurityService, + ) { } uploadCertificate$(payload): Observable<CertificateRo> { - return this.http.post<CertificateRo>(SmpConstants.REST_CERTIFICATE, payload); + // The user identifier below belongs to the currently logged in user and it may or may not be the same as the + // identifier of the user being modified (e.g. a normal user editing his own details vs. a system administrator + // adding or editing another user) + const currentUser: User = this.securityService.getCurrentUser(); + return this.http.post<CertificateRo>(`${SmpConstants.REST_USER}/${currentUser.id}/certdata`, payload); } } diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java index d3532a18e6b415912a02153bbcba7e37507c8f33..ed090465fc0f1beeeb6c890f89d824d24e50e1df 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/auth/SMPAuthorizationService.java @@ -5,12 +5,20 @@ import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; +import static eu.europa.ec.edelivery.smp.auth.SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN; + /** * @author Sebastian-Ion TINCU */ @Service("smpAuthorizationService") public class SMPAuthorizationService { + public boolean isSystemAdministrator() { + Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); + return authentication instanceof SMPAuthenticationToken + && authentication.getAuthorities().stream().anyMatch(grantedAuthority -> S_AUTHORITY_TOKEN_SYSTEM_ADMIN.equals(grantedAuthority.getAuthority())); + } + public boolean isCurrentlyLoggedIn(Long userId) { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if(authentication instanceof SMPAuthenticationToken) { diff --git a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/UserResource.java b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/UserResource.java index 5a9d549d9d9ea3926e77514bb0f41f8e93b1d3f2..f2f9832f9ac5e185551d26a0ffef1623fbc80d11 100644 --- a/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/UserResource.java +++ b/smp-webapp/src/main/java/eu/europa/ec/edelivery/smp/ui/UserResource.java @@ -77,9 +77,9 @@ public class UserResource { uiUserService.updateUserList(Arrays.asList(updateEntities)); } - @RequestMapping(path = "certdata", method = RequestMethod.POST) - @Secured({SMPAuthority.S_AUTHORITY_TOKEN_SYSTEM_ADMIN}) - public CertificateRO uploadFile(@RequestBody byte[] data) { + @PostMapping("/{id}/certdata") + @PreAuthorize("@smpAuthorizationService.systemAdministrator || @smpAuthorizationService.isCurrentlyLoggedIn(#id)") + public CertificateRO uploadFile(@PathVariable("id") Long id, @RequestBody byte[] data) { LOG.info("Got certificate data: " + data.length); try { return uiUserService.getCertificateData(data);