Skip to content

Commit

Permalink
feat: add maxAllowedCases on profiles
Browse files Browse the repository at this point in the history
Signed-off-by: Abdelsalem <abdelsalem.hedhili@rte-france.com>
  • Loading branch information
AbdelHedhili committed Jun 11, 2024
1 parent e94f5a2 commit 7dcca35
Show file tree
Hide file tree
Showing 13 changed files with 79 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import static org.gridsuite.useradmin.server.UserAdminException.Type.FORBIDDEN;
import static org.gridsuite.useradmin.server.UserAdminException.Type.NOT_FOUND;
import static org.gridsuite.useradmin.server.UserAdminException.Type.*;

/**
* @author Etienne Homer <etienne.homer at rte-france.com>
Expand All @@ -27,6 +26,8 @@ protected ResponseEntity<Object> handleException(RuntimeException exception) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(userAdminException.getType());
} else if (userAdminException.getType().equals(NOT_FOUND)) {
return ResponseEntity.status(HttpStatus.NOT_FOUND).body(userAdminException.getType());
} else if (userAdminException.getType().equals(BAD_REQUEST)) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(userAdminException.getMessage());
}
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
public class UserAdminException extends RuntimeException {
public enum Type {
FORBIDDEN,
NOT_FOUND
NOT_FOUND,
BAD_REQUEST,
}

private final Type type;
Expand All @@ -24,6 +25,11 @@ public UserAdminException(Type type) {
this.type = type;
}

public UserAdminException(Type type, String message) {
super(message);
this.type = type;
}

Type getType() {
return type;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ public ResponseEntity<UserProfile> getUserProfile(@PathVariable("sub") String su
return ResponseEntity.of(service.getUserProfile(sub));
}

@GetMapping(value = "/users/{sub}/profile/max-cases")
@Operation(summary = "Get the user's profile")
@ApiResponse(responseCode = "200", description = "The user max allowed cases created")
@ApiResponse(responseCode = "404", description = "The user doesn't exist")
public ResponseEntity<Integer> getUserProfileMaxStudies(@PathVariable("sub") String sub) {
return ResponseEntity.ok().body(service.getUserProfileMaxAllowedCases(sub));
}

@GetMapping(value = "/connections", produces = {MediaType.APPLICATION_JSON_VALUE})
@Operation(summary = "get the connections", description = "Access restricted to users of type: `admin`")
@ApiResponse(responseCode = "200", description = "The connections list")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public ResponseEntity<UserProfile> updateProfile(@PathVariable("profileUuid") UU
@ApiResponse(responseCode = "201", description = "The profile has been created")
public ResponseEntity<Void> createProfile(@RequestHeader("userId") String userId,
@RequestBody UserProfile userProfile) {
service.createProfile(userProfile.name(), userId);
service.createProfile(userProfile, userId);
return ResponseEntity.status(HttpStatus.CREATED).build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ public record UserProfile(
UUID id,
String name,
UUID loadFlowParameterId,
Boolean allParametersLinksValid
Boolean allParametersLinksValid,
Integer maxAllowedCases
) { }
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@
@Table(name = "user_profile")
public class UserProfileEntity {

public UserProfileEntity(String name) {
this(UUID.randomUUID(), name, null);
}

@Id
@Column(name = "id")
private UUID id;
Expand All @@ -38,5 +34,8 @@ public UserProfileEntity(String name) {

@Column(name = "loadFlowParameterId")
private UUID loadFlowParameterId;

@Column(name = "maxAllowedCases")
private Integer maxAllowedCases;
}

Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.gridsuite.useradmin.server.repository.UserInfosRepository;
import org.gridsuite.useradmin.server.entity.UserInfosEntity;
import org.gridsuite.useradmin.server.repository.UserProfileRepository;
import org.springframework.context.annotation.Lazy;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand All @@ -37,19 +38,22 @@ public class UserAdminService {
private final NotificationService notificationService;
private final AdminRightService adminRightService;
private final UserProfileService userProfileService;
private final UserAdminService self;

public UserAdminService(final UserInfosRepository userInfosRepository,
final UserProfileRepository userProfileRepository,
final ConnectionsService connectionsService,
final AdminRightService adminRightService,
final NotificationService notificationService,
final UserProfileService userProfileService) {
final UserProfileService userProfileService,
@Lazy final UserAdminService userAdminService) {
this.userInfosRepository = Objects.requireNonNull(userInfosRepository);
this.userProfileRepository = Objects.requireNonNull(userProfileRepository);
this.connectionsService = Objects.requireNonNull(connectionsService);
this.adminRightService = Objects.requireNonNull(adminRightService);
this.notificationService = Objects.requireNonNull(notificationService);
this.userProfileService = Objects.requireNonNull(userProfileService);
this.self = Objects.requireNonNull(userAdminService);
}

private UserInfos toDtoUserInfo(final UserInfosEntity entity) {
Expand Down Expand Up @@ -118,6 +122,12 @@ public Optional<UserProfile> getUserProfile(String sub) {
return user.getProfile() == null ? Optional.empty() : userProfileService.getProfile(user.getProfile().getId());
}

@Transactional(readOnly = true)
public Integer getUserProfileMaxAllowedCases(String sub) {
UserProfile userProfile = self.getUserProfile(sub).orElse(null);
return userProfile == null ? null : userProfile.maxAllowedCases();
}

@Transactional(readOnly = true)
public boolean userIsAdmin(@NonNull String userId) {
return adminRightService.isAdmin(userId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.function.Consumer;
import java.util.stream.Collectors;

import static org.gridsuite.useradmin.server.UserAdminException.Type.BAD_REQUEST;
import static org.gridsuite.useradmin.server.UserAdminException.Type.NOT_FOUND;

/**
Expand Down Expand Up @@ -91,12 +92,17 @@ public void updateProfile(UUID profileUuid, String userId, UserProfile userProfi
UserProfileEntity profile = userProfileRepository.findById(profileUuid).orElseThrow(() -> new UserAdminException(NOT_FOUND));
profile.setName(userProfile.name());
profile.setLoadFlowParameterId(userProfile.loadFlowParameterId());
profile.setMaxAllowedCases(userProfile.maxAllowedCases());
}

@Transactional
public void createProfile(String profileName, String userId) {
public void createProfile(UserProfile userProfile, String userId) {
adminRightService.assertIsAdmin(userId);
userProfileRepository.save(new UserProfileEntity(profileName));
UserProfileEntity userProfileEntity = toEntity(userProfile);
if (userProfileEntity == null) {
throw new UserAdminException(BAD_REQUEST, "Invalid user profile");
}
userProfileRepository.save(userProfileEntity);
}

@Transactional
Expand All @@ -117,6 +123,13 @@ private UserProfile toDto(final UserProfileEntity entity, Boolean allParametersL
if (entity == null) {
return null;
}
return new UserProfile(entity.getId(), entity.getName(), entity.getLoadFlowParameterId(), allParametersLinksValid);
return new UserProfile(entity.getId(), entity.getName(), entity.getLoadFlowParameterId(), allParametersLinksValid, entity.getMaxAllowedCases());
}

private UserProfileEntity toEntity(final UserProfile userProfile) {
if (userProfile == null) {
return null;
}
return new UserProfileEntity(UUID.randomUUID(), userProfile.name(), userProfile.loadFlowParameterId(), userProfile.maxAllowedCases());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" xmlns:pro="http://www.liquibase.org/xml/ns/pro" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd">
<changeSet author="hedhiliabd (generated)" id="1718107503096-3">
<addColumn tableName="user_profile">
<column name="max_allowed_cases" type="integer"/>
</addColumn>
</changeSet>
</databaseChangeLog>
5 changes: 4 additions & 1 deletion src/main/resources/db/changelog/db.changelog-master.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ databaseChangeLog:
relativeToChangelogFile: true
- include:
file: changesets/changelog_20240326T150422Z.xml
relativeToChangelogFile: true
relativeToChangelogFile: true
- include:
file: changesets/changelog_20240611T120441Z.xml
relativeToChangelogFile: true
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ void testConversionToDtoOfUserInfos() {
.as("dto result")
.isEqualTo(new UserInfos("sub_user", true, null));
// with profile
UserProfileEntity profile = new UserProfileEntity("a profile");
UserProfileEntity profile = new UserProfileEntity(UUID.randomUUID(), "a profile", null, null);
assertThat(UserInfosEntity.toDto(new UserInfosEntity(uuid, "sub_user", profile), sub -> true))
.as("dto result")
.isEqualTo(new UserInfos("sub_user", true, "a profile"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,7 @@ private void createUser(String userName) {
@SneakyThrows
private void createProfile(String profileName) {
ObjectWriter objectWriter = objectMapper.writer().withDefaultPrettyPrinter();
UserProfile profileInfo = new UserProfile(null, profileName, null, false);
UserProfile profileInfo = new UserProfile(null, profileName, null, false, null);
mockMvc.perform(post("/" + UserAdminApi.API_VERSION + "/profiles")
.content(objectWriter.writeValueAsString(profileInfo))
.contentType(MediaType.APPLICATION_JSON)
Expand Down
24 changes: 14 additions & 10 deletions src/test/java/org/gridsuite/useradmin/server/UserProfileTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -113,25 +113,26 @@ public void testEmptyProfileList() {
@Test
@SneakyThrows
public void testCreateProfile() {
createProfile(PROFILE_1, ADMIN_USER, HttpStatus.CREATED);
createProfile(PROFILE_1, ADMIN_USER, 10, HttpStatus.CREATED);

List<UserProfile> userProfiles = getProfileList();
assertEquals(1, userProfiles.size());
assertEquals(PROFILE_1, userProfiles.get(0).name());
assertNull(userProfiles.get(0).loadFlowParameterId());
assertNull(userProfiles.get(0).allParametersLinksValid());
assertEquals(10, userProfiles.get(0).maxAllowedCases());
}

@Test
@SneakyThrows
public void testCreateProfileForbidden() {
createProfile(PROFILE_1, NOT_ADMIN, HttpStatus.FORBIDDEN);
createProfile(PROFILE_1, NOT_ADMIN, 1, HttpStatus.FORBIDDEN);
}

@Test
@SneakyThrows
public void testDeleteExistingProfile() {
createProfile(PROFILE_1, ADMIN_USER, HttpStatus.CREATED);
createProfile(PROFILE_1, ADMIN_USER, null, HttpStatus.CREATED);
assertEquals(1, getProfileList().size());
removeProfile(PROFILE_1, ADMIN_USER, HttpStatus.NO_CONTENT);
assertEquals(0, getProfileList().size());
Expand All @@ -152,13 +153,13 @@ public void testDeleteProfileNotFound() {
@Test
@SneakyThrows
public void testProfileUpdateNotFound() {
updateProfile(new UserProfile(UUID.randomUUID(), PROFILE_2, null, null), ADMIN_USER, HttpStatus.NOT_FOUND);
updateProfile(new UserProfile(UUID.randomUUID(), PROFILE_2, null, null, null), ADMIN_USER, HttpStatus.NOT_FOUND);
}

@Test
@SneakyThrows
public void testProfileUpdateForbidden() {
updateProfile(new UserProfile(UUID.randomUUID(), PROFILE_2, null, null), NOT_ADMIN, HttpStatus.FORBIDDEN);
updateProfile(new UserProfile(UUID.randomUUID(), PROFILE_2, null, null, null), NOT_ADMIN, HttpStatus.FORBIDDEN);
}

@Test
Expand All @@ -184,10 +185,10 @@ private void updateProfile(boolean validParameters) {
.withBody(objectMapper.writeValueAsString(existingElements))
.withHeader("Content-Type", "application/json"))).getId();

UUID profileUuid = createProfile(PROFILE_1, ADMIN_USER, HttpStatus.CREATED);
UUID profileUuid = createProfile(PROFILE_1, ADMIN_USER, null, HttpStatus.CREATED);

// udpate the profile: change name and set its LF parameters
UserProfile userProfile = new UserProfile(profileUuid, PROFILE_2, lfParametersUuid, null);
// udpate the profile: change name and set its LF parameters and maxAllowedCases
UserProfile userProfile = new UserProfile(profileUuid, PROFILE_2, lfParametersUuid, null, 10);
updateProfile(userProfile, ADMIN_USER, HttpStatus.OK);

// profiles list (with validity flag)
Expand All @@ -196,15 +197,16 @@ private void updateProfile(boolean validParameters) {
assertEquals(1, userProfiles.size());
assertEquals(lfParametersUuid, userProfiles.get(0).loadFlowParameterId());
assertEquals(validParameters, userProfiles.get(0).allParametersLinksValid());
assertEquals(10, userProfiles.get(0).maxAllowedCases());
}

private Map<String, StringValuePattern> handleQueryParams(List<UUID> paramIds) {
return Map.of("ids", WireMock.matching(paramIds.stream().map(uuid -> ".+").collect(Collectors.joining(","))));
}

@SneakyThrows
private UUID createProfile(String profileName, String userName, HttpStatusCode status) {
UserProfile profileInfo = new UserProfile(null, profileName, null, false);
private UUID createProfile(String profileName, String userName, Integer maxAllowedCases, HttpStatusCode status) {
UserProfile profileInfo = new UserProfile(null, profileName, null, false, maxAllowedCases);
mockMvc.perform(post("/" + UserAdminApi.API_VERSION + "/profiles")
.content(objectWriter.writeValueAsString(profileInfo))
.contentType(MediaType.APPLICATION_JSON)
Expand All @@ -216,6 +218,7 @@ private UUID createProfile(String profileName, String userName, HttpStatusCode s
// check repository
Optional<UserProfileEntity> profile1 = userProfileRepository.findByName(profileName);
assertTrue(profile1.isPresent());
assertEquals(maxAllowedCases, profile1.get().getMaxAllowedCases());
assertNull(profile1.get().getLoadFlowParameterId()); // no LF params by dft
return profile1.get().getId();
}
Expand Down Expand Up @@ -266,6 +269,7 @@ private void updateProfile(UserProfile newData, String userName, HttpStatusCode
assertNotNull(updatedProfile);
assertEquals(newData.name(), updatedProfile.name());
assertEquals(newData.loadFlowParameterId(), updatedProfile.loadFlowParameterId());
assertEquals(newData.maxAllowedCases(), updatedProfile.maxAllowedCases());
assertNull(updatedProfile.allParametersLinksValid()); // validity not set in this case
}
}
Expand Down

0 comments on commit 7dcca35

Please sign in to comment.