From 6927b65bf56adc90f8baf9600fc4f2851dfba599 Mon Sep 17 00:00:00 2001 From: Janik Endtner Date: Fri, 2 Feb 2024 10:49:41 +0100 Subject: [PATCH] #790 create backend methods to create users --- .../puzzle/okr/controller/UserController.java | 12 +++++++++ .../java/ch/puzzle/okr/mapper/UserMapper.java | 18 +++++++++++++ .../UserAuthorizationService.java | 10 +++++++- .../service/business/UserBusinessService.java | 8 ++++++ .../persistence/UserPersistenceService.java | 3 +++ .../UserAuthorizationServiceTest.java | 25 +++++++++++++++++++ 6 files changed, 75 insertions(+), 1 deletion(-) diff --git a/backend/src/main/java/ch/puzzle/okr/controller/UserController.java b/backend/src/main/java/ch/puzzle/okr/controller/UserController.java index 51893f3060..83ddfe3565 100644 --- a/backend/src/main/java/ch/puzzle/okr/controller/UserController.java +++ b/backend/src/main/java/ch/puzzle/okr/controller/UserController.java @@ -1,5 +1,6 @@ package ch.puzzle.okr.controller; +import ch.puzzle.okr.dto.NewUserDto; import ch.puzzle.okr.dto.UserDto; import ch.puzzle.okr.mapper.UserMapper; import ch.puzzle.okr.service.authorization.AuthorizationService; @@ -68,4 +69,15 @@ public UserDto setOkrChampion( return userMapper.toDto(user); } + @Operation(summary = "Create users", description = "Creates a user entity for every user in the method body") + @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Returned users", content = { + @Content(mediaType = "application/json", schema = @Schema(implementation = UserDto.class)) }), }) + @PostMapping(path = "/createall") + public List createUsers( + @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The Team as json to create a new Team.", required = true) @RequestBody List newUserDtoList + ) { + var createdUsers = this.userAuthorizationService.createUsers(userMapper.toUserList(newUserDtoList)); + return userMapper.toDtos(createdUsers); + } + } diff --git a/backend/src/main/java/ch/puzzle/okr/mapper/UserMapper.java b/backend/src/main/java/ch/puzzle/okr/mapper/UserMapper.java index ac68b62921..8d2f3c1892 100644 --- a/backend/src/main/java/ch/puzzle/okr/mapper/UserMapper.java +++ b/backend/src/main/java/ch/puzzle/okr/mapper/UserMapper.java @@ -1,10 +1,12 @@ package ch.puzzle.okr.mapper; +import ch.puzzle.okr.dto.NewUserDto; import ch.puzzle.okr.dto.UserDto; import ch.puzzle.okr.dto.UserTeamDto; import ch.puzzle.okr.models.User; import org.springframework.stereotype.Component; +import java.util.List; import java.util.stream.Collectors; @Component @@ -16,6 +18,10 @@ public UserMapper(TeamMapper teamMapper) { this.teamMapper = teamMapper; } + public List toDtos(List userList) { + return userList.stream().map(this::toDto).toList(); + } + public UserDto toDto(User user) { var userTeams = user.getUserTeamList().stream().map( ut -> new UserTeamDto(ut.getId(), user.getVersion(), teamMapper.toDto(ut.getTeam()), ut.isTeamAdmin())) @@ -24,4 +30,16 @@ public UserDto toDto(User user) { return new UserDto(user.getId(), user.getVersion(), user.getFirstname(), user.getLastname(), user.getEmail(), userTeams, user.isOkrChampion()); } + + public List toUserList(List newUserList) { + return newUserList.stream().map(this::toUser).toList(); + } + + public User toUser(NewUserDto newUserDto) { + var user = new User(); + user.setFirstname(newUserDto.firstname()); + user.setLastname(newUserDto.lastname()); + user.setEmail(newUserDto.email()); + return user; + } } diff --git a/backend/src/main/java/ch/puzzle/okr/service/authorization/UserAuthorizationService.java b/backend/src/main/java/ch/puzzle/okr/service/authorization/UserAuthorizationService.java index 0bfa5bf90d..1a262c7ebb 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/authorization/UserAuthorizationService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/authorization/UserAuthorizationService.java @@ -19,7 +19,7 @@ public class UserAuthorizationService { private final TeamAuthorizationService teamAuthorizationService; public UserAuthorizationService(UserBusinessService userBusinessService, AuthorizationService authorizationService, - TeamAuthorizationService teamAuthorizationService) { + TeamAuthorizationService teamAuthorizationService) { this.userBusinessService = userBusinessService; this.authorizationService = authorizationService; this.teamAuthorizationService = teamAuthorizationService; @@ -52,4 +52,12 @@ public User setIsOkrChampion(long id, boolean isOkrChampion) { OkrResponseStatusException.of(ErrorKey.NOT_AUTHORIZED_TO_WRITE, USER)); return userBusinessService.setIsOkrChampion(user, isOkrChampion); } + + public List createUsers(List userList) { + AuthorizationService.checkRoleWriteAndReadAll( + authorizationService.updateOrAddAuthorizationUser(), + OkrResponseStatusException.of(ErrorKey.NOT_AUTHORIZED_TO_WRITE, USER) + ); + return userBusinessService.createUsers(userList); + } } diff --git a/backend/src/main/java/ch/puzzle/okr/service/business/UserBusinessService.java b/backend/src/main/java/ch/puzzle/okr/service/business/UserBusinessService.java index 5c749f6386..6155e4fd0d 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/business/UserBusinessService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/business/UserBusinessService.java @@ -6,11 +6,13 @@ import ch.puzzle.okr.service.CacheService; import ch.puzzle.okr.service.persistence.UserPersistenceService; import ch.puzzle.okr.service.validation.UserValidationService; +import jakarta.transaction.Transactional; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import java.util.List; import java.util.Objects; +import java.util.stream.StreamSupport; @Service public class UserBusinessService { @@ -61,4 +63,10 @@ private void checkAtLeastOneOkrChampionExists(User user) { public User saveUser(User user) { return userPersistenceService.save(user); } + + @Transactional + public List createUsers(List userList) { + var userIter = userPersistenceService.saveAll(userList); + return StreamSupport.stream(userIter.spliterator(), false).toList(); + } } diff --git a/backend/src/main/java/ch/puzzle/okr/service/persistence/UserPersistenceService.java b/backend/src/main/java/ch/puzzle/okr/service/persistence/UserPersistenceService.java index 235cf666a3..2d465f4fea 100644 --- a/backend/src/main/java/ch/puzzle/okr/service/persistence/UserPersistenceService.java +++ b/backend/src/main/java/ch/puzzle/okr/service/persistence/UserPersistenceService.java @@ -39,4 +39,7 @@ public User save(User user) { public List findAllOkrChampions() { return getRepository().findByIsOkrChampion(true); } + public Iterable saveAll(List userList) { + return getRepository().saveAll(userList); + } } diff --git a/backend/src/test/java/ch/puzzle/okr/service/authorization/UserAuthorizationServiceTest.java b/backend/src/test/java/ch/puzzle/okr/service/authorization/UserAuthorizationServiceTest.java index 0e57fba9f8..cecbd45db2 100644 --- a/backend/src/test/java/ch/puzzle/okr/service/authorization/UserAuthorizationServiceTest.java +++ b/backend/src/test/java/ch/puzzle/okr/service/authorization/UserAuthorizationServiceTest.java @@ -81,4 +81,29 @@ void setOkrChampion_shouldThrowErrorIfLoggedInUserIsNotOkrChampion() { assertThrows(OkrResponseStatusException.class, () -> userAuthorizationService.setIsOkrChampion(user.getId(), true)); } + + @Test + void createUsers_shouldCallBusinessService() { + var loggedInUser = defaultUser(1L); + loggedInUser.setOkrChampion(true); + + List users = List.of(user, user2); + when(userBusinessService.createUsers(users)).thenReturn(users); + when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(new AuthorizationUser(loggedInUser)); + + userAuthorizationService.createUsers(users); + + verify(userBusinessService, times(1)).createUsers(users); + } + + @Test + void createUsers_shouldThrowErrorIfLoggedInUserIsNotOkrChampion() { + var loggedInUser = defaultUser(1L); + loggedInUser.setOkrChampion(false); + + when(authorizationService.updateOrAddAuthorizationUser()).thenReturn(new AuthorizationUser(loggedInUser)); + + assertThrows(OkrResponseStatusException.class, + () -> userAuthorizationService.createUsers(List.of(user, user2))); + } }