diff --git a/pom.xml b/pom.xml
index 959dce25..58cdc366 100644
--- a/pom.xml
+++ b/pom.xml
@@ -186,6 +186,11 @@
spring-cloud-stream-test-binder
test
+
+ org.springframework.security
+ spring-security-test
+ test
+
org.springframework
spring-web
diff --git a/src/main/java/org/gridsuite/explore/server/UserAuthentication.java b/src/main/java/org/gridsuite/explore/server/UserAuthentication.java
new file mode 100644
index 00000000..26317a7d
--- /dev/null
+++ b/src/main/java/org/gridsuite/explore/server/UserAuthentication.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2026, RTE (http://www.rte-france.com)
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+package org.gridsuite.explore.server;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class UserAuthentication implements Authentication {
+
+ private final String principal;
+
+ private final Collection authorities;
+
+ private boolean authenticated = false;
+
+ public UserAuthentication(String principal, Collection extends GrantedAuthority> authorities) {
+ this.principal = principal;
+ this.authorities = authorities == null
+ ? AuthorityUtils.NO_AUTHORITIES
+ : Collections.unmodifiableList(new ArrayList<>(authorities));
+ setAuthenticated(true);
+ }
+
+ public UserAuthentication(String principal, String roles) {
+ List authorities = Collections.emptyList();
+ if (roles != null && !roles.isEmpty()) {
+ authorities = Arrays.stream(roles.split("\\|"))
+ .map(String::trim)
+ .filter(role -> !role.isEmpty())
+ .map(SimpleGrantedAuthority::new)
+ .map(GrantedAuthority.class::cast)
+ .toList();
+ }
+ this(principal, authorities);
+ }
+
+ // TODO: pour les roles, on recoit un String ou une liste d'authorities ? on renvoie un String on une liste d'authorities ?
+
+ public String getUserId() {
+ return principal;
+ }
+
+ public String getRoles() {
+ return authorities.stream()
+ .map(GrantedAuthority::getAuthority)
+ .collect(Collectors.joining("|"));
+ }
+
+ // methods needed by interface
+
+ @Override
+ public String getName() {
+ return principal;
+ }
+
+ @Override
+ public String getPrincipal() {
+ return this.principal;
+ }
+
+ @Override
+ public Collection getAuthorities() {
+ return this.authorities;
+ }
+
+ @Override
+ public boolean isAuthenticated() {
+ return this.authenticated;
+ }
+
+ @Override
+ public void setAuthenticated(boolean authenticated) {
+ this.authenticated = authenticated;
+ }
+
+ @Override
+ public Object getCredentials() {
+ return null;
+ }
+
+ @Override
+ public Object getDetails() {
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(getClass().getSimpleName()).append(" [");
+ sb.append("Principal=").append(getPrincipal()).append(", ");
+ sb.append("Authenticated=").append(isAuthenticated()).append(", ");
+ sb.append("Granted Authorities=").append(this.authorities);
+ sb.append("]");
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/org/gridsuite/explore/server/RestTemplateConfig.java b/src/main/java/org/gridsuite/explore/server/config/RestTemplateConfig.java
similarity index 76%
rename from src/main/java/org/gridsuite/explore/server/RestTemplateConfig.java
rename to src/main/java/org/gridsuite/explore/server/config/RestTemplateConfig.java
index aad5e2ec..931097c0 100644
--- a/src/main/java/org/gridsuite/explore/server/RestTemplateConfig.java
+++ b/src/main/java/org/gridsuite/explore/server/config/RestTemplateConfig.java
@@ -4,11 +4,11 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
-package org.gridsuite.explore.server;
+package org.gridsuite.explore.server.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
-import jakarta.servlet.http.HttpServletRequest;
+import org.gridsuite.explore.server.UserAuthentication;
import org.springframework.boot.jackson.JsonComponentModule;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
@@ -20,9 +20,8 @@
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.client.RestTemplate;
-import org.springframework.web.context.request.RequestContextHolder;
-import org.springframework.web.context.request.ServletRequestAttributes;
import java.io.IOException;
import java.util.Collections;
@@ -43,39 +42,38 @@ public RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
if (httpMessageConverter instanceof MappingJackson2HttpMessageConverter) {
restTemplate.getMessageConverters().set(i, mappingJackson2HttpMessageConverter());
}
-
- restTemplate.setInterceptors(
- Collections.singletonList(new RoleHeaderForwardingInterceptor())
- );
}
+ restTemplate.setInterceptors(
+ Collections.singletonList(new HeaderForwardingInterceptor())
+ );
+
return restTemplate;
}
/**
- * In our microservice architecture, user permissions (roles) must be preserved when
- * one service calls another. This interceptor automatically forwards the "roles" header
+ * In our microservice architecture, user permissions (userId and roles) must be preserved when
+ * one service calls another. This interceptor automatically forwards the "userId" and "roles" headers
* from incoming requests to any outgoing REST calls made with this RestTemplate.
*
* Without this interceptor, authorization information would be lost in service-to-service
* communication.
*/
- public static class RoleHeaderForwardingInterceptor implements ClientHttpRequestInterceptor {
+ public static class HeaderForwardingInterceptor implements ClientHttpRequestInterceptor {
private static final String ROLES_HEADER = "roles";
+ private static final String USER_ID_HEADER = "userId";
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body,
ClientHttpRequestExecution execution) throws IOException {
- ServletRequestAttributes attributes =
- (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+ UserAuthentication authentication = (UserAuthentication) SecurityContextHolder.getContext().getAuthentication();
- // If we have a current request, copy its roles header to the outgoing request
- if (attributes != null) {
- HttpServletRequest currentRequest = attributes.getRequest();
- String roles = currentRequest.getHeader(ROLES_HEADER);
+ if (authentication != null) {
+ request.getHeaders().set(USER_ID_HEADER, authentication.getUserId());
- if (roles != null && !roles.isEmpty()) {
+ String roles = authentication.getRoles();
+ if (!roles.isEmpty()) {
request.getHeaders().set(ROLES_HEADER, roles);
}
}
diff --git a/src/main/java/org/gridsuite/explore/server/config/SecurityFilter.java b/src/main/java/org/gridsuite/explore/server/config/SecurityFilter.java
new file mode 100644
index 00000000..f9fddd57
--- /dev/null
+++ b/src/main/java/org/gridsuite/explore/server/config/SecurityFilter.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2026, RTE (http://www.rte-france.com)
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+package org.gridsuite.explore.server.config;
+
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+import org.gridsuite.explore.server.UserAuthentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import java.io.IOException;
+
+/**
+ * @author Caroline Jeandat
+ */
+public class SecurityFilter extends OncePerRequestFilter {
+
+ private static final String HEADER_ROLES = "roles";
+ private static final String HEADER_USER_ID = "userId";
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+ throws ServletException, IOException {
+
+ String userId = request.getHeader(HEADER_USER_ID);
+ String rolesHeader = request.getHeader(HEADER_ROLES);
+
+ if (userId != null && !userId.isEmpty()) {
+ SecurityContextHolder.getContext().setAuthentication(new UserAuthentication(userId, rolesHeader));
+ /*
+ Set roles = Collections.emptySet();
+ if (rolesHeader != null && !rolesHeader.isEmpty()) {
+ roles = Arrays.stream(rolesHeader.split("\\|"))
+ .map(String::trim)
+ .filter(role -> !role.isEmpty())
+ .collect(Collectors.toSet());
+ }
+ userContext.setUserId(userId);
+ userContext.setRoles(roles);
+ */
+ }
+
+ filterChain.doFilter(request, response);
+ }
+}
diff --git a/src/main/java/org/gridsuite/explore/server/config/SpringSecurityConfig.java b/src/main/java/org/gridsuite/explore/server/config/SpringSecurityConfig.java
new file mode 100644
index 00000000..dae85e37
--- /dev/null
+++ b/src/main/java/org/gridsuite/explore/server/config/SpringSecurityConfig.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2026, RTE (http://www.rte-france.com)
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+package org.gridsuite.explore.server.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.context.SecurityContextHolderFilter;
+
+/**
+ * @author Caroline Jeandat
+ */
+@Configuration
+@EnableWebSecurity
+public class SpringSecurityConfig {
+
+ @Bean
+ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
+ http
+ .csrf(AbstractHttpConfigurer::disable)
+ .authorizeHttpRequests(authorize -> authorize
+ .anyRequest().permitAll()
+ )
+ .addFilterAfter(new SecurityFilter(), SecurityContextHolderFilter.class);
+
+ return http.build();
+ }
+}
diff --git a/src/main/java/org/gridsuite/explore/server/controller/ActionsController.java b/src/main/java/org/gridsuite/explore/server/controller/ActionsController.java
index e2b56907..21608f0d 100644
--- a/src/main/java/org/gridsuite/explore/server/controller/ActionsController.java
+++ b/src/main/java/org/gridsuite/explore/server/controller/ActionsController.java
@@ -14,6 +14,7 @@
import org.gridsuite.explore.server.services.ContingencyListService;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -32,18 +33,22 @@ public ActionsController(ContingencyListService contingencyListService) {
this.contingencyListService = contingencyListService;
}
+ // TODO: on récupère l'élément depuis actions-server, donc vérifier qu'il existe bien dans directory-server
@GetMapping(value = "/identifier-contingency-lists/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Get identifier contingency list by id from actions-server")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The identifier contingency list"),
@ApiResponse(responseCode = "404", description = "The identifier contingency list does not exists")})
+ @PreAuthorize("@authorizationService.canRead(#id)")
public ResponseEntity getIdentifierContingencyList(@PathVariable("id") UUID id) {
return ResponseEntity.ok(contingencyListService.getIdentifierContingencyList(id));
}
+ // TODO: on récupère l'élément depuis actions-server, donc vérifier qu'il existe bien dans directory-server
@GetMapping(value = "/filters-contingency-lists/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Get filter based contingency list by id from actions-server")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The filter based contingency list"),
@ApiResponse(responseCode = "404", description = "The filter based contingency list does not exists")})
+ @PreAuthorize("@authorizationService.canRead(#id)")
public ResponseEntity getFilterBasedContingencyList(@PathVariable("id") UUID id) {
return ResponseEntity.ok(contingencyListService.getFilterBasedContingencyList(id));
}
diff --git a/src/main/java/org/gridsuite/explore/server/controller/CaseController.java b/src/main/java/org/gridsuite/explore/server/controller/CaseController.java
index 57325eeb..0bfaee0f 100644
--- a/src/main/java/org/gridsuite/explore/server/controller/CaseController.java
+++ b/src/main/java/org/gridsuite/explore/server/controller/CaseController.java
@@ -35,23 +35,27 @@ public CaseController(CaseService caseService) {
this.caseService = caseService;
}
+ // TODO: rien à checker
@PostMapping(value = "/cases", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity importCase(@RequestPart("file") MultipartFile file,
@RequestParam(value = "withExpiration", required = false, defaultValue = "false") boolean withExpiration) {
return ResponseEntity.ok(caseService.importCaseWithoutDirectoryElementCreation(file, withExpiration));
}
+ // TODO: appel à case-server et pas à directory-server -> rien à checker ?? vérifier l'utilité de cet endpoint
@DeleteMapping(value = "/cases/{caseUuid}")
public ResponseEntity deleteCase(@PathVariable("caseUuid") UUID caseUuid) {
caseService.deleteCase(caseUuid);
return ResponseEntity.ok().build();
}
+ // TODO: appel à case-server et pas à directory-server -> rien à checker ?? vérifier l'utilité de cet endpoint
@GetMapping(value = "/cases/{caseUuid}")
public ResponseEntity downloadCase(@PathVariable("caseUuid") UUID caseUuid) {
return caseService.downloadCase(caseUuid);
}
+ // TODO: rien à checker
@GetMapping(value = "/cases/caseBaseName")
public ResponseEntity getBaseName(@RequestParam("caseName") String caseName) {
return ResponseEntity.ok(caseService.getBaseName(caseName));
diff --git a/src/main/java/org/gridsuite/explore/server/controller/ExploreController.java b/src/main/java/org/gridsuite/explore/server/controller/ExploreController.java
index 3c4d47e6..2987ce6b 100644
--- a/src/main/java/org/gridsuite/explore/server/controller/ExploreController.java
+++ b/src/main/java/org/gridsuite/explore/server/controller/ExploreController.java
@@ -46,7 +46,6 @@ public class ExploreController {
private static final String QUERY_PARAM_PARENT_DIRECTORY_ID = "parentDirectoryUuid";
private static final String QUERY_PARAM_TYPE = "type";
- private static final String QUERY_PARAM_USER_ID = "userId";
private final ExploreService exploreService;
private final DirectoryService directoryService;
@@ -56,141 +55,134 @@ public ExploreController(ExploreService exploreService, DirectoryService directo
this.directoryService = directoryService;
}
+ // TODO
@PostMapping(value = "/explore/studies/{studyName}/cases/{caseUuid}")
@Operation(summary = "create a study from an existing case")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Study creation request delegated to study server")})
- @PreAuthorize("@authorizationService.isAuthorized(#userId, #parentDirectoryUuid, null, T(org.gridsuite.explore.server.dto.PermissionType).WRITE)")
+ @PreAuthorize("@authorizationService.canWrite(#parentDirectoryUuid)")
public ResponseEntity createStudy(@PathVariable("studyName") String studyName,
@PathVariable("caseUuid") UUID caseUuid,
@RequestParam(name = "caseFormat") String caseFormat,
@RequestParam(name = "duplicateCase", required = false, defaultValue = "false") Boolean duplicateCase,
@RequestParam("description") String description,
@RequestParam(QUERY_PARAM_PARENT_DIRECTORY_ID) UUID parentDirectoryUuid,
- @RequestHeader(QUERY_PARAM_USER_ID) String userId,
@RequestBody(required = false) Map importParams) {
- exploreService.assertCanCreateCase(userId);
+ exploreService.assertCanCreateCase();
CaseInfo caseInfo = new CaseInfo(caseUuid, caseFormat);
- exploreService.createStudy(studyName, caseInfo, description, userId, parentDirectoryUuid, importParams, duplicateCase);
+ exploreService.createStudy(studyName, caseInfo, description, parentDirectoryUuid, importParams, duplicateCase);
return ResponseEntity.ok().build();
}
@PostMapping(value = "/explore/studies/{id}/duplicate")
@Operation(summary = "Duplicate a study")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Study creation request delegated to study server")})
- @PreAuthorize("@authorizationService.isAuthorizedForDuplication(#userId, #studyId, #targetDirectoryId)")
+ @PreAuthorize("@authorizationService.canDuplicateTo(#studyId, #targetDirectoryId)")
public ResponseEntity duplicateStudy(@PathVariable("id") UUID studyId,
- @RequestParam(name = QUERY_PARAM_PARENT_DIRECTORY_ID, required = false) UUID targetDirectoryId,
- @RequestHeader(QUERY_PARAM_USER_ID) String userId) {
- exploreService.assertCanCreateCase(userId);
- exploreService.duplicateStudy(studyId, targetDirectoryId, userId);
+ @RequestParam(name = QUERY_PARAM_PARENT_DIRECTORY_ID, required = false) UUID targetDirectoryId) {
+ exploreService.assertCanCreateCase();
+ exploreService.duplicateStudy(studyId, targetDirectoryId);
return ResponseEntity.ok().build();
}
@PostMapping(value = "/explore/cases/{caseName}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
@Operation(summary = "create a case")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Case creation request delegated to case server")})
- @PreAuthorize("@authorizationService.isAuthorized(#userId, #parentDirectoryUuid, null, T(org.gridsuite.explore.server.dto.PermissionType).WRITE)")
+ @PreAuthorize("@authorizationService.canWrite(#parentDirectoryUuid)")
public ResponseEntity createCase(@PathVariable("caseName") String caseName,
@RequestPart("caseFile") MultipartFile caseFile,
@RequestParam("description") String description,
- @RequestParam(QUERY_PARAM_PARENT_DIRECTORY_ID) UUID parentDirectoryUuid,
- @RequestHeader(QUERY_PARAM_USER_ID) String userId) {
- exploreService.assertCanCreateCase(userId);
- exploreService.createCase(caseName, caseFile, description, userId, parentDirectoryUuid);
+ @RequestParam(QUERY_PARAM_PARENT_DIRECTORY_ID) UUID parentDirectoryUuid) {
+ exploreService.assertCanCreateCase();
+ exploreService.createCase(caseName, caseFile, description, parentDirectoryUuid);
return ResponseEntity.ok().build();
}
@PostMapping(value = "/explore/cases/{caseName}/persist", params = {"caseUuid", "description", QUERY_PARAM_PARENT_DIRECTORY_ID})
@Operation(summary = "persist an existing case")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Case persist request delegated to case server")})
- @PreAuthorize("@authorizationService.isAuthorized(#userId, #parentDirectoryUuid, null, T(org.gridsuite.explore.server.dto.PermissionType).WRITE)")
+ @PreAuthorize("@authorizationService.canWrite(#parentDirectoryUuid)")
public ResponseEntity persistCase(@PathVariable("caseName") String caseName,
@RequestParam("caseUuid") UUID caseUuid,
@RequestParam("description") String description,
- @RequestParam(QUERY_PARAM_PARENT_DIRECTORY_ID) UUID parentDirectoryUuid,
- @RequestHeader(QUERY_PARAM_USER_ID) String userId) {
- exploreService.assertCanCreateCase(userId);
- exploreService.persistCase(caseName, caseUuid, description, userId, parentDirectoryUuid);
+ @RequestParam(QUERY_PARAM_PARENT_DIRECTORY_ID) UUID parentDirectoryUuid) {
+ exploreService.assertCanCreateCase();
+ exploreService.persistCase(caseName, caseUuid, description, parentDirectoryUuid);
return ResponseEntity.ok().build();
}
@PostMapping(value = "/explore/cases/{id}/duplicate")
@Operation(summary = "Duplicate a case")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Case duplication request delegated to case server")})
- @PreAuthorize("@authorizationService.isAuthorizedForDuplication(#userId, #caseId, #targetDirectoryId)")
+ @PreAuthorize("@authorizationService.canDuplicateTo(#caseId, #targetDirectoryId)")
public ResponseEntity duplicateCase(
@PathVariable("id") UUID caseId,
- @RequestParam(name = QUERY_PARAM_PARENT_DIRECTORY_ID, required = false) UUID targetDirectoryId,
- @RequestHeader(QUERY_PARAM_USER_ID) String userId) {
- exploreService.assertCanCreateCase(userId);
- exploreService.duplicateCase(caseId, targetDirectoryId, userId);
+ @RequestParam(name = QUERY_PARAM_PARENT_DIRECTORY_ID, required = false) UUID targetDirectoryId) {
+ exploreService.assertCanCreateCase();
+ exploreService.duplicateCase(caseId, targetDirectoryId);
return ResponseEntity.ok().build();
}
@PostMapping(value = "/explore/contingency-lists/{id}/duplicate")
@Operation(summary = "Duplicate a contingency list")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Contingency list has been created")})
- @PreAuthorize("@authorizationService.isAuthorizedForDuplication(#userId, #contingencyListUuid, #targetDirectoryId)")
+ @PreAuthorize("@authorizationService.canDuplicateTo(#contingencyListUuid, #targetDirectoryId)")
public ResponseEntity duplicateContingencyList(
@PathVariable("id") UUID contingencyListUuid,
@RequestParam(name = QUERY_PARAM_TYPE) ContingencyListType contingencyListType,
- @RequestParam(name = QUERY_PARAM_PARENT_DIRECTORY_ID, required = false) UUID targetDirectoryId,
- @RequestHeader(QUERY_PARAM_USER_ID) String userId) {
- exploreService.duplicateContingencyList(contingencyListUuid, targetDirectoryId, userId, contingencyListType);
+ @RequestParam(name = QUERY_PARAM_PARENT_DIRECTORY_ID, required = false) UUID targetDirectoryId) {
+ exploreService.duplicateContingencyList(contingencyListUuid, targetDirectoryId, contingencyListType);
return ResponseEntity.ok().build();
}
@PostMapping(value = "/explore/identifier-contingency-lists/{listName}")
@Operation(summary = "create an identifier contingency list")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Identifier contingency list has been created")})
- @PreAuthorize("@authorizationService.isAuthorized(#userId, #parentDirectoryUuid, null, T(org.gridsuite.explore.server.dto.PermissionType).WRITE)")
+ @PreAuthorize("@authorizationService.canWrite(#parentDirectoryUuid)")
public ResponseEntity createIdentifierContingencyList(@PathVariable("listName") String listName,
@RequestBody(required = false) String content,
@RequestParam("description") String description,
- @RequestParam(QUERY_PARAM_PARENT_DIRECTORY_ID) UUID parentDirectoryUuid,
- @RequestHeader(QUERY_PARAM_USER_ID) String userId) {
- exploreService.createIdentifierContingencyList(listName, content, description, userId, parentDirectoryUuid);
+ @RequestParam(QUERY_PARAM_PARENT_DIRECTORY_ID) UUID parentDirectoryUuid) {
+ exploreService.createIdentifierContingencyList(listName, content, description, parentDirectoryUuid);
return ResponseEntity.ok().build();
}
@PostMapping(value = "/explore/filters-contingency-lists/{listName}")
@Operation(summary = "create a filter based contingency list")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Filter based contingency list has been created")})
- @PreAuthorize("@authorizationService.isAuthorized(#userId, #parentDirectoryUuid, null, T(org.gridsuite.explore.server.dto.PermissionType).WRITE)")
+ @PreAuthorize("@authorizationService.canWrite(#parentDirectoryUuid)")
public ResponseEntity createFilterBasedContingencyList(@PathVariable("listName") String listName,
@RequestBody(required = false) String content,
@RequestParam("description") String description,
- @RequestParam(QUERY_PARAM_PARENT_DIRECTORY_ID) UUID parentDirectoryUuid,
- @RequestHeader(QUERY_PARAM_USER_ID) String userId) {
- exploreService.createFilterBasedContingencyList(listName, content, description, userId, parentDirectoryUuid);
+ @RequestParam(QUERY_PARAM_PARENT_DIRECTORY_ID) UUID parentDirectoryUuid) {
+ exploreService.createFilterBasedContingencyList(listName, content, description, parentDirectoryUuid);
return ResponseEntity.ok().build();
}
@PostMapping(value = "/explore/filters", consumes = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "create a filter")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "Filter creation request delegated to filter server")})
- @PreAuthorize("@authorizationService.isAuthorized(#userId, #parentDirectoryUuid, null, T(org.gridsuite.explore.server.dto.PermissionType).WRITE)")
+ @PreAuthorize("@authorizationService.canWrite(#parentDirectoryUuid)")
public ResponseEntity createFilter(@RequestBody String filter,
@RequestParam("name") String filterName,
@RequestParam("description") String description,
- @RequestParam(QUERY_PARAM_PARENT_DIRECTORY_ID) UUID parentDirectoryUuid,
- @RequestHeader(QUERY_PARAM_USER_ID) String userId) {
- exploreService.createFilter(filter, filterName, description, parentDirectoryUuid, userId);
+ @RequestParam(QUERY_PARAM_PARENT_DIRECTORY_ID) UUID parentDirectoryUuid) {
+ exploreService.createFilter(filter, filterName, description, parentDirectoryUuid);
return ResponseEntity.ok().build();
}
@PostMapping(value = "/explore/filters/{id}/duplicate")
@Operation(summary = "Duplicate a filter")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The script has been created successfully")})
- @PreAuthorize("@authorizationService.isAuthorizedForDuplication(#userId, #filterId, #targetDirectoryId)")
+ @PreAuthorize("@authorizationService.canDuplicateTo(#filterId, #targetDirectoryId)")
public ResponseEntity duplicateFilter(
@PathVariable("id") UUID filterId,
- @RequestParam(name = QUERY_PARAM_PARENT_DIRECTORY_ID, required = false) UUID targetDirectoryId,
- @RequestHeader(QUERY_PARAM_USER_ID) String userId) {
- exploreService.duplicateFilter(filterId, targetDirectoryId, userId);
+ @RequestParam(name = QUERY_PARAM_PARENT_DIRECTORY_ID, required = false) UUID targetDirectoryId) {
+ exploreService.duplicateFilter(filterId, targetDirectoryId);
return ResponseEntity.ok().build();
}
+ // TODO: les deux endpoints suivants sont redondants ??? p-e moyen de refacto ?
+
@DeleteMapping(value = "/explore/elements/{elementUuid}")
@Operation(summary = "Remove directory/element")
@ApiResponses(value = {
@@ -198,38 +190,41 @@ public ResponseEntity duplicateFilter(
@ApiResponse(responseCode = "404", description = "Directory/element was not found"),
@ApiResponse(responseCode = "403", description = "Access forbidden for the directory/element")
})
- @PreAuthorize("@authorizationService.isRecursivelyAuthorized(#userId, #elementUuid, null)")
- public ResponseEntity deleteElement(@PathVariable("elementUuid") UUID elementUuid,
- @RequestHeader(QUERY_PARAM_USER_ID) String userId) {
- exploreService.deleteElement(elementUuid, userId);
+ @PreAuthorize("@authorizationService.canDelete(#elementUuid)")
+ public ResponseEntity deleteElement(@PathVariable("elementUuid") UUID elementUuid) {
+ exploreService.deleteElement(elementUuid);
return ResponseEntity.ok().build();
}
@DeleteMapping(value = "/explore/elements/{directoryUuid}", params = "ids")
+ // dans les ids, ça ne peut pas contenir de subDirectories, car ils n'apparaissent que dans l'arbre
@Operation(summary = "Remove directories/elements")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "directories/elements was successfully removed"),
@ApiResponse(responseCode = "404", description = "At least one directory/element was not found"),
@ApiResponse(responseCode = "403", description = "Access forbidden for at least one directory/element")
})
- @PreAuthorize("@authorizationService.isAuthorized(#userId, #directoryUuid, null, T(org.gridsuite.explore.server.dto.PermissionType).WRITE)")
- public ResponseEntity deleteElements(@RequestParam("ids") List elementsUuid,
- @RequestHeader(QUERY_PARAM_USER_ID) String userId,
+ @PreAuthorize("@authorizationService.canDelete(#elementsUuids)") // ça ne peut pas contenir de subDirectories, car ils n'apparaissent que dans l'arbre
+ public ResponseEntity deleteElements(@RequestParam("ids") List elementsUuids,
@PathVariable UUID directoryUuid) {
- exploreService.deleteElementsFromDirectory(elementsUuid, directoryUuid, userId);
+ exploreService.deleteElementsFromDirectory(elementsUuids, directoryUuid);
return ResponseEntity.ok().build();
}
+ // TODO : l'endpoint getElements dans directory-server filtre les éléments sur lesquels on n'a pas les droits si strictMode = false, et renvoie une erreur si strictMode = true
+ // ici on a strictMode = true (peut être que c'est à revoir ?) -> @PreFilter à tester ?
@GetMapping(value = "/explore/elements/metadata", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "get element infos from ids given as parameters")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The elements information")})
+ @PreAuthorize("@authorizationService.canRead(#ids)") // TODO: strictMode => @PreAuthorize, non strictMode => @PreFilter
public ResponseEntity> getElementsMetadata(@RequestParam("ids") List ids,
@RequestParam(value = "equipmentTypes", required = false) List equipmentTypes,
- @RequestParam(value = "elementTypes", required = false) List elementTypes,
- @RequestHeader(QUERY_PARAM_USER_ID) String userId) {
- return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(directoryService.getElementsMetadata(ids, elementTypes, equipmentTypes, userId));
+ @RequestParam(value = "elementTypes", required = false) List elementTypes) {
+ return ResponseEntity.ok().contentType(MediaType.APPLICATION_JSON).body(directoryService.getElementsMetadata(ids, elementTypes, equipmentTypes));
}
+ // TODO: ici je pense qu'on n'a pas besoin de permission ? ou alors READ ?
+ // actuellement on ne regarde pas si on a les droits (même dans l'endpoint de directory-server), on renvoie tout. On peut faire un @PreFilter ?
@GetMapping(value = "/explore/elements/name", produces = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "get element names from ids given as parameters")
@ApiResponses(value = {@ApiResponse(responseCode = "200", description = "The elements names")})
@@ -237,6 +232,7 @@ public ResponseEntity