diff --git a/application-engine/pom.xml b/application-engine/pom.xml index 583df212b1a..ad18579fdeb 100644 --- a/application-engine/pom.xml +++ b/application-engine/pom.xml @@ -370,6 +370,12 @@ spring-boot-starter-data-elasticsearch + + + org.springframework.boot + spring-boot-starter-validation + + @@ -503,11 +509,6 @@ - - org.hibernate.validator - hibernate-validator - 6.2.3.Final - com.fasterxml.jackson jackson-base diff --git a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy index 1e686358e8a..649d6e37838 100644 --- a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy +++ b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy @@ -35,6 +35,7 @@ import com.netgrif.application.engine.menu.services.interfaces.DashboardManageme import com.netgrif.application.engine.menu.services.interfaces.IMenuItemService import com.netgrif.application.engine.objects.auth.domain.Group import com.netgrif.application.engine.objects.auth.domain.LoggedUser +import com.netgrif.application.engine.objects.auth.domain.QGroup import com.netgrif.application.engine.objects.petrinet.domain.I18nString import com.netgrif.application.engine.objects.petrinet.domain.PetriNet import com.netgrif.application.engine.objects.petrinet.domain.Transition @@ -99,6 +100,7 @@ import org.springframework.data.domain.Page import org.springframework.data.domain.PageRequest import org.springframework.data.domain.Pageable import com.netgrif.application.engine.objects.utils.Nullable +import org.springframework.data.util.Pair import java.time.ZoneId import java.util.stream.Collectors @@ -2874,4 +2876,61 @@ class ActionDelegate { IStorageService storageService = storageResolverService.resolve(storageField.storageType) return storageService.getPath(aCase.stringId, fileFieldId, fileName) } + + Group findGroupByIdentifier(String identifier) { + return groupService.findByIdentifier(identifier).orElse(null) + } + + Group findGroupById(String groupId) { + return groupService.findById(groupId) + } + + Page findGroups(Closure predicate = {it.identifier.isNotNull()}, Pageable pageable = Pageable.unpaged()) { + QGroup qGroup = new QGroup("group") + return groupService.findByPredicate(predicate(qGroup), pageable) + } + + Group createGroup(String identifier, String title = "", AbstractUser owner = userService.getLoggedOrSystem()) { + return groupService.create(identifier, title, owner) + } + + void deleteGroup(Group group) { + groupService.delete(group) + } + + Group saveGroup(Group group) { + return groupService.save(group) + } + + Group addUserToGroup(String groupId, String userId, String realmId) { + return groupService.addUser(groupId, userId, realmId) + } + + Group removeUserFromGroup(String groupId, String userId, String realmId) { + return groupService.removeUser(groupId, userId, realmId) + } + + Group addAuthorityToGroup(String groupId, String authorityId) { + return groupService.addAuthority(groupId, authorityId) + } + + Group removeAuthorityFromGroup(String groupId, String authorityId) { + return groupService.removeAuthority(groupId, authorityId) + } + + Group addRoleToGroup(String groupId, String roleId) { + return groupService.addRole(groupId, roleId) + } + + Group removeRoleFromGroup(String groupId, String roleId) { + return groupService.removeRole(groupId, roleId) + } + + Pair addSubGroup(String groupId, String subGroupId) { + return groupService.addSubgroup(groupId, subGroupId) + } + + Pair removeSubGroup(String groupId, String subGroupId) { + return groupService.removeSubgroup(groupId, subGroupId) + } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/auth/service/RegistrationService.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/service/RegistrationService.java index 1583db825fd..57dc2228b92 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/auth/service/RegistrationService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/auth/service/RegistrationService.java @@ -151,7 +151,7 @@ public AbstractUser createNewUser(NewUserRequest newUser) { if (newUser.groups != null && !newUser.groups.isEmpty()) { for (String group : newUser.groups) { - groupService.addUser(user, group); + groupService.addUser(group, user); } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/auth/service/UserResourceHelperService.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/service/UserResourceHelperService.java index de08201760a..884a448c1ad 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/auth/service/UserResourceHelperService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/auth/service/UserResourceHelperService.java @@ -1,9 +1,9 @@ package com.netgrif.application.engine.auth.service; +import com.netgrif.application.engine.auth.web.responsebodies.UserDto; import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.service.interfaces.IUserResourceHelperService; -import com.netgrif.application.engine.auth.web.responsebodies.User; import com.netgrif.application.engine.auth.web.responsebodies.UserResource; import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService; import lombok.extern.slf4j.Slf4j; @@ -32,20 +32,20 @@ public UserResource getResource(LoggedUser loggedUser, Locale locale, boolean sm // User result = loggedUser.isImpersonating() ? // getLocalisedUser(user, getImpersonated(loggedUser, small), locale) : // getLocalisedUser(user, locale); - User result = getLocalisedUser(user, locale); + UserDto result = getLocalisedUser(user, locale); return new UserResource(result, "profile"); } @Override - public User getLocalisedUser(AbstractUser user, AbstractUser impersonated, Locale locale) { - User localisedUser = getLocalisedUser(user, locale); - User impersonatedUser = userFactory.getUser(impersonated, locale); + public UserDto getLocalisedUser(AbstractUser user, AbstractUser impersonated, Locale locale) { + UserDto localisedUser = getLocalisedUser(user, locale); + UserDto impersonatedUser = userFactory.getUser(impersonated, locale); localisedUser.setImpersonated(impersonatedUser); return localisedUser; } @Override - public User getLocalisedUser(AbstractUser user, Locale locale) { + public UserDto getLocalisedUser(AbstractUser user, Locale locale) { return userFactory.getUser(user, locale); } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorizationService.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorizationService.java deleted file mode 100644 index 81feafc98d7..00000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorizationService.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.netgrif.application.engine.auth.service.interfaces; - -public interface IAuthorizationService { - boolean hasAuthority(String authority); -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserResourceHelperService.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserResourceHelperService.java index f82c5efe437..2ace8f75e66 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserResourceHelperService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserResourceHelperService.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.auth.service.interfaces; -import com.netgrif.application.engine.auth.web.responsebodies.User; +import com.netgrif.application.engine.auth.web.responsebodies.UserDto; import com.netgrif.application.engine.auth.web.responsebodies.UserResource; import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; @@ -10,7 +10,7 @@ public interface IUserResourceHelperService { UserResource getResource(LoggedUser loggedUser, Locale locale, boolean small); - User getLocalisedUser(AbstractUser user, AbstractUser impersonated, Locale locale); + UserDto getLocalisedUser(AbstractUser user, AbstractUser impersonated, Locale locale); - User getLocalisedUser(AbstractUser user, Locale locale); + UserDto getLocalisedUser(AbstractUser user, Locale locale); } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/auth/web/GroupController.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/GroupController.java new file mode 100644 index 00000000000..330c47835c4 --- /dev/null +++ b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/GroupController.java @@ -0,0 +1,461 @@ +package com.netgrif.application.engine.auth.web; + +import com.netgrif.application.engine.adapter.spring.common.web.responsebodies.ResponseMessage; +import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService; +import com.netgrif.application.engine.auth.service.GroupService; +import com.netgrif.application.engine.auth.service.RealmService; +import com.netgrif.application.engine.auth.service.UserFactory; +import com.netgrif.application.engine.auth.service.UserService; +import com.netgrif.application.engine.auth.web.responsebodies.UserDto; +import com.netgrif.application.engine.objects.auth.domain.Group; +import com.netgrif.application.engine.objects.auth.domain.AbstractUser; +import com.netgrif.application.engine.objects.auth.domain.Realm; +import com.netgrif.application.engine.objects.dto.request.group.CreateGroupRequestDto; +import com.netgrif.application.engine.objects.dto.request.group.GroupSearchRequestDto; +import com.netgrif.application.engine.objects.dto.request.group.UpdateGroupRequestDto; +import com.netgrif.application.engine.objects.dto.response.group.GroupDto; +import com.netgrif.application.engine.objects.workflow.domain.ProcessResourceId; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +import java.util.*; +import java.util.stream.Collectors; + +@Slf4j +@RestController +@RequestMapping("api/groups") +@ConditionalOnProperty( + value = "netgrif.engine.group.web.enabled", + havingValue = "true", + matchIfMissing = true +) +@Tag(name = "Group") +@RequiredArgsConstructor +public class GroupController { + + private final GroupService groupService; + private final UserService userService; + private final ProcessRoleService processRoleService; + private final RealmService realmService; + private final UserFactory userFactory; + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Get page of groups from defined realm", + description = "Caller must have the ADMIN role", + security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Retrieve page of groups from defined realm"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping(path = "/{realmId}/all", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> getAllGroupsOfRealm(@PathVariable("realmId") String realmId, Pageable pageable, Locale locale) { + Page groups = groupService.findAllFromRealm(realmId, pageable); + return ResponseEntity.ok(transformPageContent(groups.getContent(), pageable, locale)); + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Create new group", + description = "Caller must have the ADMIN role", + security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "201", description = "New group created successfully"), + @ApiResponse(responseCode = "400", description = "Request data invalid"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PostMapping(produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity createGroup(@Valid @RequestBody CreateGroupRequestDto request) { + if (request == null) { + return ResponseEntity.badRequest().build(); + } + if (!realmExists(request.realmId())) { + String message = "Cannot create group, realm with id [" + request.realmId() + "] does not exist"; + log.error(message); + return ResponseEntity.badRequest().build(); + } + AbstractUser user = userService.findById(request.ownerId(), null); + if (user == null) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ResponseMessage.createErrorMessage("User with id [%s] not found".formatted(request.ownerId()))); + } + try { + groupService.create(request.identifier(), request.displayName(), user); + return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Group created successfully")); + } catch (IllegalArgumentException e) { + return ResponseEntity.badRequest().body(ResponseMessage.createErrorMessage(e.getMessage())); + } catch (Exception e) { + return ResponseEntity.internalServerError().body(ResponseMessage.createErrorMessage("Failed to create group with identifier [%s]".formatted(request.identifier()))); + } + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Delete group defined by id", + description = "Caller must have the ADMIN role", + security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "New group deleted successfully"), + @ApiResponse(responseCode = "400", description = "Request data invalid"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @DeleteMapping("/{id}") + public ResponseEntity deleteGroup(@PathVariable("id") String groupId) { + try { + Group group = groupService.findById(groupId); + groupService.delete(group); + return ResponseEntity.ok("Group with id [" + groupId + "] deleted successfully"); + } catch (IllegalArgumentException e) { + String message = "Failed to delete group with id [" + groupId + "]"; + log.error(message, e); + return ResponseEntity.badRequest().body(message); + } + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Get group by id", + description = "Caller must have the ADMIN role", + security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Group retrieved successfully"), + @ApiResponse(responseCode = "400", description = "Group with given id does not exist"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/{id}") + public ResponseEntity getGroup(@PathVariable("id") String groupId, Locale locale) { + try { + Group group = groupService.findById(groupId); + return ResponseEntity.ok(GroupDto.fromGroup(group, locale)); + } catch (IllegalArgumentException e) { + log.error("Cannot get group with id [{}]", groupId, e); + return ResponseEntity.badRequest().build(); + } + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Get paged of group members", + description = "Caller must have the ADMIN role", + security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Group members retrieved successfully"), + @ApiResponse(responseCode = "400", description = "Group with given id does not exist"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/{id}/users") + public ResponseEntity> getMembersOfGroup(@PathVariable("id") String groupId, Pageable pageable, Locale locale) { + try { + Group group = groupService.findById(groupId); + Page groupMembers = userService.findAllByIds(group.getMemberIds(), group.getRealmId(), pageable).map(u -> userFactory.getUser(u, locale)); + return ResponseEntity.ok(groupMembers); + } catch (IllegalArgumentException e) { + log.error("Cannot get members of group with id [{}]", groupId, e); + return ResponseEntity.badRequest().build(); + } + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Assigns multiple users to group", + description = "Caller must have the ADMIN role", + security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Users assigned to group successfully"), + @ApiResponse(responseCode = "400", description = "Group with given id does not exist"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PatchMapping("/{id}/users/assign") + public ResponseEntity assignUsersToGroup(@PathVariable("id") String groupId, @RequestBody Set userIds) { + try { + groupService.assignUsersToGroup(groupId, userIds); + return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Selected users assigned to group " + groupId)); + } catch (IllegalArgumentException e) { + String message = "Failed to assign members to group [%s]".formatted(groupId); + log.error(message, e); + return ResponseEntity.badRequest().body(ResponseMessage.createErrorMessage("Assigning members to group " + groupId + " has failed!")); + } + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Add user to group", + description = "Caller must have the ADMIN role", + security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "User added to group successfully"), + @ApiResponse(responseCode = "400", description = "Group with given id does not exist"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PatchMapping("/{id}/users/add/{userId}") + public ResponseEntity addUserToGroup(@PathVariable("id") String groupId, @PathVariable("userId") String userId) { + try { + Group group = groupService.findById(groupId); + AbstractUser user = userService.findById(userId, group.getRealmId()); + groupService.addUser(group, user); + return ResponseEntity.ok("Added user [" + userId + "] to group [" + groupId + "]"); + } catch (IllegalArgumentException e) { + String message = "Failed to add member [%s] to group [%s]".formatted(userId, groupId); + log.error(message, e); + return ResponseEntity.badRequest().body(message); + } + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Remove user from group", + description = "Caller must have the ADMIN role", + security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "User removed from group successfully"), + @ApiResponse(responseCode = "400", description = "Group or user with given id does not exist"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PatchMapping("/{id}/users/remove/{userId}") + public ResponseEntity removeUserFromGroup(@PathVariable("id") String groupId, @PathVariable("userId") String userId) { + try { + Group group = groupService.findById(groupId); + AbstractUser user = userService.findById(userId, group.getRealmId()); + groupService.removeUser(group, user); + return ResponseEntity.ok("User [" + userId + "] removed from group [" + groupId + "]"); + } catch (IllegalArgumentException e) { + String message = "Failed to remove member [%s] from group [%s]".formatted(userId, groupId); + log.error(message, e); + return ResponseEntity.badRequest().body("Failed to remove member from group: " + e.getMessage()); + } + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Assign roles to the group", description = "Assigns roles based on request body to group based on roleIds", security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Selected roles assigned successfully"), + @ApiResponse(responseCode = "400", description = "Requested roles or group with defined id does not exist"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PatchMapping(value = "/{id}/roles/assign", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity assignRolesToGroup(@PathVariable("id") String groupId, @RequestBody Set roleIds) { + try { + Group group = groupService.findById(groupId); + processRoleService.assignRolesToGroup(group, roleIds.stream().map(ProcessResourceId::new).collect(Collectors.toSet())); + log.info("Process roles {} assigned to group with id [{}]", roleIds, groupId); + return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Selected roles assigned to group " + groupId)); + } catch (IllegalArgumentException e) { + String message = "Assigning roles to group [" + groupId + "] has failed!"; + log.error(message, e); + return ResponseEntity.badRequest().body(ResponseMessage.createErrorMessage("Assigning roles to group " + groupId + " has failed!")); + } + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Adds roles to the group", description = "Adds roles based on request body to group based on roleIds", security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Selected roles added successfully"), + @ApiResponse(responseCode = "400", description = "Requested roles or group with defined id does not exist"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PatchMapping(value = "/{id}/roles/add", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity addRolesToGroup(@PathVariable("id") String groupId, @RequestBody Set roleIds) { + try { + roleIds.forEach(roleId -> groupService.addRole(groupId, roleId)); + log.info("Process roles {} added to group with id [{}]", roleIds, groupId); + return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Selected roles added to group " + groupId)); + } catch (IllegalArgumentException e) { + String message = "Adding roles to group [" + groupId + "] has failed!"; + log.error(message, e); + return ResponseEntity.badRequest().body(ResponseMessage.createErrorMessage("Adding roles to group " + groupId + " has failed!")); + } + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Revokes roles to the group", description = "Revokes roles based on request body from group based on id", security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Selected roles revoked successfully"), + @ApiResponse(responseCode = "400", description = "Requested roles or group with defined id does not exist"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PatchMapping(value = "/{id}/roles/revoke", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity revokeRolesFromGroup(@PathVariable("id") String groupId, @RequestBody Set roleIds) { + try { + roleIds.forEach(roleId -> groupService.removeRole(groupId, roleId)); + log.info("Process roles {} revoked from group with id [{}]", roleIds, groupId); + return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Selected roles revoked from group " + groupId)); + } catch (IllegalArgumentException e) { + String message = "Revoking roles from group [" + groupId + "] has failed!"; + log.error(message, e); + return ResponseEntity.badRequest().body(ResponseMessage.createErrorMessage("Revoking roles from group " + groupId + " has failed!")); + } + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Adds authority to the group", description = "Adds authority based on request body to group based on id", security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Selected authorities added successfully"), + @ApiResponse(responseCode = "400", description = "Requested authorities or group with defined id does not exist"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PatchMapping(value = "/{id}/authorities/add", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity addAuthorityToGroup(@PathVariable("id") String groupId, @RequestBody Set authorityIds) { + try { + authorityIds.forEach(authorityId -> groupService.addAuthority(groupId, authorityId)); + log.info("Authorities {} added to group with id [{}]", authorityIds, groupId); + return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Selected authorities added to group " + groupId)); + } catch (IllegalArgumentException e) { + String message = "Adding authorities to group [" + groupId + "] has failed!"; + log.error(message, e); + return ResponseEntity.badRequest().body(ResponseMessage.createErrorMessage("Adding authorities to group " + groupId + " has failed!")); + } + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Revokes authority from the group", description = "Revokes authority based on request body from group based on roleIds", security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Selected authorities revoked successfully"), + @ApiResponse(responseCode = "400", description = "Requested authorities or group with defined id does not exist"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PatchMapping(value = "/{id}/authorities/revoke", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity revokeAuthorityFromGroup(@PathVariable("id") String groupId, @RequestBody Set authorityIds) { + try { + authorityIds.forEach(authorityId -> groupService.removeAuthority(groupId, authorityId)); + log.info("Authorities {} revoked from group with id [{}]", authorityIds, groupId); + return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Selected authorities revoked from group " + groupId)); + } catch (IllegalArgumentException e) { + String message = "Revoking authorities to group [" + groupId + "] has failed!"; + log.error(message, e); + return ResponseEntity.badRequest().body(ResponseMessage.createErrorMessage("Revoking authorities to group " + groupId + " has failed!")); + } + } + + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Groups retrieved successfully"), + @ApiResponse(responseCode = "400", description = "Invalid group data"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @Operation(summary = "Generic group search", security = {@SecurityRequirement(name = "X-Auth-Token")}) + @GetMapping(produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity> search(GroupSearchRequestDto query, Pageable pageable, Locale locale) { + List groups = groupService.search(query, pageable).getContent(); + return ResponseEntity.ok(transformPageContent(groups, pageable, locale)); + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Updates group", description = "Updates group according to incoming parameters", security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Group updated successfully"), + @ApiResponse(responseCode = "400", description = "Invalid group parameters"), + @ApiResponse(responseCode = "404", description = "Group not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PutMapping(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity updateGroup(@RequestBody UpdateGroupRequestDto groupUpdate) { + try { + Group group = groupService.findById(groupUpdate.id()); + if (groupUpdate.identifier() != null) { + group.setIdentifier(groupUpdate.identifier()); + } + if (groupUpdate.displayName() != null) { + group.setDisplayName(groupUpdate.displayName()); + } + groupService.save(group); + return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Group with id [%s] updated successfully".formatted(groupUpdate.id()))); + } catch (IllegalArgumentException e) { + return ResponseEntity.notFound().build(); + } catch (Exception e) { + return ResponseEntity.internalServerError().body(ResponseMessage.createErrorMessage("Failed to update group with id [%s]".formatted(groupUpdate.id()))); + } + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Assigns subgroups to group", description = "Removes existing subgroups and assigns new ones to group based on path param and request body", security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Selected subgroups was successfully assigned to group"), + @ApiResponse(responseCode = "400", description = "Requested group or groups with defined id do not exist"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PatchMapping(value = "/{id}/groups/assign", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity assignSubgroupsToGroup(@PathVariable("id") String groupId, @RequestBody Set subgroupIds) { + try { + groupService.assignSubgroups(groupId, subgroupIds); + log.info("Subgroups {} assigned to group with id [{}]", subgroupIds, groupId); + return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Selected subgroups was successfully assigned to group")); + } catch (IllegalArgumentException e) { + String message = "Adding subgroups to group [" + groupId + "] has failed!"; + log.error(message, e); + return ResponseEntity.badRequest().body(ResponseMessage.createErrorMessage("Adding subgroups to group " + groupId + " has failed!")); + } + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Adds subgroups to group", description = "Add subgroups to group based on path param and request body", security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Selected subgroups was successfully added to group"), + @ApiResponse(responseCode = "400", description = "Requested group or groups with defined id do not exist"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PatchMapping(value = "/{id}/groups/add", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity addSubgroupsToGroup(@PathVariable("id") String groupId, @RequestBody Set subgroupIds) { + try { + subgroupIds.forEach(subgroupId -> groupService.addSubgroup(groupId, subgroupId)); + log.info("Subgroups {} added to group with id [{}]", subgroupIds, groupId); + return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Selected subgroups was successfully added to group")); + } catch (IllegalArgumentException e) { + String message = "Adding subgroups to group [" + groupId + "] has failed!"; + log.error(message, e); + return ResponseEntity.badRequest().body(ResponseMessage.createErrorMessage("Adding subgroups to group " + groupId + " has failed!")); + } + } + + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") + @Operation(summary = "Removes subgroups from group", description = "Removes subgroups from group based on path param and request body", security = {@SecurityRequirement(name = "X-Auth-Token")}) + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Selected subgroups was successfully removed from group"), + @ApiResponse(responseCode = "400", description = "Requested group or groups with defined id do not exist"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PatchMapping(value = "/{id}/groups/remove", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity removeSubgroupsFromGroup(@PathVariable("id") String groupId, @RequestBody Set subgroupIds) { + try { + subgroupIds.forEach(subgroupId -> groupService.removeSubgroup(groupId, subgroupId)); + log.info("Subgroups {} removed from group with id [{}]", subgroupIds, groupId); + return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Selected subgroups was successfully removed from group")); + } catch (IllegalArgumentException e) { + String message = "Removing subgroups from group [" + groupId + "] has failed!"; + log.error(message, e); + return ResponseEntity.badRequest().body(ResponseMessage.createErrorMessage("Removing subgroups from group " + groupId + " has failed!")); + } + } + + private Page transformPageContent(List groups, Pageable pageable, Locale locale) { + return new PageImpl<>(groups.stream().map(group -> GroupDto.fromGroup(group, locale)).toList(), pageable, groups.size()); + } + + private boolean realmExists(String realmId) { + if (realmId == null) { + return false; + } + Optional realm = realmService.getRealmById(realmId); + return realm.isPresent(); + } +} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/auth/web/PublicUserController.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/PublicUserController.java index 6d472275a12..8d1213dac48 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/auth/web/PublicUserController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/PublicUserController.java @@ -5,7 +5,7 @@ import com.netgrif.application.engine.auth.web.requestbodies.PreferencesRequest; import com.netgrif.application.engine.auth.web.requestbodies.UserSearchRequestBody; import com.netgrif.application.engine.auth.web.responsebodies.PreferencesResource; -import com.netgrif.application.engine.auth.web.responsebodies.User; +import com.netgrif.application.engine.auth.web.responsebodies.UserDto; import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.preferences.Preferences; @@ -53,7 +53,7 @@ public class PublicUserController { @ApiResponse(responseCode = "500", description = "Internal server error") }) @GetMapping(value = "/me", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity getLoggedUser(Authentication auth) { + public ResponseEntity getLoggedUser(Authentication auth) { LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); AbstractUser user; try { @@ -67,7 +67,7 @@ public ResponseEntity getLoggedUser(Authentication auth) { return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); } - return ResponseEntity.ok(User.createUser(user)); + return ResponseEntity.ok(UserDto.createUser(user)); } @ApiResponses(value = { @@ -77,7 +77,7 @@ public ResponseEntity getLoggedUser(Authentication auth) { }) @Operation(summary = "Generic user search", security = {@SecurityRequirement(name = "X-Auth-Token")}) @PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity> search(@RequestBody UserSearchRequestBody query, Pageable pageable, Authentication auth) { + public ResponseEntity> search(@RequestBody UserSearchRequestBody query, Pageable pageable, Authentication auth) { List roles = query.getRoles() == null ? null : query.getRoles().stream().map(ProcessResourceId::new).toList(); List negativeRoles = query.getNegativeRoles() == null ? null : query.getNegativeRoles().stream().map(ProcessResourceId::new).toList(); Page users = userService.searchAllCoMembers(query.getFulltext(), @@ -127,12 +127,12 @@ public ResponseEntity savePreferences(@RequestBody PreferencesRequest pr } } - private Page changeToResponse(Page users, Pageable pageable) { + private Page changeToResponse(Page users, Pageable pageable) { return new PageImpl<>(changeType(users.getContent()), pageable, users.getTotalElements()); } - public List changeType(List users) { - return users.stream().map(User::createUser).toList(); + public List changeType(List users) { + return users.stream().map(UserDto::createUser).toList(); } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/UserController.java index 2818d2d98ae..76d67cfc1bb 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/UserController.java @@ -7,7 +7,7 @@ import com.netgrif.application.engine.auth.web.requestbodies.UserCreateRequest; import com.netgrif.application.engine.auth.web.requestbodies.UserSearchRequestBody; import com.netgrif.application.engine.auth.web.responsebodies.PreferencesResource; -import com.netgrif.application.engine.auth.web.responsebodies.User; +import com.netgrif.application.engine.auth.web.responsebodies.UserDto; import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.Authority; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; @@ -62,7 +62,7 @@ public class UserController { @ApiResponse(responseCode = "500", description = "Internal server error") }) @PostMapping("/{realmId}") - public ResponseEntity createUser(@PathVariable String realmId, @RequestBody UserCreateRequest request, Locale locale) { + public ResponseEntity createUser(@PathVariable String realmId, @RequestBody UserCreateRequest request, Locale locale) { try { if (!realmExists(realmId)) { log.error("Realm with id [{}] not found", realmId); @@ -95,7 +95,7 @@ public ResponseEntity createUser(@PathVariable String realmId, @RequestBod @ApiResponse(responseCode = "500", description = "Internal server error") }) @GetMapping("/{realmId}/all") - public ResponseEntity> getAllUsers(@PathVariable String realmId, Pageable pageable, Locale locale) { + public ResponseEntity> getAllUsers(@PathVariable String realmId, Pageable pageable, Locale locale) { if (!realmExists(realmId)) { log.error("Realm with id [{}] not found", realmId); return ResponseEntity.badRequest().build(); @@ -111,7 +111,7 @@ public ResponseEntity> getAllUsers(@PathVariable String realmId, Page @ApiResponse(responseCode = "500", description = "Internal server error") }) @GetMapping(value = "/me", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity getLoggedUser(Authentication auth, Locale locale) { + public ResponseEntity getLoggedUser(Authentication auth, Locale locale) { LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); AbstractUser user; try { @@ -135,7 +135,7 @@ public ResponseEntity getLoggedUser(Authentication auth, Locale locale) { }) @Operation(summary = "Generic user search", security = {@SecurityRequirement(name = "X-Auth-Token")}) @PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity> search(@RequestBody UserSearchRequestBody query, Pageable pageable, Authentication auth, Locale locale) { + public ResponseEntity> search(@RequestBody UserSearchRequestBody query, Pageable pageable, Authentication auth, Locale locale) { List roles = query.getRoles() == null ? null : query.getRoles().stream().map(ProcessResourceId::new).toList(); List negativeRoles = query.getNegativeRoles() == null ? null : query.getNegativeRoles().stream().map(ProcessResourceId::new).toList(); Page users = userService.searchAllCoMembers(query.getFulltext(), @@ -153,7 +153,7 @@ public ResponseEntity> search(@RequestBody UserSearchRequestBody quer @ApiResponse(responseCode = "500", description = "Internal server error") }) @GetMapping(value = "/{realmId}/{id}", produces = MediaType.APPLICATION_JSON_VALUE) - public ResponseEntity getUser(@PathVariable("realmId") String realmId, @PathVariable("id") String userId, Locale locale) { + public ResponseEntity getUser(@PathVariable("realmId") String realmId, @PathVariable("id") String userId, Locale locale) { LoggedUser actualUser = userService.getLoggedUserFromContext(); // TODO: impersonation // LoggedUser loggedUser = actualUser.getSelfOrImpersonated(); @@ -251,7 +251,7 @@ public ResponseEntity assignRolesToUser(@PathVariable("realmId" // } // } // - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") @Operation(summary = "Get all authorities of the system", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "X-Auth-Token")}) @@ -265,7 +265,7 @@ public ResponseEntity> getAllAuthorities() { return ResponseEntity.ok(authorityService.findAll(Pageable.unpaged()).stream().toList()); } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") @Operation(summary = "Assign authority to the user", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "X-Auth-Token")}) @@ -325,11 +325,11 @@ public ResponseEntity savePreferences(@RequestBody PreferencesR } } - private Page changeToResponse(Page users, Pageable pageable, Locale locale) { + private Page changeToResponse(Page users, Pageable pageable, Locale locale) { return new PageImpl<>(changeType(users.getContent(), locale), pageable, users.getTotalElements()); } - public List changeType(List users, Locale locale) { + public List changeType(List users, Locale locale) { return users.stream().map(u -> userFactory.getUser(u, locale)).toList(); } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/UserResource.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/UserResource.java index da82aaab178..7ad5da3faed 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/UserResource.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/UserResource.java @@ -5,9 +5,9 @@ import java.util.ArrayList; -public class UserResource extends EntityModel { +public class UserResource extends EntityModel { - public UserResource(User content, String selfRel) { + public UserResource(UserDto content, String selfRel) { super(content, new ArrayList<>()); } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java b/application-engine/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java index 5cc48601259..f413ae1c606 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java @@ -80,7 +80,7 @@ public void setIndexService(IElasticIndexService indexService) { this.indexService = indexService; } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") @Operation(summary = "Reindex specified cases", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -114,7 +114,7 @@ public MessageResource reindex(@RequestBody Map searchBody, Auth } } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") @Operation(summary = "Reindex all or stale cases with bulk index", description = "Reindex all or stale cases (specified by IndexParams.indexAll param) with bulk index. Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java b/application-engine/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java index 5fca05b1095..9670d43b324 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java @@ -1,56 +1,56 @@ -package com.netgrif.application.engine.orgstructure.web; - -import com.netgrif.application.engine.auth.service.GroupService; -import com.netgrif.application.engine.orgstructure.web.responsebodies.Group; -import com.netgrif.application.engine.orgstructure.web.responsebodies.GroupsResource; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.data.domain.Pageable; -import org.springframework.hateoas.MediaTypes; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -@RestController -@RequestMapping("/api/group") -@ConditionalOnProperty( - value = "netgrif.engine.security.web.group-enabled", - havingValue = "true", - matchIfMissing = true -) -@Tag(name = "Group") -public class GroupController { - - private final GroupService service; - - public GroupController(GroupService service) { - this.service = service; - } - - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") - @Operation(summary = "Get all groups in the system", - description = "Caller must have the ADMIN role", - security = {@SecurityRequirement(name = "BasicAuth")}) - @GetMapping(value = "/all", produces = MediaTypes.HAL_JSON_VALUE) - @ApiResponses(value = { - @ApiResponse(responseCode = "200", description = "OK"), - @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), - }) - public GroupsResource getAllGroups() { - List groups = service.findAll(Pageable.unpaged()).getContent(); - Set groupResponse = groups.stream() - .map(g -> new Group(g.getStringId(), g.getDisplayName())) - .collect(Collectors.toCollection(HashSet::new)); - return new GroupsResource(groupResponse); - } -} +//package com.netgrif.application.engine.orgstructure.web; +// +//import com.netgrif.application.engine.auth.service.GroupService; +//import com.netgrif.application.engine.orgstructure.web.responsebodies.Group; +//import com.netgrif.application.engine.orgstructure.web.responsebodies.GroupsResource; +//import io.swagger.v3.oas.annotations.Operation; +//import io.swagger.v3.oas.annotations.responses.ApiResponse; +//import io.swagger.v3.oas.annotations.responses.ApiResponses; +//import io.swagger.v3.oas.annotations.security.SecurityRequirement; +//import io.swagger.v3.oas.annotations.tags.Tag; +//import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +//import org.springframework.data.domain.Pageable; +//import org.springframework.hateoas.MediaTypes; +//import org.springframework.security.access.prepost.PreAuthorize; +//import org.springframework.web.bind.annotation.GetMapping; +//import org.springframework.web.bind.annotation.RequestMapping; +//import org.springframework.web.bind.annotation.RestController; +// +//import java.util.HashSet; +//import java.util.List; +//import java.util.Set; +//import java.util.stream.Collectors; +// +//@RestController +//@RequestMapping("/api/group") +//@ConditionalOnProperty( +// value = "netgrif.engine.security.web.group-enabled", +// havingValue = "true", +// matchIfMissing = true +//) +//@Tag(name = "Group") +//public class GroupController { +// +// private final GroupService service; +// +// public GroupController(GroupService service) { +// this.service = service; +// } +// +// @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") +// @Operation(summary = "Get all groups in the system", +// description = "Caller must have the ADMIN role", +// security = {@SecurityRequirement(name = "BasicAuth")}) +// @GetMapping(value = "/all", produces = MediaTypes.HAL_JSON_VALUE) +// @ApiResponses(value = { +// @ApiResponse(responseCode = "200", description = "OK"), +// @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), +// }) +// public GroupsResource getAllGroups() { +// List groups = service.findAll(Pageable.unpaged()).getContent(); +// Set groupResponse = groups.stream() +// .map(g -> new Group(g.getStringId(), g.getDisplayName())) +// .collect(Collectors.toCollection(HashSet::new)); +// return new GroupsResource(groupResponse); +// } +//} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/GroupsResource.java b/application-engine/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/GroupsResource.java index a6039cd6bde..c61b891c669 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/GroupsResource.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/GroupsResource.java @@ -1,19 +1,19 @@ -package com.netgrif.application.engine.orgstructure.web.responsebodies; - -import com.netgrif.application.engine.orgstructure.web.GroupController; -import org.springframework.hateoas.CollectionModel; -import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; - - -public class GroupsResource extends CollectionModel { - - public GroupsResource(Iterable content) { - super(content); - buildLinks(); - } - - private void buildLinks() { - add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(GroupController.class) - .getAllGroups()).withSelfRel()); - } -} \ No newline at end of file +//package com.netgrif.application.engine.orgstructure.web.responsebodies; +// +//import com.netgrif.application.engine.orgstructure.web.GroupController; +//import org.springframework.hateoas.CollectionModel; +//import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; +// +// +//public class GroupsResource extends CollectionModel { +// +// public GroupsResource(Iterable content) { +// super(content); +// buildLinks(); +// } +// +// private void buildLinks() { +// add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(GroupController.class) +// .getAllGroups()).withSelfRel()); +// } +//} \ No newline at end of file diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/ProcessRoleService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/ProcessRoleService.java index e61ebf9c30a..407d6cb9bb8 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/ProcessRoleService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/ProcessRoleService.java @@ -416,38 +416,8 @@ public void deleteRolesOfNet(PetriNet net, LoggedUser loggedUser) { .collect(Collectors.toList()); Set deletedRoleStringIds = deletedRoleIds.stream().map(ProcessResourceId::toString).collect(Collectors.toSet()); - Pageable realmPageable = PageRequest.of(0, paginationProperties.getBackendPageSize()); - Page realms; - do { - realms = realmService.getSmallRealm(realmPageable); - - realms.forEach(realm -> { - Pageable usersPageable = PageRequest.of(0, paginationProperties.getBackendPageSize()); - Page users; - do { - users = this.userService.findAllByProcessRoles(new HashSet<>(deletedRoleIds), realm.getName(), usersPageable); - - for (AbstractUser user : users) { - log.info("[{}]: Removing deleted roles of Petri net {} version {} from user {} with id {}", - net.getStringId(), net.getIdentifier(), net.getVersion().toString(), user.getFullName(), user.getStringId()); - - if (user.getProcessRoles().isEmpty()) { - continue; - } - - Set newRoles = user.getProcessRoles().stream() - .filter(role -> !deletedRoleStringIds.contains(role.getStringId())) - .map(ProcessRole::get_id) - .collect(Collectors.toSet()); - this.assignRolesToUser(user, newRoles, loggedUser); - } - - usersPageable = usersPageable.next(); - } while (users.hasNext()); - }); - - realmPageable = realmPageable.next(); - } while (realms.hasNext()); + deleteRolesOfNetFromUser(net, deletedRoleIds, deletedRoleStringIds, loggedUser); + deleteRolesOfNetFromGroup(net, deletedRoleIds, deletedRoleStringIds); log.info("[{}]: Deleting all roles of Petri net {} version {}", net.getStringId(), net.getIdentifier(), net.getVersion().toString()); @@ -523,4 +493,60 @@ private ObjectId extractObjectId(String caseId) { return new ObjectId(objectIdPart); } + + private void deleteRolesOfNetFromUser(PetriNet net, List deletedRoleIds, Set deletedRoleStringIds, LoggedUser loggedUser) { + Pageable realmPageable = PageRequest.of(0, paginationProperties.getBackendPageSize()); + Page realms; + do { + realms = realmService.getSmallRealm(realmPageable); + + realms.forEach(realm -> { + Pageable usersPageable = PageRequest.of(0, paginationProperties.getBackendPageSize()); + Page users; + do { + users = this.userService.findAllByProcessRoles(new HashSet<>(deletedRoleIds), realm.getName(), usersPageable); + + for (AbstractUser user : users) { + log.info("[{}]: Removing deleted roles of Petri net {} version {} from user {} with id {}", + net.getStringId(), net.getIdentifier(), net.getVersion().toString(), user.getFullName(), user.getStringId()); + + if (user.getProcessRoles().isEmpty()) { + continue; + } + + Set newRoles = user.getProcessRoles().stream() + .filter(role -> !deletedRoleStringIds.contains(role.getStringId())) + .map(ProcessRole::get_id) + .collect(Collectors.toSet()); + this.assignRolesToUser(user, newRoles, loggedUser); + } + + usersPageable = usersPageable.next(); + } while (users.hasNext()); + }); + + realmPageable = realmPageable.next(); + } while (realms.hasNext()); + } + + private void deleteRolesOfNetFromGroup(PetriNet net, List deletedRoleIds, Set deletedRoleStringIds) { + Pageable groupPageable = PageRequest.of(0, paginationProperties.getBackendPageSize()); + Page groups; + do { + groups = groupService.findAllByProcessRoles(new HashSet<>(deletedRoleIds), groupPageable); + for (Group group : groups) { + log.info("[{}]: Removing deleted roles of Petri net {} version {} from group {} with id {}", + net.getStringId(), net.getIdentifier(), net.getVersion().toString(), group.getFullName(), group.getStringId()); + if (group.getProcessRoles().isEmpty()) { + continue; + } + Set newRoles = group.getProcessRoles().stream() + .filter(role -> !deletedRoleStringIds.contains(role.getStringId())) + .map(ProcessRole::get_id) + .collect(Collectors.toSet()); + assignRolesToGroup(group, newRoles); + } + groupPageable = groupPageable.next(); + } while (groups.hasNext()); + } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index d4b062650c2..29497470846 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -95,7 +95,7 @@ public static String decodeUrl(String s1) { } } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") @Operation(summary = "Import new process", description = "Caller must have the ADMIN role. Imports an entirely new process or a new version of an existing process.", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -182,7 +182,7 @@ public TransactionsResource getTransactions(@PathVariable("netId") String netId, return new TransactionsResource(net.getTransactions().values(), netId, locale); } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") @Operation(summary = "Download process model", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/{netId}/file", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) public FileSystemResource getNetFile(@PathVariable("netId") String netId, @RequestParam(value = "title", required = false) String title, Authentication auth, HttpServletResponse response) { diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/ProcessRoleController.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/ProcessRoleController.java index 77cac9d06fd..7d10c6f9f8d 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/ProcessRoleController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/ProcessRoleController.java @@ -34,7 +34,7 @@ public class ProcessRoleController { private final ProcessRoleService processRoleService; - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") @Operation(summary = "Delete global role", security = {@SecurityRequirement(name = "X-Auth-Token")}) @Parameter(name = "id", description = "Id of the global role to be deleted", required = true, example = "GcdIZcAPUc6jh7i2-68d683f80dc9384aa6791a64") diff --git a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/GroupRunner.java b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/GroupRunner.java index a404fc17d94..b9783d6cfe2 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/GroupRunner.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/GroupRunner.java @@ -3,6 +3,7 @@ import com.netgrif.application.engine.auth.config.GroupConfigurationProperties; import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.auth.service.GroupService; +import com.netgrif.application.engine.objects.auth.domain.Group; import com.netgrif.application.engine.startup.ApplicationEngineStartupRunner; import com.netgrif.application.engine.startup.annotation.RunnerOrder; import lombok.RequiredArgsConstructor; @@ -11,6 +12,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Component; +import java.util.Optional; + @Slf4j @Component @RunnerOrder(110) @@ -24,12 +27,16 @@ public class GroupRunner implements ApplicationEngineStartupRunner { @Override public void run(ApplicationArguments args) throws Exception { - createDefaultGroup(); + if (groupProperties.isSystemEnabled()) { + createDefaultGroup(); + } } protected void createDefaultGroup() { - if (groupProperties.isSystemEnabled()) { - groupService.create(userService.getLoggedOrSystem()); + Optional systemGroupOpt = groupService.findByIdentifier(userService.getSystem().getUsername()); + if (systemGroupOpt.isEmpty()) { + groupService.create(userService.getSystem()); + log.info("Default system group created."); } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/SuperCreatorRunner.java b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/SuperCreatorRunner.java index d3059fe5a64..3281cb4457f 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/SuperCreatorRunner.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/SuperCreatorRunner.java @@ -83,7 +83,7 @@ public void setAllToSuperUser() { } public void setAllGroups() { - groupService.findAll(Pageable.unpaged()).forEach(g -> groupService.addUser(getSuperUser(), g)); + groupService.findAll(Pageable.unpaged()).forEach(g -> groupService.addUser(g, getSuperUser())); } public void setAllProcessRoles() { diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java index 7222b4ae969..8a7aa04a8fe 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java @@ -176,7 +176,7 @@ public PagedModel findAllByAuthor(@PathVariable("id") String autho return PagedModel.of(cases.stream().map(CaseResource::new).toList(), new PagedModel.PageMetadata(pageable.getPageSize(), pageable.getPageNumber(), cases.getTotalElements())); } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") @Operation(summary = "Reload tasks of case", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy index f55beac18b8..824b7b41293 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy @@ -100,7 +100,7 @@ class AssignActionTest { auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - importHelper.createUser(new User(firstName: "Test", lastName: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), + importHelper.createUser(new User(firstName: "Test", lastName: "Integration", username: USER_EMAIL, email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), [auths.get("user"), auths.get("admin")] as Authority[], // [org] as Group[], [] as ProcessRole[]) diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/auth/LoginAttemptsTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/auth/LoginAttemptsTest.groovy index c75b94d7869..202eadfb876 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/auth/LoginAttemptsTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/auth/LoginAttemptsTest.groovy @@ -63,7 +63,7 @@ class LoginAttemptsTest { .build() auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - importHelper.createUser(new User(firstName: "Test", lastName: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), + importHelper.createUser(new User(firstName: "Test", lastName: "Integration", username: USER_EMAIL, email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), [auths.get("user"), auths.get("admin")] as Authority[], [] as ProcessRole[]) } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy index b68de6738a8..9f6f524b978 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy @@ -183,7 +183,7 @@ class TaskAuthorizationServiceTest { this.netWithUserRefs = netWithUserRefs.getNet() def auths = importHelper.createAuthorities(["user": Authority.user]) - testUser = importHelper.createUser(new User(firstName: "Role", lastName: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), + testUser = importHelper.createUser(new User(firstName: "Role", lastName: "User", username: USER_EMAIL, email: USER_EMAIL, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], // [org] as Group[], [] as ProcessRole[] diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy index 9872f6c5110..22ec3b20711 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy @@ -141,7 +141,7 @@ class WorkflowAuthorizationServiceTest { this.netWithUserRefs = netWithUserRefs.getNet() def auths = importHelper.createAuthorities(["user": Authority.user]) - testUser = importHelper.createUser(new User(firstName: "Role", lastName: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), + testUser = importHelper.createUser(new User(firstName: "Role", lastName: "User", username: USER_EMAIL, email: USER_EMAIL, password: "password", state: UserState.ACTIVE), [auths.get("user")]as Authority[], // [org] as Group[], [] as ProcessRole[]) diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/elastic/DataSearchRequestTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/elastic/DataSearchRequestTest.groovy index 9fcd5a7353a..2c6fa62c6da 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/elastic/DataSearchRequestTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/elastic/DataSearchRequestTest.groovy @@ -196,8 +196,8 @@ class DataSearchRequestTest { new AbstractMap.SimpleEntry("fileList.fileNameValue.keyword" as String, "multifile2" as String), new AbstractMap.SimpleEntry("fileList.fileExtensionValue.keyword" as String, "txt" as String), new AbstractMap.SimpleEntry("fileList.fileExtensionValue.keyword" as String, "pdf" as String), - new AbstractMap.SimpleEntry("userList" as String, "${testUser1.name} ${testUser1.email}" as String), - new AbstractMap.SimpleEntry("userList" as String, "${testUser2.name} ${testUser2.email}" as String), + new AbstractMap.SimpleEntry("userList" as String, "${testUser1.name} ${testUser1.username}" as String), + new AbstractMap.SimpleEntry("userList" as String, "${testUser2.name} ${testUser2.username}" as String), new AbstractMap.SimpleEntry("userList" as String, "${groupService.getDefaultSystemGroup().getFullName()}" as String), new AbstractMap.SimpleEntry("userList.usernameValue.keyword" as String, "${testUser1.username}" as String), new AbstractMap.SimpleEntry("userList.usernameValue.keyword" as String, "${testUser2.username}" as String), diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy index 7803d2f9aa3..94d9005f8ec 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy @@ -204,7 +204,7 @@ class MenuImportExportTest { private User createDummyUser() { def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - return importHelper.createUser(new User(firstName: "Dummy", lastName: "User", email: DUMMY_USER_MAIL, password: DUMMY_USER_PASSWORD, state: UserState.ACTIVE), + return importHelper.createUser(new User(firstName: "Dummy", lastName: "User", username: DUMMY_USER_MAIL, email: DUMMY_USER_MAIL, password: DUMMY_USER_PASSWORD, state: UserState.ACTIVE), [auths.get("user")] as Authority[], [] as ProcessRole[]) } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/GroupServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/GroupServiceTest.groovy index e577779fae4..75760ca08ff 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/GroupServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/GroupServiceTest.groovy @@ -1,21 +1,32 @@ package com.netgrif.application.engine.orgstructure.groups import com.netgrif.application.engine.TestHelper +import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService import com.netgrif.application.engine.auth.service.GroupService import com.netgrif.application.engine.auth.service.UserService +import com.netgrif.application.engine.objects.auth.domain.AbstractUser import com.netgrif.application.engine.objects.auth.domain.Authority import com.netgrif.application.engine.objects.auth.domain.Group import com.netgrif.application.engine.objects.auth.domain.QGroup import com.netgrif.application.engine.objects.auth.domain.User import com.netgrif.application.engine.objects.auth.domain.enums.UserState +import com.netgrif.application.engine.objects.petrinet.domain.PetriNet +import com.netgrif.application.engine.objects.petrinet.domain.VersionType import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole +import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.petrinet.params.ImportPetriNetParams +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.runner.GroupRunner import com.netgrif.application.engine.utils.FullPageRequest +import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest +import org.springframework.data.domain.Page +import org.springframework.data.domain.Pageable +import org.springframework.data.util.Pair import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension @@ -37,65 +48,84 @@ class GroupServiceTest { UserService userService @Autowired - private ImportHelper importHelper + ProcessRoleService processRoleService + + @Autowired + ImportHelper importHelper + + @Autowired + IPetriNetService petriNetService @Autowired TestHelper testHelper - @Test - void groupTest() { + AbstractUser dummy, customer + + @BeforeEach + void init() { testHelper.truncateDbs() def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - importHelper.createUser(new User(firstName: "Dummy", lastName: "User", email: DUMMY_USER_MAIL, username: DUMMY_USER_MAIL, password: "password", state: UserState.ACTIVE), + dummy = importHelper.createUser(new User(firstName: "Dummy", lastName: "User", email: DUMMY_USER_MAIL, username: DUMMY_USER_MAIL, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], [] as ProcessRole[]) - importHelper.createUser(new User(firstName: "Customer", lastName: "User", email: CUSTOMER_USER_MAIL, username: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), + customer = importHelper.createUser(new User(firstName: "Customer", lastName: "User", email: CUSTOMER_USER_MAIL, username: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], [] as ProcessRole[]) - Group customGroup = createGroup() - if (customGroup == null) { - throw new NullPointerException() - } - - List allGroups = findAllGroups() - assert !allGroups.isEmpty() - - List byPredicate = findGroup() - assert !byPredicate.isEmpty() - - Group addedUserGroup = addUser() - assert !addedUserGroup.getMemberIds().isEmpty() - - Group removedUserGroup = removeUser() - assert !removedUserGroup.getMemberIds().isEmpty() } - Group createGroup() { - return groupService.create("CUSTOM_GROUP_1", "CUSTOM_GROUP_1", userService.findUserByUsername(DUMMY_USER_MAIL, null).get()) + @Test + void createGroup() { + groupService.create("CUSTOM_GROUP_1", "CUSTOM_GROUP_1", userService.findUserByUsername(DUMMY_USER_MAIL, null).get()) + Optional groupOpt = groupService.findByIdentifier("CUSTOM_GROUP_1") + assert groupOpt.isPresent() + } - List findGroup() { + @Test + void findGroup() { QGroup qGroup = new QGroup("group") - return groupService.findByPredicate(qGroup.ownerUsername.eq(DUMMY_USER_MAIL), new FullPageRequest()).getContent() + Page groupPage = groupService.findByPredicate(qGroup.ownerUsername.eq(DUMMY_USER_MAIL), Pageable.ofSize(1)) + assert !groupPage.isEmpty() } - List findAllGroups() { - return groupService.findAll() as List + @Test + void addAndRemoveUser() { + QGroup qGroup = new QGroup("group") + Group group = groupService.findByPredicate(qGroup.identifier.eq(DUMMY_USER_MAIL), new FullPageRequest()).getContent().get(0) + group = groupService.addUser(userService.findUserByUsername(CUSTOMER_USER_MAIL, null).get(), group) + assert group.getMemberIds().size() == 2 + group = groupService.removeUser(userService.findUserByUsername(CUSTOMER_USER_MAIL, null).get(), group) + assert group.getMemberIds().size() == 1 } - Group addUser() { - QGroup qGroup = new QGroup("group") - Group group = groupService.findByPredicate(qGroup.identifier.eq("CUSTOM_GROUP_1"), new FullPageRequest()).getContent().get(0) - groupService.addUser(userService.findUserByUsername(CUSTOMER_USER_MAIL, null).get(), group) - groupService.addUser(userService.findUserByUsername("engine@netgrif.com", null).get(), group) - return group + @Test + void addAndRemoveRole() { + ImportPetriNetEventOutcome netWithRoleOutcome = petriNetService.importPetriNet(ImportPetriNetParams.with() + .xmlFile(new FileInputStream("src/test/resources/simple_role.xml")) + .releaseType(VersionType.MAJOR) + .author(userService.getSystem()) + .build()) + ProcessRole role = netWithRoleOutcome.getNet().getRoles().values().find { it.importId == "simple_role"} + Group group = groupService.create("addAndRemoveRole", "Add and remove role test group", dummy) + group = groupService.addRole(group.getStringId(), role.getStringId()) + assert group.getProcessRoles().any {it.getStringId() == role.getStringId()} + group = groupService.removeRole(group.getStringId(), role.getStringId()) + assert !group.getProcessRoles().any() {it.getStringId() == role.getStringId()} } - Group removeUser() { - QGroup qGroup = new QGroup("group") - Group group = groupService.findByPredicate(qGroup.identifier.eq("CUSTOM_GROUP_1"), new FullPageRequest()).getContent().get(0) - groupService.removeUser(userService.findUserByUsername(CUSTOMER_USER_MAIL, null).get(), group) - return group + @Test + void addAndRemoveSubgroup() { + Group group = groupService.findByIdentifier(dummy.getUsername()).orElse(null) + assert group != null + Group subGroup = groupService.create("addAndRemoveSubgroup", "Add and remove role test group", dummy) + + Pair groupPair = groupService.addSubgroup(group.getStringId(), subGroup.getStringId()) + assert groupPair.getFirst().getSubgroupIds().contains(subGroup.getStringId()) + assert groupPair.getSecond().getGroupIds().contains(group.getStringId()) + + groupPair = groupService.removeSubgroup(group.getStringId(), subGroup.getStringId()) + assert !groupPair.getFirst().getSubgroupIds().contains(subGroup.getStringId()) + assert !groupPair.getSecond().getGroupIds().contains(group.getStringId()) } } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy index b49b795d8a1..25528011193 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy @@ -106,7 +106,7 @@ class ElasticSearchViewPermissionTest { userAuthority = authorityService.getOrCreate(Authority.user) - testUser = importHelper.createUser(new User(firstName: "Role", lastName: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), + testUser = importHelper.createUser(new User(firstName: "Role", lastName: "User", username: USER_EMAIL, email: USER_EMAIL, password: "password", state: UserState.ACTIVE), [userAuthority] as Authority[], [] as ProcessRole[]) } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/permissions/QueryDSLViewPermissionTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/permissions/QueryDSLViewPermissionTest.groovy index 61a2e8d3b43..e33210d26d7 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/permissions/QueryDSLViewPermissionTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/permissions/QueryDSLViewPermissionTest.groovy @@ -99,7 +99,7 @@ class QueryDSLViewPermissionTest { userAuthority = authorityService.getOrCreate(Authority.user) - testUser = importHelper.createUser(new User(firstName: "Role", lastName: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), + testUser = importHelper.createUser(new User(firstName: "Role", lastName: "User", username: USER_EMAIL, email: USER_EMAIL, password: "password", state: UserState.ACTIVE), [userAuthority] as Authority[], [] as ProcessRole[]) } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileFieldTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileFieldTest.groovy index a7195dc8103..5d513874a1d 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileFieldTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileFieldTest.groovy @@ -135,10 +135,7 @@ class FileFieldTest { def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - def adminUser = importHelper.createUser(new User(firstName: "Admin", lastName: "User", username: UserConstants.ADMIN_USER_USERNAME, email: UserConstants.ADMIN_USER_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("admin")] as Authority[], -// [] as Group[], - [] as ProcessRole[]) + def adminUser = userService.findUserByUsername(UserConstants.ADMIN_USER_USERNAME, null).get() auth = new UsernamePasswordAuthenticationToken(ActorTransformer.toLoggedUser(adminUser), "password", [auths.get("admin")] as List) auth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileListFieldTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileListFieldTest.groovy index 75fcf2f448c..eed14509b23 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileListFieldTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/domain/dataset/FileListFieldTest.groovy @@ -135,10 +135,7 @@ class FileListFieldTest { def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - def adminUser = importHelper.createUser(new User(firstName: "Admin", lastName: "User", username: UserConstants.ADMIN_USER_USERNAME, email: USER_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("admin")] as Authority[], -// [] as Group[], - [] as ProcessRole[]) + def adminUser = userService.findUserByUsername(UserConstants.ADMIN_USER_USERNAME, null).get() auth = new UsernamePasswordAuthenticationToken(ActorTransformer.toLoggedUser(adminUser), "password", [auths.get("admin")] as List) auth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy index c2ec5a73c89..41727186d2a 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy @@ -61,7 +61,7 @@ class CachePetriNetServiceTest { void setup() { testHelper.truncateDbs() def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - importHelper.createUser(new User(firstName: "Customer", lastName: "User", email: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), + importHelper.createUser(new User(firstName: "Customer", lastName: "User", username: CUSTOMER_USER_MAIL, email: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], [] as ProcessRole[]) } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy index 90ee4f54048..50415003895 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy @@ -96,7 +96,7 @@ class PetriNetServiceTest { void setup() { testHelper.truncateDbs() def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - importHelper.createUser(new User(firstName: "Customer", lastName: "User", email: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), + importHelper.createUser(new User(firstName: "Customer", lastName: "User", username: CUSTOMER_USER_MAIL, email: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], [] as ProcessRole[]) } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy index 5477dcf487a..5c2ec63d604 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy @@ -34,6 +34,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders import org.springframework.web.context.WebApplicationContext import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.user import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status @@ -99,7 +100,7 @@ class PetriNetControllerTest { def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) - def simpleUser = importHelper.createUser(new User(firstName: "Role", lastName: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), + def simpleUser = importHelper.createUser(new User(firstName: "Role", lastName: "User", username: USER_EMAIL, email: USER_EMAIL, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], // [] as Group[], [] as ProcessRole[]) @@ -107,7 +108,7 @@ class PetriNetControllerTest { userAuth = new UsernamePasswordAuthenticationToken(ActorTransformer.toLoggedUser(simpleUser), "password", [auths.get("user")] as List) userAuth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) - def adminUser = importHelper.createUser(new User(firstName: "Admin", lastName: "User", email: ADMIN_EMAIL, password: "password", state: UserState.ACTIVE), + def adminUser = importHelper.createUser(new User(firstName: "Admin", lastName: "User", username: ADMIN_EMAIL, email: ADMIN_EMAIL, password: "password", state: UserState.ACTIVE), [auths.get("admin")] as Authority[], // [] as Group[], [] as ProcessRole[]) diff --git a/application-engine/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java b/application-engine/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java index a1f61c2029f..adc9bced5f9 100644 --- a/application-engine/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java +++ b/application-engine/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java @@ -130,6 +130,7 @@ public void before() throws Exception { user.setCredential("password", passwordCredential); user.setState(UserState.ACTIVE); user.setEmail("VariableArcsTest@test.com"); + user.setUsername("VariableArcsTest@test.com"); testUser = importHelper.createUser(user, new Authority[]{authorityService.getOrCreate(Authority.user)}, new ProcessRole[]{}); diff --git a/application-engine/src/test/resources/simple_role.xml b/application-engine/src/test/resources/simple_role.xml new file mode 100644 index 00000000000..eb843ee34f0 --- /dev/null +++ b/application-engine/src/test/resources/simple_role.xml @@ -0,0 +1,14 @@ + + simple_role + 1.0.0 + SMR + Simple Role + device_hub + true + true + false + + simple_role + Simple role + + \ No newline at end of file diff --git a/docs/javadoc/com/netgrif/application/engine/auth/service/AuthorizationService.html b/docs/javadoc/com/netgrif/application/engine/auth/service/AuthorizationService.html index 4561d141e47..83e26e6c0e5 100644 --- a/docs/javadoc/com/netgrif/application/engine/auth/service/AuthorizationService.html +++ b/docs/javadoc/com/netgrif/application/engine/auth/service/AuthorizationService.html @@ -125,7 +125,7 @@

Class AuthorizationService<
  • java.lang.Object
    • -
    • com.netgrif.application.engine.auth.service.AuthorizationService
    • +
    • com.netgrif.application.engine.auth.service.AuthorizationServiceImpl
  • diff --git a/docs/javadoc/com/netgrif/application/engine/auth/service/class-use/AuthorizationService.html b/docs/javadoc/com/netgrif/application/engine/auth/service/class-use/AuthorizationService.html index 7ca1e28b96f..aba16657ac5 100644 --- a/docs/javadoc/com/netgrif/application/engine/auth/service/class-use/AuthorizationService.html +++ b/docs/javadoc/com/netgrif/application/engine/auth/service/class-use/AuthorizationService.html @@ -3,7 +3,7 @@ -Uses of Class com.netgrif.application.engine.auth.service.AuthorizationService (NETGRIF Application Engine 6.4.0 API) +Uses of Class com.netgrif.application.engine.auth.service.AuthorizationServiceImpl (NETGRIF Application Engine 6.4.0 API) @@ -22,7 +22,7 @@