Skip to content

Commit a7ad4a9

Browse files
Merge pull request #258 from InseeFr/devBackOfficeUserAuth
Back office role
2 parents e707731 + e4859f9 commit a7ad4a9

File tree

8 files changed

+72
-7
lines changed

8 files changed

+72
-7
lines changed

src/main/java/fr/insee/genesis/configuration/auth/security/ApplicationRole.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ public enum ApplicationRole {
77
COLLECT_PLATFORM,
88
SCHEDULER,
99
READER,
10+
USER_BACK_OFFICE,
1011
USER_BATCH_GENERIC
1112
}
1213

src/main/java/fr/insee/genesis/configuration/auth/security/RoleConfiguration.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ public class RoleConfiguration {
3131
@Value("#{'${app.role.collect-platform.claims}'.split(',')}")
3232
private List<String> collectPlatformClaims;
3333

34+
@Value("#{'${app.role.user-back-office.claims}'.split(',')}")
35+
private List<String> userBackOfficeClaims;
36+
3437
@Value("#{'${app.role.scheduler.claims}'.split(',')}")
3538
private List<String> schedulerClaims;
3639

@@ -54,11 +57,13 @@ static RoleHierarchy roleHierarchy() {
5457
return RoleHierarchyImpl.withDefaultRolePrefix()
5558
.role(ApplicationRole.ADMIN.toString()).implies(ApplicationRole.USER_KRAFTWERK.toString())
5659
.role(ApplicationRole.ADMIN.toString()).implies(ApplicationRole.USER_PLATINE.toString())
60+
.role(ApplicationRole.ADMIN.toString()).implies(ApplicationRole.USER_BACK_OFFICE.toString())
5761
.role(ApplicationRole.ADMIN.toString()).implies(ApplicationRole.COLLECT_PLATFORM.toString())
5862
.role(ApplicationRole.ADMIN.toString()).implies(ApplicationRole.SCHEDULER.toString())
5963
.role(ApplicationRole.ADMIN.toString()).implies(ApplicationRole.USER_BATCH_GENERIC.toString())
6064
.role(ApplicationRole.USER_KRAFTWERK.toString()).implies(ApplicationRole.READER.toString())
6165
.role(ApplicationRole.USER_PLATINE.toString()).implies(ApplicationRole.READER.toString())
66+
.role(ApplicationRole.USER_BACK_OFFICE.toString()).implies(ApplicationRole.READER.toString())
6267
.build();
6368
}
6469

@@ -90,6 +95,11 @@ public void initialization() {
9095
.computeIfAbsent(claim, k -> new ArrayList<>())
9196
.add(String.valueOf(ApplicationRole.USER_PLATINE)));
9297

98+
// Ajout des claims pour le rôle USER_BACK_OFFICE
99+
userBackOfficeClaims.forEach(claim -> rolesByClaim
100+
.computeIfAbsent(claim, k -> new ArrayList<>())
101+
.add(String.valueOf(ApplicationRole.USER_BACK_OFFICE)));
102+
93103
// Add claims for the COLLECT_PLATFORM role
94104
collectPlatformClaims.forEach(claim -> rolesByClaim
95105
.computeIfAbsent(claim, k -> new ArrayList<>())
@@ -112,5 +122,4 @@ public void initialization() {
112122

113123
log.info("Roles configuration : {}", rolesByClaim);
114124
}
115-
116125
}

src/main/java/fr/insee/genesis/controller/rest/DataProcessingContextController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public class DataProcessingContextController {
4646

4747
@Operation(summary = "Create or update a data processing context")
4848
@PutMapping(path = "/review")
49-
@PreAuthorize("hasRole('ADMIN')")
49+
@PreAuthorize("hasRole('USER_BACK_OFFICE')")
5050
public ResponseEntity<Object> saveContext(
5151
@Parameter(description = "Identifier of the partition", required = true) @RequestParam("partitionId") String partitionId,
5252
@Parameter(description = "Allow reviewing") @RequestParam(value = "withReview", defaultValue = "false") Boolean withReview

src/main/java/fr/insee/genesis/controller/rest/LunaticModelController.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ public LunaticModelController(LunaticModelApiPort lunaticModelApiPort) {
3131

3232
@Operation(summary = "Save lunatic json data from one interrogation in Genesis Database")
3333
@PutMapping(path = "/save")
34-
@PreAuthorize("hasRole('ADMIN')")
34+
@PreAuthorize("hasRole('USER_BACK_OFFICE')")
3535
public ResponseEntity<String> saveRawResponsesFromJsonBody(
3636
@RequestParam("questionnaireId") String questionnaireId,
3737
@RequestBody Map<String, Object> dataJson

src/main/java/fr/insee/genesis/controller/rest/responses/EditedResponseController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public ResponseEntity<Object> getEditedResponses(
5050

5151
@Operation(summary = "Add edited previous json file")
5252
@PostMapping(path = "previous/json")
53-
@PreAuthorize("hasAnyRole('USER_PLATINE','SCHEDULER')")
53+
@PreAuthorize("hasAnyRole('USER_PLATINE','SCHEDULER','USER_BACK_OFFICE')")
5454
public ResponseEntity<Object> readEditedPreviousJson(
5555
@RequestParam("questionnaireId") String questionnaireId,
5656
@RequestParam("mode") Mode mode,
@@ -77,7 +77,7 @@ public ResponseEntity<Object> readEditedPreviousJson(
7777

7878
@Operation(summary = "Add edited external json file")
7979
@PostMapping(path = "/external/json")
80-
@PreAuthorize("hasAnyRole('USER_PLATINE','SCHEDULER')")
80+
@PreAuthorize("hasAnyRole('USER_PLATINE','SCHEDULER','USER_BACK_OFFICE')")
8181
public ResponseEntity<Object> readEditedExternalJson(
8282
@RequestParam("questionnaireId") String questionnaireId,
8383
@RequestParam("mode") Mode mode,

src/main/resources/application-test-cucumber.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ fr.insee.genesis.sourcefolder.specifications = /data/genesis
55
app.role.admin.claims=administrateur_traiter
66
app.role.user-kraftwerk.claims=utilisateur_Kraftwerk
77
app.role.user-platine.claims=utilisateur_Platine
8+
app.role.user-back-office.claims=utilisateur_Back_Office
89
app.role.reader.claims=lecteur_traiter
910
app.role.collect-platform.claims=protools
1011
app.role.scheduler.claims=scheduler_traiter

src/main/resources/application-test.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ fr.insee.genesis.sourcefolder.specifications = /data/genesis
55
app.role.admin.claims=administrateur_traiter
66
app.role.user-kraftwerk.claims=utilisateur_Kraftwerk
77
app.role.user-platine.claims=utilisateur_Platine
8+
app.role.user-back-office.claims=utilisateur_Back_Office
89
app.role.reader.claims=lecteur_traiter
910
app.role.collect-platform.claims=protools
1011
app.role.scheduler.claims=scheduler_traiter

src/test/java/fr/insee/genesis/controller/rest/ControllerAccessTest.java

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,14 @@
1111
import fr.insee.genesis.infrastructure.repository.RundeckExecutionDBRepository;
1212
import fr.insee.genesis.infrastructure.repository.SurveyUnitMongoDBRepository;
1313
import fr.insee.genesis.infrastructure.repository.VariableTypeMongoDBRepository;
14+
import org.junit.jupiter.api.Assertions;
1415
import org.junit.jupiter.api.DisplayName;
1516
import org.junit.jupiter.api.Test;
1617
import org.junit.jupiter.params.ParameterizedTest;
1718
import org.junit.jupiter.params.provider.Arguments;
1819
import org.junit.jupiter.params.provider.MethodSource;
1920
import org.springframework.beans.factory.annotation.Autowired;
21+
import org.springframework.beans.factory.annotation.Value;
2022
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
2123
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
2224
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
@@ -30,13 +32,15 @@
3032
import org.springframework.test.web.servlet.MockMvc;
3133
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
3234

35+
import java.util.HashMap;
3336
import java.util.stream.Stream;
3437

3538
import static org.hamcrest.Matchers.oneOf;
3639
import static org.mockito.ArgumentMatchers.anyString;
3740
import static org.mockito.Mockito.doNothing;
3841
import static org.springframework.http.HttpMethod.GET;
3942
import static org.springframework.http.HttpMethod.POST;
43+
import static org.springframework.http.HttpMethod.PUT;
4044
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.jwt;
4145
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
4246
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
@@ -51,6 +55,12 @@
5155
@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class})
5256
class ControllerAccessTest {
5357

58+
// Constants for user roles
59+
// JWT claim properties loaded from application properties
60+
@Value("${fr.insee.genesis.security.token.oidc-claim-role}")
61+
private String claimRoleDotRoles;
62+
@Value("${fr.insee.genesis.security.token.oidc-claim-username}")
63+
private String claimName;
5464
@Autowired
5565
private MockMvc mockMvc; // Simulates HTTP requests to the REST endpoints
5666

@@ -108,6 +118,15 @@ private static Stream<Arguments> responseEndpoint() {
108118
);
109119
}
110120

121+
private static Stream<Arguments> backOfficeEndpointProd() {
122+
return Stream.of(
123+
Arguments.of(PUT,"/lunatic-model/save?questionnaireId=TEST", new HashMap<>()),
124+
Arguments.of(POST,"/edited/previous/json?questionnaireId=TEST&mode=WEB&jsonFileName=truc.json"),
125+
Arguments.of(POST,"/edited/external/json?questionnaireId=TEST&mode=WEB&jsonFileName=truc.json"),
126+
Arguments.of(PUT,"/context/review?partitionId=TEST")
127+
);
128+
}
129+
111130
/**
112131
* Tests that users with the "ADMIN" role can access read-only endpoints.
113132
*/
@@ -150,6 +169,42 @@ void platine_users_should_access_reader_allowed_services(String endpointURI) thr
150169
.andExpect(status().is(oneOf(200,404)));
151170
}
152171

172+
/**
173+
* Tests that users with the "USER_BACK_OFFICE" role can access read-only endpoints.
174+
*/
175+
@ParameterizedTest
176+
@MethodSource("backOfficeEndpointProd")
177+
@DisplayName("Back office users should access prod services")
178+
void back_office_users_should_access_prod_services(HttpMethod method, String endpointURI) throws Exception {
179+
switch (method.name()){
180+
case "PUT" -> mockMvc.perform(
181+
put(endpointURI).with(
182+
jwt().authorities(new SimpleGrantedAuthority("ROLE_USER_BACK_OFFICE")))
183+
)
184+
.andExpect(status().is(oneOf(200,400,404)));
185+
case "POST" -> mockMvc.perform(
186+
post(endpointURI).with(
187+
jwt().authorities(new SimpleGrantedAuthority("ROLE_USER_BACK_OFFICE")))
188+
)
189+
.andExpect(status().is(oneOf(200,400,404)));
190+
default -> Assertions.fail("Method %s not supported".formatted(method.name()));
191+
}
192+
}
193+
194+
/**
195+
* Tests that users with the "USER_BACK_OFFICE" role can access read-only endpoints.
196+
*/
197+
@ParameterizedTest
198+
@MethodSource("endpointsReader")
199+
@DisplayName("Back office users should access reader-allowed services")
200+
void back_office_users_should_access_reader_allowed_services(String endpointURI) throws Exception {
201+
mockMvc.perform(
202+
get(endpointURI).with(
203+
jwt().authorities(new SimpleGrantedAuthority("ROLE_USER_BACK_OFFICE")))
204+
)
205+
.andExpect(status().is(oneOf(200,400,404)));
206+
}
207+
153208
/**
154209
* Tests that users with the "READER" role can access read-only endpoints.
155210
*/
@@ -269,6 +324,4 @@ void invalid_roles_should_access_schedules_services() throws Exception {
269324
jwt().authorities(new SimpleGrantedAuthority("ROLE_invalid"))))
270325
.andExpect(status().isForbidden());
271326
}
272-
273-
274327
}

0 commit comments

Comments
 (0)