From 037445c41147e4b0dc48853f868f98399df22ea8 Mon Sep 17 00:00:00 2001 From: renczesstefan Date: Mon, 9 Feb 2026 16:07:35 +0100 Subject: [PATCH 01/25] [NAE-2286] Group API - Introduced methods in `ActionDelegate` for CRUD operations on groups: - Added methods for creating, deleting, saving, and finding groups (`createGroup`, `deleteGroup`, `saveGroup`, `findGroupByIdentifier`, etc.). - Supported user assignments to groups with methods like `addUserToGroup`, `removeUserFromGroup`. - Added operations for managing group roles and authorities. - Enhanced `GroupService` with detailed methods for: - Adding/removing users, roles, and authorities to/from groups. - Managing subgroup relationships, including creation and deletion of parent-child links. - Extended MongoDB query support for group searches. - Annotated `Group` entity with custom annotations: - Ensured collection using `@EnsureCollection`. - Enhanced query capabilities with `@Indexed` on key fields. - Improved documentation for all newly added methods. These changes introduce robust support for group-related operations, enhancing scalability and clarity for permissions and role management. --- .../logic/action/ActionDelegate.groovy | 52 +++++++ .../petrinet/service/ProcessRoleService.java | 4 +- .../engine/objects/auth/domain/Group.java | 7 + .../petrinet/service/ProcessRoleService.java | 2 +- .../engine/auth/service/GroupServiceImpl.java | 108 ++++++++++++++- .../engine/auth/service/GroupService.java | 127 ++++++++++++++++-- 6 files changed, 283 insertions(+), 17 deletions(-) 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 06a51af45e..5933e296f9 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 @@ -33,7 +33,9 @@ import com.netgrif.application.engine.objects.auth.domain.ActorTransformer import com.netgrif.application.engine.menu.services.interfaces.DashboardItemService import com.netgrif.application.engine.menu.services.interfaces.DashboardManagementService 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 @@ -47,6 +49,7 @@ import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole import com.netgrif.application.engine.objects.petrinet.domain.version.Version import com.netgrif.application.engine.objects.utils.MenuItemUtils import com.netgrif.application.engine.objects.workflow.domain.Case +import com.netgrif.application.engine.objects.workflow.domain.ProcessResourceId import com.netgrif.application.engine.objects.workflow.domain.Task import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.EventOutcome import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.caseoutcomes.ChangeCasePropertyOutcome @@ -2856,4 +2859,53 @@ 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 userId, String groupId, String realmId) { + return groupService.addUser(userId, groupId, realmId) + } + + Group removeUserFromGroup(String userId, String realmId, String groupId) { + return groupService.removeUser(userId, realmId, groupId) + } + + Group assignAuthorityToGroup(String groupId, String authorityId) { + return groupService.assignAuthority(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) + } } 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 e61ebf9c30..63ffc4f27e 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 @@ -126,9 +126,9 @@ public void assignRolesToUser(AbstractUser user, Collection p } @Override - public void assignRolesToGroup(Group group, Collection requestedRolesIds) { + public Group assignRolesToGroup(Group group, Collection requestedRolesIds) { assignRolesToActor(group.getProcessRoles(), requestedRolesIds); - groupService.save(group); + return groupService.save(group); } protected void assignRolesToActor(Collection oldActorRoles, Collection requestedRolesIds) { diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/Group.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/Group.java index 5c14ba51de..146026f8c3 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/Group.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/domain/Group.java @@ -1,5 +1,7 @@ package com.netgrif.application.engine.objects.auth.domain; +import com.netgrif.application.engine.objects.annotations.EnsureCollection; +import com.netgrif.application.engine.objects.annotations.Indexed; import com.querydsl.core.annotations.QueryEntity; import lombok.Getter; import lombok.Setter; @@ -16,30 +18,35 @@ */ @Getter @QueryEntity +@EnsureCollection public class Group extends AbstractActor implements Serializable { /** * The unique identifier of the group. */ @Setter + @Indexed private String identifier; /** * The display name of the group shown in the user interface. */ @Setter + @Indexed private String displayName; /** * The unique identifier of the group owner. */ @Setter + @Indexed private String ownerId; /** * The username of the group owner. */ @Setter + @Indexed private String ownerUsername; /** diff --git a/nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/service/ProcessRoleService.java b/nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/service/ProcessRoleService.java index 4b4ee16127..3889de44ad 100644 --- a/nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/service/ProcessRoleService.java +++ b/nae-spring-core-adapter/src/main/java/com/netgrif/application/engine/adapter/spring/petrinet/service/ProcessRoleService.java @@ -20,7 +20,7 @@ public interface ProcessRoleService { void deleteAll(Collection ids); void deleteAll(); void assignRolesToUser(AbstractUser user, Collection roleIds, LoggedUser loggedUser); - void assignRolesToGroup(Group group, Collection requestedRolesIds); + Group assignRolesToGroup(Group group, Collection requestedRolesIds); ProcessRole getDefaultRole(); ProcessRole getAnonymousRole(); diff --git a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/GroupServiceImpl.java b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/GroupServiceImpl.java index b13df2a032..7c429e4c0c 100644 --- a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/GroupServiceImpl.java +++ b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/GroupServiceImpl.java @@ -1,5 +1,6 @@ package com.netgrif.application.engine.auth.service; +import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService; import com.netgrif.application.engine.adapter.spring.utils.PaginationProperties; import com.netgrif.application.engine.auth.config.GroupConfigurationProperties; import com.netgrif.application.engine.auth.provider.CollectionNameProvider; @@ -9,6 +10,9 @@ import com.netgrif.application.engine.objects.auth.dto.GroupSearchDto; import com.netgrif.application.engine.objects.common.ResourceNotFoundException; import com.netgrif.application.engine.objects.common.ResourceNotFoundExceptionCode; +import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; +import com.netgrif.application.engine.objects.workflow.domain.ProcessResourceId; +import org.springframework.context.annotation.Lazy; import org.springframework.data.domain.PageImpl; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; @@ -46,6 +50,8 @@ public class GroupServiceImpl implements GroupService { private MongoTemplate mongoTemplate; + private ProcessRoleService processRoleService; + @Autowired public void setCollectionNameProvider(CollectionNameProvider collectionNameProvider) { this.collectionNameProvider = collectionNameProvider; @@ -81,6 +87,12 @@ public void setPaginationProperties(PaginationProperties paginationProperties) { this.paginationProperties = paginationProperties; } + @Lazy + @Autowired + public void setProcessRoleService(ProcessRoleService processRoleService) { + this.processRoleService = processRoleService; + } + @Override public void delete(Group group) { if (!groupRepository.existsById(group.getStringId())) { @@ -122,7 +134,11 @@ public void delete(Group group) { @Override public Group save(Group group) { - log.debug("Saving group: [{}]", group.getStringId()); + if (groupRepository.existsById(group.getStringId())) { + log.info("Updating group: [{}]", group.getIdentifier()); + } else { + log.info("Saving new group: [{}]", group.getIdentifier()); + } group.setModifiedAt(LocalDateTime.now()); return groupRepository.save(group); } @@ -223,8 +239,8 @@ public Group addUser(String userId, Group group, String realmId) { } @Override - public Group addUser(AbstractUser user, String groupIdentifier) { - Group group = findByIdentifier(groupIdentifier).orElseThrow(() -> new IllegalArgumentException("Group with identifier [%s] not found. ".formatted(groupIdentifier))); + public Group addUser(AbstractUser user, String groupId) { + Group group = findById(groupId); return addUser(user, group); } @@ -238,8 +254,13 @@ public Group addUser(AbstractUser user, Group group) { } @Override - public Group removeUser(AbstractUser user, String groupIdentifier) { - Group group = findByIdentifier(groupIdentifier).orElseThrow(() -> new IllegalArgumentException("Group with identifier [%s] not found. ".formatted(groupIdentifier))); + public Group removeUser(String userId, String realmId, String groupId) { + return removeUser(userService.findById(userId, realmId), groupId); + } + + @Override + public Group removeUser(AbstractUser user, String groupId) { + Group group = findById(groupId); return removeUser(user, group); } @@ -289,13 +310,21 @@ public Group assignAuthority(String groupId, String authorityId) { return save(group); } + @Override + public Group removeAuthority(String groupId, String authorityId) { + Group group = findById(groupId); + group.removeAuthority(authorityService.getOne(authorityId)); + return save(group); + } + @Override public Pair addSubgroup(String parentGroupId, String childGroupId) { if (parentGroupId.equals(childGroupId)) { throw new IllegalArgumentException("Trying to add group to itself [%s]!".formatted(parentGroupId)); } Group parentGroup = this.findById(parentGroupId); - return this.addSubgroup(parentGroup, childGroupId); + Group childGroup = this.findById(childGroupId); + return this.addSubgroup(parentGroup, childGroup); } @Override @@ -330,6 +359,47 @@ public Pair addSubgroup(Group parentGroup, Group childGroup) { return Pair.of(parentGroup, childGroup); } + @Override + public Pair removeSubgroup(String parentGroupId, String childGroupId) { + if (parentGroupId.equals(childGroupId)) { + throw new IllegalArgumentException("Trying to remove group from itself [%s]!".formatted(parentGroupId)); + } + Group parentGroup = this.findById(parentGroupId); + Group childGroup = this.findById(childGroupId); + return this.removeSubgroup(parentGroup, childGroup); + } + + @Override + public Pair removeSubgroup(Group parentGroup, String childGroupId) { + if (parentGroup.getStringId().equals(childGroupId)) { + throw new IllegalArgumentException("Trying to remove group from itself [%s]!".formatted(parentGroup.getStringId())); + } + Group childGroup = this.findById(childGroupId); + return this.removeSubgroup(parentGroup, childGroup); + } + + @Override + public Pair removeSubgroup(String parentGroupId, Group childGroup) { + if (childGroup.getStringId().equals(parentGroupId)) { + throw new IllegalArgumentException("Trying to remove group from itself [%s]!".formatted(childGroup.getStringId())); + } + Group parentGroup = this.findById(parentGroupId); + return this.removeSubgroup(parentGroup, childGroup); + } + + @Override + public Pair removeSubgroup(Group parentGroup, Group childGroup) { + if (parentGroup.getStringId().equals(childGroup.getStringId())) { + throw new IllegalArgumentException("Trying to remove group from itself [%s]!".formatted(parentGroup.getStringId())); + } + parentGroup.removeSubgroupId(childGroup.getStringId()); + childGroup.removeGroupId(parentGroup.getStringId()); + log.info("Removing group [{}] from parent group [{}]", childGroup.getStringId(), parentGroup.getStringId()); + this.save(parentGroup); + this.save(childGroup); + return Pair.of(parentGroup, childGroup); + } + @Override public List getGroupParentGroupsById(String groupId) { Group group = this.findById(groupId); @@ -391,6 +461,32 @@ public Page search(GroupSearchDto searchDto, Pageable pageable) { return new PageImpl<>(groups, pageable, count); } + @Override + public Group addRole(String groupId, String roleId) { + Group group = findById(groupId); + ProcessRole role = processRoleService.findById(new ProcessResourceId(roleId)); + return addRole(group, role); + } + + @Override + public Group addRole(Group group, ProcessRole processRole) { + group.addProcessRole(processRole); + return save(group); + } + + @Override + public Group removeRole(String groupId, String roleId) { + Group group = findById(groupId); + ProcessRole role = processRoleService.findById(new ProcessResourceId(roleId)); + return removeRole(group, role); + } + + @Override + public Group removeRole(Group group, ProcessRole processRole) { + group.removeProcessRole(processRole); + return save(group); + } + protected String getGroupOwnerEmail(Group groupCase) { return userService.findById(groupCase.getOwnerId(), groupCase.getRealmId()).getEmail(); } diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/GroupService.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/GroupService.java index 81f5a20714..d2b4c8b3a4 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/GroupService.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/GroupService.java @@ -3,6 +3,7 @@ import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.Group; import com.netgrif.application.engine.objects.auth.dto.GroupSearchDto; +import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; import org.springframework.data.mongodb.core.query.Query; import com.querydsl.core.types.Predicate; import org.springframework.data.domain.Page; @@ -83,7 +84,14 @@ public interface GroupService { * @return the {@link Group} with the specified ID */ Group findById(String id); - + + /** + * Finds all groups matching the specified collection of IDs with pagination support. + * + * @param ids collection of group IDs to search for + * @param pageable pagination information + * @return a page of {@link Group}s that match the provided IDs + */ Page findAllByIds(Collection ids, Pageable pageable); /** @@ -142,11 +150,11 @@ public interface GroupService { * Adds a user to a group within a specific realm. * * @param userId ID of the user to add - * @param groupId ID of the group + * @param groupIdentifier identifier of the group * @param realmId ID of the realm * @return the updated {@link Group} */ - Group addUser(String userId, String groupId, String realmId); + Group addUser(String userId, String groupIdentifier, String realmId); /** * Adds a user to a group within a specific realm. @@ -176,11 +184,22 @@ public interface GroupService { */ Group addUser(AbstractUser user, Group group); + /** - * Removes a user from a group specified by identifier. + * Removes a user from a group within a specific realm. * - * @param user the user to remove - * @param groupIdentifier identifier of the target group + * @param userId the ID of the user to remove + * @param realmId the ID of the realm where the group exists + * @param groupIdentifier the unique identifier of the group + * @return the updated {@link Group} + */ + Group removeUser(String userId, String realmId, String groupIdentifier); + + /** + * Removes a user from a group specified by its unique identifier. + * + * @param user the user to be removed + * @param groupIdentifier the unique identifier of the target group * @return the updated {@link Group} */ Group removeUser(AbstractUser user, String groupIdentifier); @@ -188,8 +207,8 @@ public interface GroupService { /** * Removes a user from a specific group. * - * @param user the user to remove - * @param group the group to remove the user from + * @param user the user to be removed + * @param group the group from which the user will be removed * @return the updated {@link Group} */ Group removeUser(AbstractUser user, Group group); @@ -203,6 +222,13 @@ public interface GroupService { */ Page findByPredicate(Predicate predicate, Pageable pageable); + /** + * Finds groups matching the specified MongoDB query with pagination support. + * + * @param query the MongoDB query defining the criteria for searching groups + * @param pageable pagination information + * @return a page of {@link Group}s that match the query criteria + */ Page findByQuery(Query query, Pageable pageable); /** @@ -214,6 +240,16 @@ public interface GroupService { */ Group assignAuthority(String groupId, String authorityId); + + /** + * Removes a specific authority from a group. + * + * @param groupId the ID of the group from which the authority will be removed + * @param authorityId the ID of the authority to remove + * @return the updated {@link Group} object without the specified authority + */ + Group removeAuthority(String groupId, String authorityId); + /** * Adds a subgroup relationship between two groups. * @@ -250,6 +286,43 @@ public interface GroupService { */ Pair addSubgroup(Group parentGroup, Group childGroup); + + /** + * Removes a subgroup relationship between two groups by their IDs. + * + * @param parentGroupId the ID of the parent group + * @param childGroupId the ID of the child group + * @return a {@link Pair} containing both the updated parent and child {@link Group}s + */ + Pair removeSubgroup(String parentGroupId, String childGroupId); + + /** + * Removes a subgroup relationship between a parent group object and a child group by its ID. + * + * @param parentGroup the parent group object + * @param childGroupId the ID of the child group + * @return a {@link Pair} containing both the updated parent and child {@link Group}s + */ + Pair removeSubgroup(Group parentGroup, String childGroupId); + + /** + * Removes a subgroup relationship between a parent group by its ID and a child group object. + * + * @param parentGroupId the ID of the parent group + * @param childGroup the child group object + * @return a {@link Pair} containing both the updated parent and child {@link Group}s + */ + Pair removeSubgroup(String parentGroupId, Group childGroup); + + /** + * Removes a subgroup relationship between two group objects. + * + * @param parentGroup the parent group object + * @param childGroup the child group object + * @return a {@link Pair} containing both the updated parent and child {@link Group}s + */ + Pair removeSubgroup(Group parentGroup, Group childGroup); + /** * Retrieves all parent groups of a specified group. * @@ -307,4 +380,42 @@ public interface GroupService { * @return a page of {@link Group} objects that match the search criteria */ Page search(GroupSearchDto searchDto, Pageable pageable); + + /** + * Adds a role to a specified group. + * + * @param groupId the ID of the group to which the role will be added + * @param roleId the ID of the role to add to the group + * @return the updated {@link Group} object with the new role assigned + */ + Group addRole(String groupId, String roleId); + + + /** + * Assigns a specific process role to a group. + * + * @param group the {@link Group} to which the role will be added + * @param processRole the {@link ProcessRole} to assign to the group + * @return the updated {@link Group} object with the assigned role + */ + Group addRole(Group group, ProcessRole processRole); + + /** + * Removes a role from a specified group. + * + * @param groupId the ID of the group from which the role will be removed + * @param roleId the ID of the role to remove from the group + * @return the updated {@link Group} object without the specified role + */ + Group removeRole(String groupId, String roleId); + + + /** + * Removes a specified process role from a group. + * + * @param group the {@link Group} from which the role will be removed + * @param processRole the {@link ProcessRole} to remove from the group + * @return the updated {@link Group} object without the specified role + */ + Group removeRole(Group group, ProcessRole processRole); } From 91d2ff48f2d2175419241209fdcef0ada5ca2104 Mon Sep 17 00:00:00 2001 From: renczesstefan Date: Tue, 10 Feb 2026 14:58:34 +0100 Subject: [PATCH 02/25] [NAE-2286] Group API - Added `NewGroupDto` to support new group creation with validation constraints. - Renamed `GroupSearchDto` -> `SearchGroupDto` for consistent naming. - Renamed `assignAuthority` methods to `addAuthority` in `GroupService` for clarity. - Added `GroupController` to handle API operations for group management, including: - Retrieving a group by ID. - Searching for groups with search criteria. - Creating, updating, and deleting groups with proper authorization checks. --- .../logic/action/ActionDelegate.groovy | 5 +- .../engine/auth/web/GroupController.java | 133 ++++++++++++++++++ .../web/requestbodies/NewGroupRequest.java | 17 +++ .../orgstructure/web/GroupController.java | 112 +++++++-------- .../web/responsebodies/GroupsResource.java | 38 ++--- .../engine/objects/auth/dto/NewGroupDto.java | 17 +++ ...roupSearchDto.java => SearchGroupDto.java} | 2 +- .../engine/auth/service/GroupServiceImpl.java | 10 +- .../engine/auth/service/GroupService.java | 8 +- 9 files changed, 254 insertions(+), 88 deletions(-) create mode 100644 application-engine/src/main/java/com/netgrif/application/engine/auth/web/GroupController.java create mode 100644 application-engine/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/NewGroupRequest.java create mode 100644 nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/NewGroupDto.java rename nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/{GroupSearchDto.java => SearchGroupDto.java} (82%) 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 5933e296f9..7db108e947 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 @@ -49,7 +49,6 @@ import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole import com.netgrif.application.engine.objects.petrinet.domain.version.Version import com.netgrif.application.engine.objects.utils.MenuItemUtils import com.netgrif.application.engine.objects.workflow.domain.Case -import com.netgrif.application.engine.objects.workflow.domain.ProcessResourceId import com.netgrif.application.engine.objects.workflow.domain.Task import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.EventOutcome import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.caseoutcomes.ChangeCasePropertyOutcome @@ -2893,8 +2892,8 @@ class ActionDelegate { return groupService.removeUser(userId, realmId, groupId) } - Group assignAuthorityToGroup(String groupId, String authorityId) { - return groupService.assignAuthority(groupId, authorityId) + Group addAuthorityToGroup(String groupId, String authorityId) { + return groupService.addAuthority(groupId, authorityId) } Group removeAuthorityFromGroup(String groupId, String authorityId) { 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 0000000000..2aa939b4d8 --- /dev/null +++ b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/GroupController.java @@ -0,0 +1,133 @@ +package com.netgrif.application.engine.auth.web; + +import com.netgrif.application.engine.adapter.spring.common.web.responsebodies.ResponseMessage; +import com.netgrif.application.engine.auth.service.GroupService; +import com.netgrif.application.engine.auth.service.UserService; +import com.netgrif.application.engine.auth.web.requestbodies.NewGroupRequest; +import com.netgrif.application.engine.objects.auth.domain.AbstractUser; +import com.netgrif.application.engine.objects.auth.dto.SearchGroupDto; +import com.netgrif.application.engine.orgstructure.web.responsebodies.Group; +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.tags.Tag; +import jakarta.validation.constraints.Size; +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.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.*; + +@Slf4j +@RestController +@RequestMapping("api/groups") +@Tag(name = "GroupController") +@ConditionalOnProperty( + value = "netgrif.engine.group.web.enabled", + havingValue = "true", + matchIfMissing = true +) +@RequiredArgsConstructor +public class GroupController { + + private final GroupService groupService; + + private final UserService userService; + + @Operation(summary = "Retrieves group by its ID", description = "The endpoint receives ID of group and returns it the caller") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Group found"), + @ApiResponse(responseCode = "400", description = "Invalid group ID"), + @ApiResponse(responseCode = "404", description = "Group not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @GetMapping("/{id}") + public ResponseEntity getGroup(@PathVariable String id) { + if (id == null || id.isBlank()) { + return ResponseEntity.badRequest().build(); + } + try { + com.netgrif.application.engine.objects.auth.domain.Group group = groupService.findById(id); + return ResponseEntity.ok(new Group(group.getStringId(), group.getDisplayName())); + } catch (IllegalArgumentException e) { + return ResponseEntity.notFound().build(); + } catch (Exception e) { + return ResponseEntity.internalServerError().build(); + } + } + + @Operation(summary = "Search page of groups", description = "Retrieves a page of groups according to search params and pageable objects") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Page of groups found"), + @ApiResponse(responseCode = "500", description = "Internal server error"), + }) + @GetMapping("/search") + public ResponseEntity> searchGroups(SearchGroupDto searchDto, Pageable pageable) { + try { + Page groups = groupService.search(searchDto, pageable); + return ResponseEntity.ok(groups.map(group -> new Group(group.getStringId(), group.getDisplayName()))); + } catch (Exception e) { + return ResponseEntity.internalServerError().build(); + } + } + + @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @Operation(summary = "Creates new group", description = "Creates new group according to parameters in request body") + @ApiResponses(value = { + @ApiResponse(responseCode = "201", description = "Group created successfully"), + @ApiResponse(responseCode = "400", description = "Invalid group parameters"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @PostMapping + public ResponseEntity createGroup(@RequestBody NewGroupRequest newGroupRequest) { + if (newGroupRequest == null) { + return ResponseEntity.badRequest().build(); + } + AbstractUser user = userService.findById(newGroupRequest.getOwnerId(), null); + if (user == null) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ResponseMessage.createErrorMessage("User with id [%s] not found".formatted(newGroupRequest.getOwnerId()))); + } + groupService.create(newGroupRequest.getIdentifier(), newGroupRequest.getTitle(), user); + return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Group created successfully")); + } + + @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @Operation(summary = "Deletes group", description = "Deletes group according to incoming ID") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "Group deleted successfully"), + @ApiResponse(responseCode = "400", description = "Invalid group ID"), + @ApiResponse(responseCode = "404", description = "Group not found"), + @ApiResponse(responseCode = "500", description = "Internal server error") + }) + @DeleteMapping("/{id}") + public ResponseEntity deleteGroup(@PathVariable @Size(min = 24, max = 24) String id) { + try { + com.netgrif.application.engine.objects.auth.domain.Group group = groupService.findById(id); + groupService.delete(group); + return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Group with id [%s] deleted successfully".formatted(id))); + } catch (IllegalArgumentException e) { + return ResponseEntity.notFound().build(); + } catch (Exception e) { + return ResponseEntity.internalServerError().body(ResponseMessage.createErrorMessage("Failed to delete group with id [%s]".formatted(id))); + } + } + + @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @Operation(summary = "Updates group", description = "Updates group according to incoming parameters") + @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 + public ResponseEntity updateGroup(@RequestBody Group group) { + + return ResponseEntity.ok(group); + } +} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/NewGroupRequest.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/NewGroupRequest.java new file mode 100644 index 0000000000..07d1cd5461 --- /dev/null +++ b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/NewGroupRequest.java @@ -0,0 +1,17 @@ +package com.netgrif.application.engine.auth.web.requestbodies; + +import jakarta.validation.constraints.Size; +import lombok.Data; + +@Data +public class NewGroupRequest { + + @Size(min = 3, max = 255) + private String identifier; + + @Size(min = 3, max = 255) + private String title; + + @Size(min = 24, max = 24) + private String ownerId; +} 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 5fca05b109..9670d43b32 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 a6039cd6bd..c61b891c66 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/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/NewGroupDto.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/NewGroupDto.java new file mode 100644 index 0000000000..898e086e54 --- /dev/null +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/NewGroupDto.java @@ -0,0 +1,17 @@ +package com.netgrif.application.engine.objects.auth.dto; + +import jakarta.validation.constraints.Size; +import lombok.Data; + +@Data +public class NewGroupDto { + + @Size(min = 3, max = 255) + private String identifier; + + @Size(min = 3, max = 255) + private String title; + + @Size(min = 24, max = 24) + private String ownerId; +} diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/GroupSearchDto.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/SearchGroupDto.java similarity index 82% rename from nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/GroupSearchDto.java rename to nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/SearchGroupDto.java index a8560fabf1..d4a71eb47c 100644 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/GroupSearchDto.java +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/SearchGroupDto.java @@ -3,7 +3,7 @@ import lombok.Data; @Data -public class GroupSearchDto { +public class SearchGroupDto { private String fullText; private String realmId; } diff --git a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/GroupServiceImpl.java b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/GroupServiceImpl.java index 7c429e4c0c..d76b9b4761 100644 --- a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/GroupServiceImpl.java +++ b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/GroupServiceImpl.java @@ -7,7 +7,7 @@ import com.netgrif.application.engine.auth.repository.GroupRepository; import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.Group; -import com.netgrif.application.engine.objects.auth.dto.GroupSearchDto; +import com.netgrif.application.engine.objects.auth.dto.SearchGroupDto; import com.netgrif.application.engine.objects.common.ResourceNotFoundException; import com.netgrif.application.engine.objects.common.ResourceNotFoundExceptionCode; import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; @@ -304,7 +304,7 @@ public Page findAllFromRealmIn(Collection realmIds, Pageable page } @Override - public Group assignAuthority(String groupId, String authorityId) { + public Group addAuthority(String groupId, String authorityId) { Group group = findById(groupId); group.addAuthority(authorityService.getOne(authorityId)); return save(group); @@ -442,9 +442,9 @@ public String getGroupOwnerEmail(String groupId) { } @Override - public Page search(GroupSearchDto searchDto, Pageable pageable) { + public Page search(SearchGroupDto searchDto, Pageable pageable) { List filters = new ArrayList<>(); - if (searchDto.getFullText() != null && !searchDto.getFullText().isBlank()) { + if (searchDto != null && searchDto.getFullText() != null && !searchDto.getFullText().isBlank()) { Criteria criteria = new Criteria().orOperator( Criteria.where("identifier").regex(searchDto.getFullText(), "i"), Criteria.where("displayName").regex(searchDto.getFullText(), "i"), @@ -452,7 +452,7 @@ public Page search(GroupSearchDto searchDto, Pageable pageable) { ); filters.add(criteria); } - if (searchDto.getRealmId() != null && !searchDto.getRealmId().isBlank()) { + if (searchDto != null && searchDto.getRealmId() != null && !searchDto.getRealmId().isBlank()) { filters.add(Criteria.where("realmId").regex(searchDto.getRealmId(), "i")); } Query query = Query.query(filters.isEmpty() ? new Criteria() : new Criteria().andOperator(filters.toArray(new Criteria[0]))); diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/GroupService.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/GroupService.java index d2b4c8b3a4..77a04358ff 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/GroupService.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/GroupService.java @@ -2,7 +2,7 @@ import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.Group; -import com.netgrif.application.engine.objects.auth.dto.GroupSearchDto; +import com.netgrif.application.engine.objects.auth.dto.SearchGroupDto; import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; import org.springframework.data.mongodb.core.query.Query; import com.querydsl.core.types.Predicate; @@ -238,7 +238,7 @@ public interface GroupService { * @param authorityId ID of the authority to assign * @return the updated {@link Group} */ - Group assignAuthority(String groupId, String authorityId); + Group addAuthority(String groupId, String authorityId); /** @@ -375,11 +375,11 @@ public interface GroupService { /** * Searches for groups based on the provided search criteria and pageable details. * - * @param searchDto the search criteria encapsulated in a {@link GroupSearchDto} + * @param searchDto the search criteria encapsulated in a {@link SearchGroupDto} * @param pageable pagination information for the results * @return a page of {@link Group} objects that match the search criteria */ - Page search(GroupSearchDto searchDto, Pageable pageable); + Page search(SearchGroupDto searchDto, Pageable pageable); /** * Adds a role to a specified group. From 7fe3e106a88c4c355e176e7ec2b9848f3c50c08a Mon Sep 17 00:00:00 2001 From: renczesstefan Date: Tue, 10 Feb 2026 15:03:57 +0100 Subject: [PATCH 03/25] [NAE-2286] Group API - added GroupDto class --- .../engine/auth/web/GroupController.java | 3 ++- .../engine/objects/auth/dto/GroupDto.java | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/GroupDto.java 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 index 2aa939b4d8..9e2764fe79 100644 --- 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 @@ -5,6 +5,7 @@ import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.auth.web.requestbodies.NewGroupRequest; import com.netgrif.application.engine.objects.auth.domain.AbstractUser; +import com.netgrif.application.engine.objects.auth.dto.GroupDto; import com.netgrif.application.engine.objects.auth.dto.SearchGroupDto; import com.netgrif.application.engine.orgstructure.web.responsebodies.Group; import io.swagger.v3.oas.annotations.Operation; @@ -126,7 +127,7 @@ public ResponseEntity deleteGroup(@PathVariable @Size(min = 24, @ApiResponse(responseCode = "500", description = "Internal server error") }) @PutMapping - public ResponseEntity updateGroup(@RequestBody Group group) { + public ResponseEntity updateGroup(@RequestBody GroupDto group) { return ResponseEntity.ok(group); } diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/GroupDto.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/GroupDto.java new file mode 100644 index 0000000000..e7518d65b9 --- /dev/null +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/GroupDto.java @@ -0,0 +1,17 @@ +package com.netgrif.application.engine.objects.auth.dto; + +import lombok.Data; + +@Data +public class GroupDto { + + private String id; + + private String identifier; + + private String displayName; + + private String ownerId; + + private String ownerUsername; +} From 398601a948354de9ce02da368575f9ae5586a3c0 Mon Sep 17 00:00:00 2001 From: renczesstefan Date: Thu, 12 Feb 2026 06:52:17 +0100 Subject: [PATCH 04/25] [NAE-2286] Group API - Replaced `SearchGroupDto` with `GroupSearchRequestDto` in `GroupService` and `GroupController` for improved DTO consistency. - Introduced `CreateGroupRequestDto` and `UpdateGroupRequestDto` to support group creation and updates, respectively. - Added role management endpoints in `GroupController`: - Assign roles to a group (`/roles/assign`). - Add roles to a group (`/roles/add`). - Refactored the `createGroup` and `updateGroup` methods for better validation and error handling. - Removed the redundant `NewGroupRequest` class and its usage. - Added `SecurityRequirement` annotations to secure endpoints in `GroupController`. These changes improve the flexibility and security of group management services while maintaining a cleaner and more consistent codebase. --- .../engine/auth/web/GroupController.java | 161 ++++++++++++++++-- .../web/requestbodies/NewGroupRequest.java | 17 -- .../engine/objects/auth/dto/GroupDto.java | 17 -- .../engine/objects/auth/dto/NewGroupDto.java | 17 -- .../objects/auth/dto/SearchGroupDto.java | 9 - .../request/group/CreateGroupRequestDto.java | 6 + .../request/group/GroupSearchRequestDto.java | 10 ++ .../request/group/UpdateGroupRequestDto.java | 4 + .../dto/response/authority/AuthorityDto.java | 17 ++ .../objects/dto/response/group/GroupDto.java | 22 +++ .../dto/response/petrinet/ProcessRoleDto.java | 28 +++ .../engine/auth/service/GroupServiceImpl.java | 16 +- .../engine/auth/service/GroupService.java | 6 +- 13 files changed, 243 insertions(+), 87 deletions(-) delete mode 100644 application-engine/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/NewGroupRequest.java delete mode 100644 nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/GroupDto.java delete mode 100644 nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/NewGroupDto.java delete mode 100644 nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/SearchGroupDto.java create mode 100644 nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/request/group/CreateGroupRequestDto.java create mode 100644 nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/request/group/GroupSearchRequestDto.java create mode 100644 nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/request/group/UpdateGroupRequestDto.java create mode 100644 nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/authority/AuthorityDto.java create mode 100644 nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/group/GroupDto.java create mode 100644 nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/petrinet/ProcessRoleDto.java 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 index 9e2764fe79..7acd477d34 100644 --- 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 @@ -1,16 +1,20 @@ 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.UserService; -import com.netgrif.application.engine.auth.web.requestbodies.NewGroupRequest; import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.objects.auth.dto.GroupDto; -import com.netgrif.application.engine.objects.auth.dto.SearchGroupDto; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; +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.workflow.domain.ProcessResourceId; import com.netgrif.application.engine.orgstructure.web.responsebodies.Group; 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.constraints.Size; import lombok.RequiredArgsConstructor; @@ -19,11 +23,15 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.http.HttpStatus; -import org.springframework.http.HttpStatusCode; +import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; +import java.util.Set; +import java.util.stream.Collectors; + @Slf4j @RestController @RequestMapping("api/groups") @@ -40,7 +48,9 @@ public class GroupController { private final UserService userService; - @Operation(summary = "Retrieves group by its ID", description = "The endpoint receives ID of group and returns it the caller") + private final ProcessRoleService processRoleService; + + @Operation(summary = "Retrieves group by its ID", description = "The endpoint receives ID of group and returns it the caller", security = {@SecurityRequirement(name = "X-Auth-Token")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Group found"), @ApiResponse(responseCode = "400", description = "Invalid group ID"), @@ -62,13 +72,13 @@ public ResponseEntity getGroup(@PathVariable String id) { } } - @Operation(summary = "Search page of groups", description = "Retrieves a page of groups according to search params and pageable objects") + @Operation(summary = "Search page of groups", description = "Retrieves a page of groups according to search params and pageable objects", security = {@SecurityRequirement(name = "X-Auth-Token")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Page of groups found"), @ApiResponse(responseCode = "500", description = "Internal server error"), }) @GetMapping("/search") - public ResponseEntity> searchGroups(SearchGroupDto searchDto, Pageable pageable) { + public ResponseEntity> searchGroups(GroupSearchRequestDto searchDto, Pageable pageable) { try { Page groups = groupService.search(searchDto, pageable); return ResponseEntity.ok(groups.map(group -> new Group(group.getStringId(), group.getDisplayName()))); @@ -78,27 +88,27 @@ public ResponseEntity> searchGroups(SearchGroupDto searchDto, Pageab } @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") - @Operation(summary = "Creates new group", description = "Creates new group according to parameters in request body") + @Operation(summary = "Creates new group", description = "Creates new group according to parameters in request body", security = {@SecurityRequirement(name = "X-Auth-Token")}) @ApiResponses(value = { @ApiResponse(responseCode = "201", description = "Group created successfully"), @ApiResponse(responseCode = "400", description = "Invalid group parameters"), @ApiResponse(responseCode = "500", description = "Internal server error") }) @PostMapping - public ResponseEntity createGroup(@RequestBody NewGroupRequest newGroupRequest) { + public ResponseEntity createGroup(@RequestBody CreateGroupRequestDto newGroupRequest) { if (newGroupRequest == null) { return ResponseEntity.badRequest().build(); } - AbstractUser user = userService.findById(newGroupRequest.getOwnerId(), null); + AbstractUser user = userService.findById(newGroupRequest.ownerId(), null); if (user == null) { - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ResponseMessage.createErrorMessage("User with id [%s] not found".formatted(newGroupRequest.getOwnerId()))); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(ResponseMessage.createErrorMessage("User with id [%s] not found".formatted(newGroupRequest.ownerId()))); } - groupService.create(newGroupRequest.getIdentifier(), newGroupRequest.getTitle(), user); + groupService.create(newGroupRequest.identifier(), newGroupRequest.displayName(), user); return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Group created successfully")); } @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") - @Operation(summary = "Deletes group", description = "Deletes group according to incoming ID") + @Operation(summary = "Deletes group", description = "Deletes group according to incoming ID", security = {@SecurityRequirement(name = "X-Auth-Token")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Group deleted successfully"), @ApiResponse(responseCode = "400", description = "Invalid group ID"), @@ -119,7 +129,7 @@ public ResponseEntity deleteGroup(@PathVariable @Size(min = 24, } @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") - @Operation(summary = "Updates group", description = "Updates group according to incoming parameters") + @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"), @@ -127,8 +137,127 @@ public ResponseEntity deleteGroup(@PathVariable @Size(min = 24, @ApiResponse(responseCode = "500", description = "Internal server error") }) @PutMapping - public ResponseEntity updateGroup(@RequestBody GroupDto group) { + public ResponseEntity updateGroup(@RequestBody UpdateGroupRequestDto groupUpdate) { + try { + com.netgrif.application.engine.objects.auth.domain.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("@authorizationService.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")}) + @PatchMapping(value = "/{id}/roles/assign", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @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") + }) + public ResponseEntity assignRolesToUser(@PathVariable("id") String groupId, @RequestBody Set roleIds) { + try { + com.netgrif.application.engine.objects.auth.domain.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("@authorizationService.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")}) + @PatchMapping(value = "/{id}/roles/add", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @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") + }) + public ResponseEntity addRolesToUser(@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!")); + } + } - return ResponseEntity.ok(group); + @PreAuthorize("@authorizationService.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")}) + @PatchMapping(value = "/{id}/roles/revoke", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @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") + }) + public ResponseEntity revokeRolesFromUser(@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("@authorizationService.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")}) + @PatchMapping(value = "/{id}/authorities/add", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @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") + }) + public ResponseEntity addAuthorityToUser(@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("@authorizationService.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")}) + @PatchMapping(value = "/{id}/authorities/revoke", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @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") + }) + public ResponseEntity revokeAuthorityFromUser(@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!")); + } } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/NewGroupRequest.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/NewGroupRequest.java deleted file mode 100644 index 07d1cd5461..0000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/NewGroupRequest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.netgrif.application.engine.auth.web.requestbodies; - -import jakarta.validation.constraints.Size; -import lombok.Data; - -@Data -public class NewGroupRequest { - - @Size(min = 3, max = 255) - private String identifier; - - @Size(min = 3, max = 255) - private String title; - - @Size(min = 24, max = 24) - private String ownerId; -} diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/GroupDto.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/GroupDto.java deleted file mode 100644 index e7518d65b9..0000000000 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/GroupDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.netgrif.application.engine.objects.auth.dto; - -import lombok.Data; - -@Data -public class GroupDto { - - private String id; - - private String identifier; - - private String displayName; - - private String ownerId; - - private String ownerUsername; -} diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/NewGroupDto.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/NewGroupDto.java deleted file mode 100644 index 898e086e54..0000000000 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/NewGroupDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.netgrif.application.engine.objects.auth.dto; - -import jakarta.validation.constraints.Size; -import lombok.Data; - -@Data -public class NewGroupDto { - - @Size(min = 3, max = 255) - private String identifier; - - @Size(min = 3, max = 255) - private String title; - - @Size(min = 24, max = 24) - private String ownerId; -} diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/SearchGroupDto.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/SearchGroupDto.java deleted file mode 100644 index d4a71eb47c..0000000000 --- a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/auth/dto/SearchGroupDto.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.netgrif.application.engine.objects.auth.dto; - -import lombok.Data; - -@Data -public class SearchGroupDto { - private String fullText; - private String realmId; -} diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/request/group/CreateGroupRequestDto.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/request/group/CreateGroupRequestDto.java new file mode 100644 index 0000000000..c81d990ea0 --- /dev/null +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/request/group/CreateGroupRequestDto.java @@ -0,0 +1,6 @@ +package com.netgrif.application.engine.objects.dto.request.group; + +import java.io.Serializable; + +public record CreateGroupRequestDto(String displayName, String realmId, String identifier, String ownerId) implements Serializable { +} diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/request/group/GroupSearchRequestDto.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/request/group/GroupSearchRequestDto.java new file mode 100644 index 0000000000..8095146c9b --- /dev/null +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/request/group/GroupSearchRequestDto.java @@ -0,0 +1,10 @@ +package com.netgrif.application.engine.objects.dto.request.group; + +import com.netgrif.application.engine.objects.auth.domain.Group; + +import java.io.Serializable; + +/** + * DTO for {@link Group} search request + */ +public record GroupSearchRequestDto(String fullText, String realmId) implements Serializable { } diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/request/group/UpdateGroupRequestDto.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/request/group/UpdateGroupRequestDto.java new file mode 100644 index 0000000000..d66181b4f1 --- /dev/null +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/request/group/UpdateGroupRequestDto.java @@ -0,0 +1,4 @@ +package com.netgrif.application.engine.objects.dto.request.group; + +public record UpdateGroupRequestDto(String id, String identifier, String displayName) { +} diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/authority/AuthorityDto.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/authority/AuthorityDto.java new file mode 100644 index 0000000000..bea583d166 --- /dev/null +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/authority/AuthorityDto.java @@ -0,0 +1,17 @@ +package com.netgrif.application.engine.objects.dto.response.authority; + +import com.netgrif.application.engine.objects.auth.domain.Authority; +import org.bson.types.ObjectId; + +import java.io.Serializable; + +/** + * DTO for {@link Authority} + */ +public record AuthorityDto(ObjectId id, String name) implements Serializable { + + public static AuthorityDto fromAuthority(Authority authority) { + return new AuthorityDto(authority.get_id(), authority.getName()); + } + +} \ No newline at end of file diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/group/GroupDto.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/group/GroupDto.java new file mode 100644 index 0000000000..599b5cb548 --- /dev/null +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/group/GroupDto.java @@ -0,0 +1,22 @@ +package com.netgrif.application.engine.objects.dto.response.group; + +import com.netgrif.application.engine.objects.auth.domain.Group; +import com.netgrif.application.engine.objects.dto.response.authority.AuthorityDto; +import com.netgrif.application.engine.objects.dto.response.petrinet.ProcessRoleDto; + +import java.io.Serializable; +import java.util.Locale; +import java.util.Set; +import java.util.stream.Collectors; + +public record GroupDto(String id, String displayName, String identifier, String ownerUsername, + Set authoritySet, Set processRoles) implements Serializable { + + public static GroupDto fromGroup(Group group, Locale locale) { + return new GroupDto(group.getStringId(), group.getDisplayName(), group.getIdentifier(), group.getOwnerUsername(), + group.getAuthoritySet().stream().map(AuthorityDto::fromAuthority).collect(Collectors.toSet()), + group.getProcessRoles().stream().map(processRole -> new ProcessRoleDto(processRole, locale)).collect(Collectors.toSet()) + ); + } + +} diff --git a/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/petrinet/ProcessRoleDto.java b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/petrinet/ProcessRoleDto.java new file mode 100644 index 0000000000..5c820c7691 --- /dev/null +++ b/nae-object-library/src/main/java/com/netgrif/application/engine/objects/dto/response/petrinet/ProcessRoleDto.java @@ -0,0 +1,28 @@ +package com.netgrif.application.engine.objects.dto.response.petrinet; + +import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; + +import java.io.Serializable; +import java.util.Locale; + +public record ProcessRoleDto(String stringId, String name, String description, String importId, String netImportId, + String netVersion, String netStringId, boolean global) implements Serializable { + + /** + * This constructor doesn't set attributes regarding the Petri net. + *

+ * Use the ProcessRoleFactory to create instances that have these attributes set. + */ + public ProcessRoleDto(ProcessRole role, Locale locale) { + this(role.getStringId(), role.getLocalisedName(locale), role.getDescription(), role.getImportId(), null, null, null, role.isGlobal()); + } + + public ProcessRoleDto(ProcessRole role, Locale locale, String netImportId, + String netVersion, String netStringId) { + this(role.getStringId(), role.getLocalisedName(locale), role.getDescription(), role.getImportId(),netImportId, netVersion, netStringId, role.isGlobal()); + } + + public ProcessRoleDto(String id, String name, String description, boolean global) { + this(id, name, description, null, null, null, null, global); + } +} diff --git a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/GroupServiceImpl.java b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/GroupServiceImpl.java index d76b9b4761..fe27d0adaa 100644 --- a/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/GroupServiceImpl.java +++ b/nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/GroupServiceImpl.java @@ -7,9 +7,9 @@ import com.netgrif.application.engine.auth.repository.GroupRepository; import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.Group; -import com.netgrif.application.engine.objects.auth.dto.SearchGroupDto; import com.netgrif.application.engine.objects.common.ResourceNotFoundException; import com.netgrif.application.engine.objects.common.ResourceNotFoundExceptionCode; +import com.netgrif.application.engine.objects.dto.request.group.GroupSearchRequestDto; import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; import com.netgrif.application.engine.objects.workflow.domain.ProcessResourceId; import org.springframework.context.annotation.Lazy; @@ -442,18 +442,18 @@ public String getGroupOwnerEmail(String groupId) { } @Override - public Page search(SearchGroupDto searchDto, Pageable pageable) { + public Page search(GroupSearchRequestDto searchDto, Pageable pageable) { List filters = new ArrayList<>(); - if (searchDto != null && searchDto.getFullText() != null && !searchDto.getFullText().isBlank()) { + if (searchDto != null && searchDto.fullText() != null && !searchDto.fullText().isBlank()) { Criteria criteria = new Criteria().orOperator( - Criteria.where("identifier").regex(searchDto.getFullText(), "i"), - Criteria.where("displayName").regex(searchDto.getFullText(), "i"), - Criteria.where("ownerUsername").regex(searchDto.getFullText(), "i") + Criteria.where("identifier").regex(searchDto.fullText(), "i"), + Criteria.where("displayName").regex(searchDto.fullText(), "i"), + Criteria.where("ownerUsername").regex(searchDto.fullText(), "i") ); filters.add(criteria); } - if (searchDto != null && searchDto.getRealmId() != null && !searchDto.getRealmId().isBlank()) { - filters.add(Criteria.where("realmId").regex(searchDto.getRealmId(), "i")); + if (searchDto != null && searchDto.realmId() != null && !searchDto.realmId().isBlank()) { + filters.add(Criteria.where("realmId").regex(searchDto.realmId(), "i")); } Query query = Query.query(filters.isEmpty() ? new Criteria() : new Criteria().andOperator(filters.toArray(new Criteria[0]))); long count = mongoTemplate.count(query, Group.class); diff --git a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/GroupService.java b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/GroupService.java index 77a04358ff..5c913bab1b 100644 --- a/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/GroupService.java +++ b/nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/GroupService.java @@ -2,7 +2,7 @@ import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.Group; -import com.netgrif.application.engine.objects.auth.dto.SearchGroupDto; +import com.netgrif.application.engine.objects.dto.request.group.GroupSearchRequestDto; import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; import org.springframework.data.mongodb.core.query.Query; import com.querydsl.core.types.Predicate; @@ -375,11 +375,11 @@ public interface GroupService { /** * Searches for groups based on the provided search criteria and pageable details. * - * @param searchDto the search criteria encapsulated in a {@link SearchGroupDto} + * @param searchDto the search criteria encapsulated in a {@link GroupSearchRequestDto} * @param pageable pagination information for the results * @return a page of {@link Group} objects that match the search criteria */ - Page search(SearchGroupDto searchDto, Pageable pageable); + Page search(GroupSearchRequestDto searchDto, Pageable pageable); /** * Adds a role to a specified group. From e04c49c4accb119c540aad1a4cbbf7699e204d8f Mon Sep 17 00:00:00 2001 From: renczesstefan Date: Thu, 12 Feb 2026 06:53:18 +0100 Subject: [PATCH 05/25] [NAE-2286] Group API - resolved unused import --- .../netgrif/application/engine/auth/web/GroupController.java | 2 -- 1 file changed, 2 deletions(-) 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 index 7acd477d34..194fe1c258 100644 --- 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 @@ -5,7 +5,6 @@ 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.LoggedUser; 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; @@ -26,7 +25,6 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; import java.util.Set; From 69102305078b4c9d5077fa4ab284f6788e95dbf2 Mon Sep 17 00:00:00 2001 From: renczesstefan Date: Thu, 12 Feb 2026 07:07:24 +0100 Subject: [PATCH 06/25] [NAE-2286] Group API - updated return types --- .../engine/auth/web/GroupController.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) 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 index 194fe1c258..19c98b2e0a 100644 --- 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 @@ -5,11 +5,12 @@ 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.Group; 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 com.netgrif.application.engine.orgstructure.web.responsebodies.Group; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; @@ -27,6 +28,7 @@ import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; +import java.util.Locale; import java.util.Set; import java.util.stream.Collectors; @@ -56,13 +58,13 @@ public class GroupController { @ApiResponse(responseCode = "500", description = "Internal server error") }) @GetMapping("/{id}") - public ResponseEntity getGroup(@PathVariable String id) { + public ResponseEntity getGroup(@PathVariable String id, Locale locale) { if (id == null || id.isBlank()) { return ResponseEntity.badRequest().build(); } try { - com.netgrif.application.engine.objects.auth.domain.Group group = groupService.findById(id); - return ResponseEntity.ok(new Group(group.getStringId(), group.getDisplayName())); + Group group = groupService.findById(id); + return ResponseEntity.ok(GroupDto.fromGroup(group, locale)); } catch (IllegalArgumentException e) { return ResponseEntity.notFound().build(); } catch (Exception e) { @@ -76,10 +78,10 @@ public ResponseEntity getGroup(@PathVariable String id) { @ApiResponse(responseCode = "500", description = "Internal server error"), }) @GetMapping("/search") - public ResponseEntity> searchGroups(GroupSearchRequestDto searchDto, Pageable pageable) { + public ResponseEntity> searchGroups(GroupSearchRequestDto searchDto, Pageable pageable, Locale locale) { try { - Page groups = groupService.search(searchDto, pageable); - return ResponseEntity.ok(groups.map(group -> new Group(group.getStringId(), group.getDisplayName()))); + Page groups = groupService.search(searchDto, pageable); + return ResponseEntity.ok(groups.map(group -> GroupDto.fromGroup(group, locale))); } catch (Exception e) { return ResponseEntity.internalServerError().build(); } @@ -116,7 +118,7 @@ public ResponseEntity createGroup(@RequestBody CreateGroupReque @DeleteMapping("/{id}") public ResponseEntity deleteGroup(@PathVariable @Size(min = 24, max = 24) String id) { try { - com.netgrif.application.engine.objects.auth.domain.Group group = groupService.findById(id); + Group group = groupService.findById(id); groupService.delete(group); return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Group with id [%s] deleted successfully".formatted(id))); } catch (IllegalArgumentException e) { @@ -137,7 +139,7 @@ public ResponseEntity deleteGroup(@PathVariable @Size(min = 24, @PutMapping public ResponseEntity updateGroup(@RequestBody UpdateGroupRequestDto groupUpdate) { try { - com.netgrif.application.engine.objects.auth.domain.Group group = groupService.findById(groupUpdate.id()); + Group group = groupService.findById(groupUpdate.id()); if (groupUpdate.identifier() != null) { group.setIdentifier(groupUpdate.identifier()); } @@ -164,7 +166,7 @@ public ResponseEntity updateGroup(@RequestBody UpdateGroupReque }) public ResponseEntity assignRolesToUser(@PathVariable("id") String groupId, @RequestBody Set roleIds) { try { - com.netgrif.application.engine.objects.auth.domain.Group group = groupService.findById(groupId); + 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)); From 4a66d8c9f80cc88d15596711f428d8f71cc552c0 Mon Sep 17 00:00:00 2001 From: renczesstefan Date: Thu, 12 Feb 2026 14:16:09 +0100 Subject: [PATCH 07/25] [NAE-2286] Group API - updated validation dependencies --- application-engine/pom.xml | 11 ++++++----- .../application/engine/auth/web/GroupController.java | 4 +++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/application-engine/pom.xml b/application-engine/pom.xml index c9a9e937a5..20f887dc7e 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/java/com/netgrif/application/engine/auth/web/GroupController.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/GroupController.java index 19c98b2e0a..a46a7423e0 100644 --- 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 @@ -16,6 +16,7 @@ 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 jakarta.validation.constraints.Size; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -26,6 +27,7 @@ import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.Locale; @@ -116,7 +118,7 @@ public ResponseEntity createGroup(@RequestBody CreateGroupReque @ApiResponse(responseCode = "500", description = "Internal server error") }) @DeleteMapping("/{id}") - public ResponseEntity deleteGroup(@PathVariable @Size(min = 24, max = 24) String id) { + public ResponseEntity deleteGroup(@PathVariable @Valid @Size(min = 24, max = 24) String id) { try { Group group = groupService.findById(id); groupService.delete(group); From 5482d694c3ec8ea6e2c20f105fffac45d91cacba Mon Sep 17 00:00:00 2001 From: renczesstefan Date: Fri, 13 Feb 2026 12:52:33 +0100 Subject: [PATCH 08/25] Rename and update AuthorizationService to AuthorizationServiceImpl Replaced references to AuthorizationService with AuthorizationServiceImpl across the application for consistency. Updated method and class names, adjusted related documentation, and ensured all `@PreAuthorize` annotations now reference the renamed implementation. --- .../interfaces/IAuthorizationService.java | 5 ---- .../engine/auth/web/GroupController.java | 24 +++++++++---------- .../engine/auth/web/UserController.java | 4 ++-- .../engine/elastic/web/ElasticController.java | 4 ++-- .../petrinet/web/PetriNetController.java | 4 ++-- .../petrinet/web/ProcessRoleController.java | 2 +- .../workflow/web/WorkflowController.java | 2 +- .../auth/service/AuthorizationService.html | 2 +- .../class-use/AuthorizationService.html | 8 +++---- .../class-use/IAuthorizationService.html | 6 ++--- .../service/AuthorizationServiceImpl.java | 3 +-- .../auth/service/AuthorizationService.java | 5 ++++ 12 files changed, 34 insertions(+), 35 deletions(-) delete mode 100644 application-engine/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorizationService.java rename application-engine/src/main/java/com/netgrif/application/engine/auth/service/AuthorizationService.java => nae-user-ce/src/main/java/com/netgrif/application/engine/auth/service/AuthorizationServiceImpl.java (81%) create mode 100644 nae-user-common/src/main/java/com/netgrif/application/engine/auth/service/AuthorizationService.java 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 81feafc98d..0000000000 --- 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/web/GroupController.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/GroupController.java index a46a7423e0..4ccb8e88ab 100644 --- 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 @@ -89,7 +89,7 @@ public ResponseEntity> searchGroups(GroupSearchRequestDto searchD } } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") @Operation(summary = "Creates new group", description = "Creates new group according to parameters in request body", security = {@SecurityRequirement(name = "X-Auth-Token")}) @ApiResponses(value = { @ApiResponse(responseCode = "201", description = "Group created successfully"), @@ -109,7 +109,7 @@ public ResponseEntity createGroup(@RequestBody CreateGroupReque return ResponseEntity.ok(ResponseMessage.createSuccessMessage("Group created successfully")); } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@authorizationServiceImpl.hasAuthority('ADMIN')") @Operation(summary = "Deletes group", description = "Deletes group according to incoming ID", security = {@SecurityRequirement(name = "X-Auth-Token")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Group deleted successfully"), @@ -130,7 +130,7 @@ public ResponseEntity deleteGroup(@PathVariable @Valid @Size(mi } } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @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"), @@ -157,7 +157,7 @@ public ResponseEntity updateGroup(@RequestBody UpdateGroupReque } } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @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")}) @PatchMapping(value = "/{id}/roles/assign", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ApiResponses(value = { @@ -166,7 +166,7 @@ public ResponseEntity updateGroup(@RequestBody UpdateGroupReque @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), @ApiResponse(responseCode = "500", description = "Internal server error") }) - public ResponseEntity assignRolesToUser(@PathVariable("id") String groupId, @RequestBody Set roleIds) { + 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())); @@ -179,7 +179,7 @@ public ResponseEntity assignRolesToUser(@PathVariable("id") Str } } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @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")}) @PatchMapping(value = "/{id}/roles/add", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ApiResponses(value = { @@ -188,7 +188,7 @@ public ResponseEntity assignRolesToUser(@PathVariable("id") Str @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), @ApiResponse(responseCode = "500", description = "Internal server error") }) - public ResponseEntity addRolesToUser(@PathVariable("id") String groupId, @RequestBody Set roleIds) { + 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); @@ -200,7 +200,7 @@ public ResponseEntity addRolesToUser(@PathVariable("id") String } } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @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")}) @PatchMapping(value = "/{id}/roles/revoke", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ApiResponses(value = { @@ -209,7 +209,7 @@ public ResponseEntity addRolesToUser(@PathVariable("id") String @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), @ApiResponse(responseCode = "500", description = "Internal server error") }) - public ResponseEntity revokeRolesFromUser(@PathVariable("id") String groupId, @RequestBody Set roleIds) { + 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); @@ -221,7 +221,7 @@ public ResponseEntity revokeRolesFromUser(@PathVariable("id") S } } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @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")}) @PatchMapping(value = "/{id}/authorities/add", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ApiResponses(value = { @@ -230,7 +230,7 @@ public ResponseEntity revokeRolesFromUser(@PathVariable("id") S @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), @ApiResponse(responseCode = "500", description = "Internal server error") }) - public ResponseEntity addAuthorityToUser(@PathVariable("id") String groupId, @RequestBody Set authorityIds) { + 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); @@ -242,7 +242,7 @@ public ResponseEntity addAuthorityToUser(@PathVariable("id") St } } - @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") + @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")}) @PatchMapping(value = "/{id}/authorities/revoke", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) @ApiResponses(value = { 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 e03c3f168e..c82ce77007 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 @@ -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")}) 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 5cc4860125..f413ae1c60 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/petrinet/web/PetriNetController.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index d4b062650c..2949747084 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 77cac9d06f..7d10c6f9f8 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/workflow/web/WorkflowController.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java index 7222b4ae96..8a7aa04a8f 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/docs/javadoc/com/netgrif/application/engine/auth/service/AuthorizationService.html b/docs/javadoc/com/netgrif/application/engine/auth/service/AuthorizationService.html index 4561d141e4..83e26e6c0e 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 7ca1e28b96..aba16657ac 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 @@