From 0179f7a9ad31a2f9cc22832f277f333c8d4194ba Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Fri, 29 Apr 2022 10:17:52 +0200 Subject: [PATCH 01/68] [NAE-1617] Refactor Authority - refactor Authority.java - implemented domain and authority constants --- .../engine/auth/domain/Authority.java | 53 +++++++++++++------ 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java index 60dc163827..d19a8e0405 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java @@ -16,14 +16,43 @@ public class Authority implements GrantedAuthority { public static final long serialVersionUID = 2839744057647464485L; - public static final String PERMISSION = "PERM_"; - public static final String ROLE = "ROLE_"; - - public static final String admin = ROLE + "ADMIN"; - public static final String systemAdmin = ROLE + "SYSTEMADMIN"; - public static final String user = ROLE + "USER"; - public static final String anonymous = ROLE + "ANONYMOUS"; - +// public static final String PERMISSION = "PERM_"; +// public static final String ROLE = "ROLE_"; +// +// public static final String admin = ROLE + "ADMIN"; +// public static final String systemAdmin = ROLE + "SYSTEMADMIN"; +// public static final String user = ROLE + "USER"; +// public static final String anonymous = ROLE + "ANONYMOUS"; + + /** + * Domain constants + * */ + public static final String ADMIN = "*"; + public static final String PROCESS = "PROCESS"; + public static final String FILTER = "FILTER"; + public static final String USER = "USER"; + public static final String GROUP = "GROUP"; + public static final String ROLE = "ROLE"; + public static final String AUTHORITY = "AUTHORITY"; + + /** + * Authority objects constants + * */ + public static final String processUpload = "PROCESS.UPLOAD"; + public static final String processDelete = "PROCESS.DELETE"; + public static final String filterUpload = "FILTER.UPLOAD"; + public static final String filterDelete = "FILTER.DELETE"; + public static final String userCreate = "USER.CREATE"; + public static final String userDelete = "USER.DELETE"; + public static final String userEdit = "USER.EDIT"; + public static final String groupCreate = "GROUP.CREATE"; + public static final String groupDelete = "GROUP.DELETE"; + public static final String groupAddUser = "GROUP.ADD_USER"; + public static final String groupRemoveUser = "GROUP.REMOVE_USER"; + public static final String roleCreate = "ROLE.CREATE"; + public static final String roleDelete = "ROLE.DELETE"; + public static final String authorityCreate = "AUTHORITY.CREATE"; + public static final String authorityDelete = "AUTHORITY.DELETE"; @Id @Getter @@ -47,14 +76,6 @@ public Authority(String name) { this.name = name; } - public static Authority createRole(String name) { - return new Authority(ROLE + name); - } - - public static Authority createPermission(String name) { - return new Authority(PERMISSION + name); - } - public void addUser(IUser user) { users.add(user.getStringId()); } From 90d33413f50d537cd9c46713840b2d26518d2c5b Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Fri, 29 Apr 2022 10:35:11 +0200 Subject: [PATCH 02/68] [NAE-1617] Refactor Authority - refactor AuthorityService - implemented enum for authorities --- .../engine/auth/domain/Authority.java | 41 +++++++++++-------- .../engine/auth/domain/AuthorityEnum.java | 22 ++++++++++ .../engine/auth/service/AuthorityService.java | 20 --------- .../service/interfaces/IAuthorityService.java | 8 ---- 4 files changed, 45 insertions(+), 46 deletions(-) create mode 100644 src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java index d19a8e0405..08245ee0c2 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java @@ -9,6 +9,9 @@ import org.springframework.security.core.GrantedAuthority; import javax.validation.constraints.NotNull; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Set; @Document @@ -35,24 +38,26 @@ public class Authority implements GrantedAuthority { public static final String ROLE = "ROLE"; public static final String AUTHORITY = "AUTHORITY"; - /** - * Authority objects constants - * */ - public static final String processUpload = "PROCESS.UPLOAD"; - public static final String processDelete = "PROCESS.DELETE"; - public static final String filterUpload = "FILTER.UPLOAD"; - public static final String filterDelete = "FILTER.DELETE"; - public static final String userCreate = "USER.CREATE"; - public static final String userDelete = "USER.DELETE"; - public static final String userEdit = "USER.EDIT"; - public static final String groupCreate = "GROUP.CREATE"; - public static final String groupDelete = "GROUP.DELETE"; - public static final String groupAddUser = "GROUP.ADD_USER"; - public static final String groupRemoveUser = "GROUP.REMOVE_USER"; - public static final String roleCreate = "ROLE.CREATE"; - public static final String roleDelete = "ROLE.DELETE"; - public static final String authorityCreate = "AUTHORITY.CREATE"; - public static final String authorityDelete = "AUTHORITY.DELETE"; +// /** +// * Authority objects constants +// * */ +// public static final String processUpload = "PROCESS.UPLOAD"; +// public static final String processDelete = "PROCESS.DELETE"; +// public static final String filterUpload = "FILTER.UPLOAD"; +// public static final String filterDelete = "FILTER.DELETE"; +// public static final String userCreate = "USER.CREATE"; +// public static final String userDelete = "USER.DELETE"; +// public static final String userEdit = "USER.EDIT"; +// public static final String groupCreate = "GROUP.CREATE"; +// public static final String groupDelete = "GROUP.DELETE"; +// public static final String groupAddUser = "GROUP.ADD_USER"; +// public static final String groupRemoveUser = "GROUP.REMOVE_USER"; +// public static final String roleCreate = "ROLE.CREATE"; +// public static final String roleDelete = "ROLE.DELETE"; +// public static final String authorityCreate = "AUTHORITY.CREATE"; +// public static final String authorityDelete = "AUTHORITY.DELETE"; + + public static final List allAuthorities = new ArrayList<>(List.of(AuthorityEnum.values())); @Id @Getter diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java new file mode 100644 index 0000000000..076470140a --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java @@ -0,0 +1,22 @@ +package com.netgrif.application.engine.auth.domain; + +public enum AuthorityEnum { + PROCESS_UPLOAD("PROCESS.UPLOAD"), + PROCESS_DELETE("PROCESS.DELETE"), + FILTER_UPLOAD("FILTER.UPLOAD"), + FILTER_DELETE("FILTER.DELETE"), + USER_CREATE("USER.CREATE"), + USER_DELETE("USER.DELETE"), + USER_EDIT("USER.EDIT"), + GROUP_CREATE("GROUP.CREATE"), + GROUP_DELETE("GROUP.DELETE"), + GROUP_ADD_USER("GROUP.ADD_USER"), + GROUP_REMOVE_USER("GROUP.REMOVE_USER"), + ROLE_CREATE("ROLE.CREATE"), + ROLE_DELETE("ROLE.DELETE"), + AUTHORITY_CREATE("AUTHORITY.CREATE"), + AUTHORITY_DELETE("AUTHORITY.DELETE"); + + AuthorityEnum(String s) { + } +} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index 59e6ff0b61..85f86eafd0 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -30,26 +30,6 @@ public Authority getOrCreate(String name) { return authority; } - @Override - public Authority getOrCreatePermission(String name) { - return getOrCreate(Authority.PERMISSION + name); - } - - @Override - public Authority getOrCreateRole(String name) { - return getOrCreate(Authority.ROLE + name); - } - - @Override - public List getAllPermissions() { - return repository.findAllByNameStartsWith(Authority.PERMISSION); - } - - @Override - public List getAllRoles() { - return repository.findAllByNameStartsWith(Authority.ROLE); - } - public Authority getOne(String id) { Optional authority = repository.findById(id); if (!authority.isPresent()) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java index 3fd98af7b3..615a34abfa 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java @@ -10,13 +10,5 @@ public interface IAuthorityService { Authority getOrCreate(String name); - Authority getOrCreatePermission(String name); - - Authority getOrCreateRole(String name); - - List getAllPermissions(); - - List getAllRoles(); - Authority getOne(String id); } \ No newline at end of file From a50fd0258a49ac55dfdc7796b91e4e4abc0b6e8b Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Fri, 29 Apr 2022 10:40:15 +0200 Subject: [PATCH 03/68] [NAE-1617] Refactor Authority - removed authority domains from Authority and created enum for it --- .../engine/auth/domain/Authority.java | 40 ------------------- .../auth/domain/AuthorityDomainEnum.java | 14 +++++++ .../engine/auth/domain/AuthorityEnum.java | 2 +- 3 files changed, 15 insertions(+), 41 deletions(-) create mode 100644 src/main/java/com/netgrif/application/engine/auth/domain/AuthorityDomainEnum.java diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java index 08245ee0c2..d66dbb455b 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java @@ -19,46 +19,6 @@ public class Authority implements GrantedAuthority { public static final long serialVersionUID = 2839744057647464485L; -// public static final String PERMISSION = "PERM_"; -// public static final String ROLE = "ROLE_"; -// -// public static final String admin = ROLE + "ADMIN"; -// public static final String systemAdmin = ROLE + "SYSTEMADMIN"; -// public static final String user = ROLE + "USER"; -// public static final String anonymous = ROLE + "ANONYMOUS"; - - /** - * Domain constants - * */ - public static final String ADMIN = "*"; - public static final String PROCESS = "PROCESS"; - public static final String FILTER = "FILTER"; - public static final String USER = "USER"; - public static final String GROUP = "GROUP"; - public static final String ROLE = "ROLE"; - public static final String AUTHORITY = "AUTHORITY"; - -// /** -// * Authority objects constants -// * */ -// public static final String processUpload = "PROCESS.UPLOAD"; -// public static final String processDelete = "PROCESS.DELETE"; -// public static final String filterUpload = "FILTER.UPLOAD"; -// public static final String filterDelete = "FILTER.DELETE"; -// public static final String userCreate = "USER.CREATE"; -// public static final String userDelete = "USER.DELETE"; -// public static final String userEdit = "USER.EDIT"; -// public static final String groupCreate = "GROUP.CREATE"; -// public static final String groupDelete = "GROUP.DELETE"; -// public static final String groupAddUser = "GROUP.ADD_USER"; -// public static final String groupRemoveUser = "GROUP.REMOVE_USER"; -// public static final String roleCreate = "ROLE.CREATE"; -// public static final String roleDelete = "ROLE.DELETE"; -// public static final String authorityCreate = "AUTHORITY.CREATE"; -// public static final String authorityDelete = "AUTHORITY.DELETE"; - - public static final List allAuthorities = new ArrayList<>(List.of(AuthorityEnum.values())); - @Id @Getter private ObjectId _id; diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityDomainEnum.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityDomainEnum.java new file mode 100644 index 0000000000..5cd6382c58 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityDomainEnum.java @@ -0,0 +1,14 @@ +package com.netgrif.application.engine.auth.domain; + +public enum AuthorityDomainEnum { + ADMIN("*"), + PROCESS("PROCESS"), + FILTER("FILTER"), + USER("USER"), + GROUP("GROUP"), + ROLE("ROLE"), + AUTHORITY("AUTHORITY"); + + AuthorityDomainEnum(String name) { + } +} diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java index 076470140a..34dffdc6c3 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java @@ -17,6 +17,6 @@ public enum AuthorityEnum { AUTHORITY_CREATE("AUTHORITY.CREATE"), AUTHORITY_DELETE("AUTHORITY.DELETE"); - AuthorityEnum(String s) { + AuthorityEnum(String name) { } } From a14d450f0257cbd894e7ef161629225727b69449 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Fri, 29 Apr 2022 10:50:35 +0200 Subject: [PATCH 04/68] [NAE-1617] Refactor Authority - updating authority runner --- .../application/engine/startup/AuthorityRunner.groovy | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy index 12504add93..6e2111edfd 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy @@ -1,6 +1,6 @@ package com.netgrif.application.engine.startup -import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityEnum import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Component @@ -13,9 +13,6 @@ class AuthorityRunner extends AbstractOrderedCommandLineRunner { @Override void run(String... strings) throws Exception { - service.getOrCreate(Authority.user) - service.getOrCreate(Authority.admin) - service.getOrCreate(Authority.systemAdmin) - service.getOrCreate(Authority.anonymous) + AuthorityEnum.values().toList().forEach(authority -> service.getOrCreate(authority.name())) } } \ No newline at end of file From 19befc89b4d4a5253a897321858c3cdea0a59724 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Fri, 29 Apr 2022 10:58:27 +0200 Subject: [PATCH 05/68] [NAE-1617] Refactor Authority - implemented inDomain function in Authority --- .../com/netgrif/application/engine/auth/domain/Authority.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java index d66dbb455b..c0c20c3b10 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java @@ -80,4 +80,8 @@ public String toString() { public int hashCode() { return name.hashCode(); } + + public boolean inDomain(AuthorityDomainEnum domain) { + return this.name.startsWith(domain.name()); + } } From 3e6f56ee4ffccd93550b02ef7f8e2b1fffa9d4b5 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Fri, 29 Apr 2022 11:26:25 +0200 Subject: [PATCH 06/68] [NAE-1617] Refactor Authority - refactored AbstractUserService to resolve default user authorities - implemented list for defaultUserAuthorities - added domains to AuthorityEnum - removed AuthorityDomainEnum - implemented getOrCreate for AuthorityEnum input - refactored LoggedUser isAdmin --- .../application/engine/auth/domain/Authority.java | 8 +++++++- .../engine/auth/domain/AuthorityDomainEnum.java | 14 -------------- .../engine/auth/domain/AuthorityEnum.java | 8 +++++++- .../application/engine/auth/domain/LoggedUser.java | 2 +- .../engine/auth/service/AbstractUserService.java | 6 ++---- .../engine/auth/service/AuthorityService.java | 8 +++++++- .../auth/service/interfaces/IAuthorityService.java | 3 +++ 7 files changed, 27 insertions(+), 22 deletions(-) delete mode 100644 src/main/java/com/netgrif/application/engine/auth/domain/AuthorityDomainEnum.java diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java index c0c20c3b10..e9399b56d6 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java @@ -19,6 +19,8 @@ public class Authority implements GrantedAuthority { public static final long serialVersionUID = 2839744057647464485L; + public static final List defaultUserAuthorities = Arrays.asList(AuthorityEnum.FILTER, AuthorityEnum.GROUP); + @Id @Getter private ObjectId _id; @@ -41,6 +43,10 @@ public Authority(String name) { this.name = name; } + public Authority(AuthorityEnum authority) { + this.name = authority.name(); + } + public void addUser(IUser user) { users.add(user.getStringId()); } @@ -81,7 +87,7 @@ public int hashCode() { return name.hashCode(); } - public boolean inDomain(AuthorityDomainEnum domain) { + public boolean inDomain(AuthorityEnum domain) { return this.name.startsWith(domain.name()); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityDomainEnum.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityDomainEnum.java deleted file mode 100644 index 5cd6382c58..0000000000 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityDomainEnum.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.netgrif.application.engine.auth.domain; - -public enum AuthorityDomainEnum { - ADMIN("*"), - PROCESS("PROCESS"), - FILTER("FILTER"), - USER("USER"), - GROUP("GROUP"), - ROLE("ROLE"), - AUTHORITY("AUTHORITY"); - - AuthorityDomainEnum(String name) { - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java index 34dffdc6c3..967e9ea4ae 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java @@ -1,6 +1,12 @@ package com.netgrif.application.engine.auth.domain; -public enum AuthorityEnum { +public enum AuthorityEnum {ADMIN("*"), + PROCESS("PROCESS"), + FILTER("FILTER"), + USER("USER"), + GROUP("GROUP"), + ROLE("ROLE"), + AUTHORITY("AUTHORITY"), PROCESS_UPLOAD("PROCESS.UPLOAD"), PROCESS_DELETE("PROCESS.DELETE"), FILTER_UPLOAD("FILTER.UPLOAD"), diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java b/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java index 8161f1f96b..b272a0ffef 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java @@ -48,7 +48,7 @@ public void parseProcessRoles(Set processRoles) { } public boolean isAdmin() { - return getAuthorities().contains(new Authority(Authority.admin)); + return getAuthorities().contains(new Authority(AuthorityEnum.ADMIN)); } public String getEmail() { diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java index cb8fe9ce78..a9d7a61f1d 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java @@ -48,7 +48,7 @@ public void addDefaultRole(IUser user) { public void addDefaultAuthorities(IUser user) { if (user.getAuthorities().isEmpty()) { HashSet authorities = new HashSet<>(); - authorities.add(authorityService.getOrCreate(Authority.user)); + Authority.defaultUserAuthorities.forEach(a -> authorities.add(authorityService.getOrCreate(a))); user.setAuthorities(authorities); } } @@ -95,9 +95,7 @@ protected IUser removeRole(IUser user, ProcessRole role) { @Override public void removeRoleOfDeletedPetriNet(PetriNet net) { List users = findAllByProcessRoles(net.getRoles().keySet(), false); - users.forEach(u -> { - net.getRoles().forEach((k, role) -> removeRole(u, role)); - }); + users.forEach(u -> net.getRoles().forEach((k, role) -> removeRole(u, role))); } @Override diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index 85f86eafd0..5e187599bd 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.auth.service; import com.netgrif.application.engine.auth.domain.Authority; +import com.netgrif.application.engine.auth.domain.AuthorityEnum; import com.netgrif.application.engine.auth.domain.repositories.AuthorityRepository; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import org.springframework.beans.factory.annotation.Autowired; @@ -30,9 +31,14 @@ public Authority getOrCreate(String name) { return authority; } + @Override + public Authority getOrCreate(AuthorityEnum authorityEnum) { + return getOrCreate(authorityEnum.name()); + } + public Authority getOne(String id) { Optional authority = repository.findById(id); - if (!authority.isPresent()) + if (authority.isEmpty()) throw new IllegalArgumentException("Could not find authority with id [" + id + "]"); return authority.get(); } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java index 615a34abfa..a6096398ea 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.auth.service.interfaces; import com.netgrif.application.engine.auth.domain.Authority; +import com.netgrif.application.engine.auth.domain.AuthorityEnum; import java.util.List; @@ -10,5 +11,7 @@ public interface IAuthorityService { Authority getOrCreate(String name); + Authority getOrCreate(AuthorityEnum authorityEnum); + Authority getOne(String id); } \ No newline at end of file From 5d6ee5373ff0d47a85fd9b0cabe685ca6e9fbb26 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Fri, 29 Apr 2022 13:17:08 +0200 Subject: [PATCH 07/68] [NAE-1617] Refactor Authority - refactored tests when creating authorities - modified functions in Authority to ensure Admin has all authorities - added anonymous authority - implemented getOrCreate with list input in AuthorityService - refactored user permission creation --- .../engine/startup/ImportHelper.groovy | 27 +++++-------------- .../engine/startup/SuperCreator.groovy | 4 +-- .../engine/auth/domain/Authority.java | 2 +- .../engine/auth/domain/AuthorityEnum.java | 4 ++- .../engine/auth/service/AuthorityService.java | 9 +++++++ .../engine/auth/service/UserService.java | 4 +-- .../service/interfaces/IAuthorityService.java | 2 ++ .../configuration/SecurityConfiguration.java | 3 ++- .../SecurityConfigurationLdap.java | 3 ++- .../engine/action/AssignActionTest.groovy | 3 ++- .../engine/action/RemoveActionTest.groovy | 3 ++- .../FilterAuthorizationServiceTest.groovy | 2 +- .../auth/TaskAuthorizationServiceTest.groovy | 5 ++-- .../WorkflowAuthorizationServiceTest.groovy | 4 +-- .../engine/elastic/ElasticSearchTest.groovy | 2 +- .../event/GroovyShellFactoryTest.groovy | 3 ++- .../filters/FilterImportExportTest.groovy | 2 +- .../engine/insurance/mvc/InsuranceTest.groovy | 2 +- .../engine/menu/MenuImportExportTest.groovy | 2 +- .../groups/NextGroupServiceTest.groovy | 2 +- .../domain/roles/ProcessRoleTest.groovy | 2 +- .../service/PetriNetServiceTest.groovy | 2 +- .../web/PetriNetControllerTest.groovy | 2 +- .../application/engine/MockService.java | 5 ++-- .../workflow/service/TaskServiceTest.java | 10 +++---- .../engine/workflow/web/VariableArcsTest.java | 2 +- 26 files changed, 57 insertions(+), 54 deletions(-) diff --git a/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy b/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy index dcb853d9df..df59bfad08 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy @@ -91,10 +91,13 @@ class ImportHelper { @SuppressWarnings("GroovyAssignabilityCheck") - Map createAuthorities(Map authorities) { - HashMap authoritities = new HashMap<>() + Map> createAuthorities(Map> authorities) { + HashMap> authoritities = new HashMap<>() authorities.each { authority -> - authoritities.put(authority.key, authorityService.getOrCreate(authority.value)) + authoritities.put(authority.key, new ArrayList()) + authority.value.forEach( a -> + authoritities.get(authority.key).add(authorityService.getOrCreate(a)) + ) } log.info("Creating ${authoritities.size()} authorities") @@ -123,24 +126,6 @@ class ImportHelper { return Optional.of(petriNet) } -// ProcessRole createUserProcessRole(PetriNet net, String name) { -// ProcessRole role = processRoleRepository.save(new ProcessRole(roleId: -// net.roles.values().find { it -> it.name.defaultValue == name }.stringId, netId: net.getStringId())) -// log.info("Created user process role $name") -// return role -// } -// -// Map createUserProcessRoles(Map roles, PetriNet net) { -// HashMap userRoles = new HashMap<>() -// roles.each { it -> -// userRoles.put(it.key, createUserProcessRole(net, it.value)) -// } -// -// log.info("Created ${userRoles.size()} process roles") -// return userRoles -// } - - ProcessRole getProcessRoleByImportId(PetriNet net, String roleId) { ProcessRole role = net.roles.values().find { it -> it.importId == roleId } return role diff --git a/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy b/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy index 876008d5f6..a37b9545fb 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy @@ -43,8 +43,8 @@ class SuperCreator extends AbstractOrderedCommandLineRunner { } private IUser createSuperUser() { - Authority adminAuthority = authorityService.getOrCreate(Authority.admin) - Authority systemAuthority = authorityService.getOrCreate(Authority.systemAdmin) + Authority adminAuthority = authorityService.getOrCreate(AuthorityEnum.ADMIN) + Authority systemAuthority = authorityService.getOrCreate(AuthorityEnum.ADMIN) IUser superUser = userService.findByEmail("super@netgrif.com", false) if (superUser == null) { diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java index e9399b56d6..074684be0e 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java @@ -88,6 +88,6 @@ public int hashCode() { } public boolean inDomain(AuthorityEnum domain) { - return this.name.startsWith(domain.name()); + return this.name.startsWith(domain.name()) || this.name.equals(AuthorityEnum.ADMIN.name()); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java index 967e9ea4ae..7f651226c4 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java @@ -1,6 +1,8 @@ package com.netgrif.application.engine.auth.domain; -public enum AuthorityEnum {ADMIN("*"), +public enum AuthorityEnum { + ADMIN("*"), + ANONYMOUS("-"), PROCESS("PROCESS"), FILTER("FILTER"), USER("USER"), diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index 5e187599bd..24d7de5553 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -8,8 +8,10 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; @Service public class AuthorityService implements IAuthorityService { @@ -36,6 +38,13 @@ public Authority getOrCreate(AuthorityEnum authorityEnum) { return getOrCreate(authorityEnum.name()); } + @Override + public List getOrCreate(List authorities) { + if (authorities == null) + return Collections.emptyList(); + return authorities.stream().map(this::getOrCreate).collect(Collectors.toList()); + } + public Authority getOne(String id) { Optional authority = repository.findById(id); if (authority.isEmpty()) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java index e57bc63cb8..fff50d3eb8 100755 --- a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java @@ -130,7 +130,7 @@ public void addAnonymousRole(User user) { public void addDefaultAuthorities(User user) { if (user.getAuthorities().isEmpty()) { HashSet authorities = new HashSet(); - authorities.add(authorityRepository.findByName(Authority.user)); + Authority.defaultUserAuthorities.forEach(a -> authorities.add(authorityRepository.findByName(a.name()))); user.setAuthorities(authorities); } } @@ -138,7 +138,7 @@ public void addDefaultAuthorities(User user) { public void addAnonymousAuthorities(User user) { if (user.getAuthorities().isEmpty()) { HashSet authorities = new HashSet(); - authorities.add(authorityRepository.findByName(Authority.anonymous)); + authorities.add(authorityRepository.findByName(AuthorityEnum.ANONYMOUS.name())); user.setAuthorities(authorities); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java index a6096398ea..c1279cab4c 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java @@ -13,5 +13,7 @@ public interface IAuthorityService { Authority getOrCreate(AuthorityEnum authorityEnum); + List getOrCreate(List authorities); + Authority getOne(String id); } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/configuration/SecurityConfiguration.java b/src/main/java/com/netgrif/application/engine/configuration/SecurityConfiguration.java index e20d3b7d06..95288c1b6a 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/SecurityConfiguration.java +++ b/src/main/java/com/netgrif/application/engine/configuration/SecurityConfiguration.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.configuration; import com.netgrif.application.engine.auth.domain.Authority; +import com.netgrif.application.engine.auth.domain.AuthorityEnum; import com.netgrif.application.engine.auth.domain.UserProperties; import com.netgrif.application.engine.auth.service.AfterRegistrationAuthService; import com.netgrif.application.engine.auth.service.interfaces.IAfterRegistrationAuthService; @@ -175,7 +176,7 @@ protected Environment getEnvironment() { } private PublicAuthenticationFilter createPublicAuthenticationFilter() throws Exception { - Authority authority = authorityService.getOrCreate(Authority.anonymous); + Authority authority = authorityService.getOrCreate(AuthorityEnum.ANONYMOUS); authority.setUsers(new HashSet<>()); return new PublicAuthenticationFilter( authenticationManager(), diff --git a/src/main/java/com/netgrif/application/engine/configuration/SecurityConfigurationLdap.java b/src/main/java/com/netgrif/application/engine/configuration/SecurityConfigurationLdap.java index 6e4f9f2b00..3019dc7985 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/SecurityConfigurationLdap.java +++ b/src/main/java/com/netgrif/application/engine/configuration/SecurityConfigurationLdap.java @@ -2,6 +2,7 @@ import com.netgrif.application.engine.auth.domain.Authority; +import com.netgrif.application.engine.auth.domain.AuthorityEnum; import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.ldap.domain.LdapUser; import com.netgrif.application.engine.auth.service.AfterRegistrationAuthService; @@ -227,7 +228,7 @@ protected Environment getEnvironment() { } private PublicAuthenticationFilter createPublicAuthenticationFilter() throws Exception { - Authority authority = authorityService.getOrCreate(Authority.anonymous); + Authority authority = authorityService.getOrCreate(AuthorityEnum.ANONYMOUS); authority.setUsers(new HashSet<>()); return new PublicAuthenticationFilter( authenticationManager(), diff --git a/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy index 84e30ed108..ee95156de6 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.action import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityEnum import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.auth.domain.repositories.UserRepository @@ -90,7 +91,7 @@ class AssignActionTest { createMainAndSecondaryNet() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), [auths.get("user"), auths.get("admin")] as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy index 8306be043d..f09f26d349 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.action import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityEnum import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.auth.domain.repositories.UserRepository @@ -96,7 +97,7 @@ class RemoveActionTest { this.petriNet = net.getNet() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), [auths.get("user")] as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy index 3191b87f48..c69abd7ecc 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy @@ -67,7 +67,7 @@ class FilterAuthorizationServiceTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy index 0ad59edf25..de8ef33e64 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy @@ -1,6 +1,7 @@ package com.netgrif.application.engine.auth import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityEnum import com.netgrif.application.engine.auth.domain.IUser import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState @@ -119,7 +120,7 @@ class TaskAuthorizationServiceTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) def processRoles = userProcessRoleRepository.findAllByNetId(this.net.getStringId()) def user = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_WITH_ROLE_EMAIL, password: "password", state: UserState.ACTIVE), @@ -166,7 +167,7 @@ class TaskAuthorizationServiceTest { assert netWithUserRefs.getNet() != null this.netWithUserRefs = netWithUserRefs.getNet() - auths = importHelper.createAuthorities(["user": Authority.user]) + auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities]) testUser = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], [] as ProcessRole[]) } diff --git a/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy index 26c3733ca3..3fe3eeb725 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy @@ -96,7 +96,7 @@ class WorkflowAuthorizationServiceTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], @@ -123,7 +123,7 @@ class WorkflowAuthorizationServiceTest { assert netWithUserRefs.getNet() != null this.netWithUserRefs = netWithUserRefs.getNet() - auths = importHelper.createAuthorities(["user": Authority.user]) + auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities]) testUser = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], [] as ProcessRole[]) } diff --git a/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy b/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy index c261ad7556..4baa823621 100644 --- a/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy @@ -109,7 +109,7 @@ class ElasticSearchTest { netId2 = net2.getStringId() // def org = importHelper.createGroup("Test") - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) // def processRoles = importHelper.getProcessRoles(net.get()) def testUser = importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSW, state: UserState.ACTIVE), [auths.get("user")] as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy b/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy index 0a95f5ca0d..bb0a65ba94 100644 --- a/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.event import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityEnum import com.netgrif.application.engine.auth.domain.LoggedUser import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState @@ -80,7 +81,7 @@ class GroovyShellFactoryTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["systemAdmin": Authority.systemAdmin]) + def auths = importHelper.createAuthorities(["systemAdmin": [AuthorityEnum.ADMIN]]) importHelper.createUser(new User(name: "Admin", surname: "User", email: USER_EMAIL, password: USER_PASSW, state: UserState.ACTIVE), [auths.get("systemAdmin")] as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy b/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy index d726724f21..25ade537ef 100644 --- a/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy @@ -299,7 +299,7 @@ class FilterImportExportTest { } private User createDummyUser() { - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) return importHelper.createUser(new User(name: "Dummy", surname: "User", email: DUMMY_USER_MAIL, password: DUMMY_USER_PASSWORD, state: UserState.ACTIVE), [auths.get("user")] as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy b/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy index b2eb555e07..36d8e8e229 100644 --- a/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy @@ -133,7 +133,7 @@ class InsuranceTest { netId = net.getNet().getStringId() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) def processRoles = importHelper.getProcessRolesByImportId(net.getNet(), ["agent": "1", "company": "2"]) importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), [auths.get("user"), auths.get("admin")] as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy b/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy index cf6e010885..5773b3c9df 100644 --- a/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy @@ -199,7 +199,7 @@ class MenuImportExportTest { } private User createDummyUser() { - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) return importHelper.createUser(new User(name: "Dummy", surname: "User", email: DUMMY_USER_MAIL, password: DUMMY_USER_PASSWORD, state: UserState.ACTIVE), [auths.get("user")] as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy index 43133d77fc..ba909b539e 100644 --- a/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy @@ -45,7 +45,7 @@ class NextGroupServiceTest { @Test void groupTest() { testHelper.truncateDbs() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) importHelper.createUser(new User(name: "Dummy", surname: "User", email: DUMMY_USER_MAIL, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy index ed7c467268..5fd11958ca 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy @@ -85,7 +85,7 @@ class ProcessRoleTest { String netId = net.getNet().getStringId() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) def processRoles = userProcessRoleRepository.findAllByNetId(netId) importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL_VIEW, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy index 9d17e6c3d9..29de899123 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy @@ -73,7 +73,7 @@ class PetriNetServiceTest { @BeforeEach void setup() { testHelper.truncateDbs() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) importHelper.createUser(new User(name: "Customer", surname: "User", email: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy index b270d3c331..f421e77b3b 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy @@ -79,7 +79,7 @@ class PetriNetControllerTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], diff --git a/src/test/java/com/netgrif/application/engine/MockService.java b/src/test/java/com/netgrif/application/engine/MockService.java index 524cb597c3..741b39181b 100644 --- a/src/test/java/com/netgrif/application/engine/MockService.java +++ b/src/test/java/com/netgrif/application/engine/MockService.java @@ -9,6 +9,7 @@ import org.springframework.stereotype.Component; import java.util.Collections; +import java.util.List; @Component @Profile("test") @@ -18,7 +19,7 @@ public class MockService { private IAuthorityService authorityService; public LoggedUser mockLoggedUser() { - Authority authorityUser = authorityService.getOrCreate(Authority.user); - return new LoggedUser(new ObjectId().toString(), "super@netgrif.com", "password", Collections.singleton(authorityUser)); + List authorityUser = authorityService.getOrCreate(Authority.defaultUserAuthorities); + return new LoggedUser(new ObjectId().toString(), "super@netgrif.com", "password", authorityUser); } } diff --git a/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java b/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java index 473ccd68fb..3f206b153d 100644 --- a/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java +++ b/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java @@ -1,9 +1,6 @@ package com.netgrif.application.engine.workflow.service; -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.domain.User; -import com.netgrif.application.engine.auth.domain.UserState; +import com.netgrif.application.engine.auth.domain.*; import com.netgrif.application.engine.auth.domain.repositories.UserRepository; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; @@ -36,6 +33,7 @@ import java.io.FileInputStream; import java.io.IOException; import java.util.Collections; +import java.util.List; @SpringBootTest @ActiveProfiles({"test"}) @@ -132,7 +130,7 @@ public void resetArcTest() throws TransitionNotExecutableException, MissingPetri } public LoggedUser mockLoggedUser() { - Authority authorityUser = authorityService.getOrCreate(Authority.user); - return new LoggedUser(new ObjectId().toString(), "super@netgrif.com", "password", Collections.singleton(authorityUser)); + List authorityUser = authorityService.getOrCreate(Authority.defaultUserAuthorities); + return new LoggedUser(new ObjectId().toString(), "super@netgrif.com", "password", authorityUser); } } \ No newline at end of file diff --git a/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java b/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java index 9ab4e4b231..c7a93c9886 100644 --- a/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java +++ b/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java @@ -119,7 +119,7 @@ public void before() throws Exception { user.setState(UserState.ACTIVE); user.setEmail("VariableArcsTest@test.com"); testUser = importHelper.createUser(user, - new Authority[]{authorityService.getOrCreate(Authority.user)}, + authorityService.getOrCreate(Authority.defaultUserAuthorities).toArray(new Authority[]{}), new ProcessRole[]{}); finishCase = importHelper.createCase("finish case", loaded); From 6f17119a75639ffb48d49ae74e76d2d100f8fc2f Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Fri, 29 Apr 2022 14:13:26 +0200 Subject: [PATCH 08/68] [NAE-1617] Refactor Authority - implemented delete function for AuthorityService --- .../application/engine/auth/service/AuthorityService.java | 8 ++++++++ .../engine/auth/service/interfaces/IAuthorityService.java | 2 ++ 2 files changed, 10 insertions(+) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index 24d7de5553..6df2d49515 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -45,6 +45,14 @@ public List getOrCreate(List authorities) { return authorities.stream().map(this::getOrCreate).collect(Collectors.toList()); } + @Override + public void delete(String name) { + Authority authority = repository.findByName(name); + if (authority == null) + throw new IllegalArgumentException("Could not find authority with name [" + name + "]"); + repository.delete(authority); + } + public Authority getOne(String id) { Optional authority = repository.findById(id); if (authority.isEmpty()) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java index c1279cab4c..865cfc67b1 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java @@ -15,5 +15,7 @@ public interface IAuthorityService { List getOrCreate(List authorities); + void delete(String name); + Authority getOne(String id); } \ No newline at end of file From 552cb90fd9b63934ee8aa07d603c97f6f75e5e76 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 2 May 2022 09:36:32 +0200 Subject: [PATCH 09/68] [NAE-1617] Refactor Authority - implemented objects needed to resolve AuthorityController - implemented new functions in AuthorityService --- .../AuthorityAuthorizationService.java | 4 ++ .../engine/auth/service/AuthorityService.java | 3 +- .../IAuthorityAuthorizationService.java | 4 ++ .../service/interfaces/IAuthorityService.java | 2 +- .../engine/auth/web/AuthorityController.java | 48 +++++++++++++++++++ .../requestbodies/NewAuthorityRequest.java | 10 ++++ .../web/responsebodies/AuthorityResource.java | 13 +++++ 7 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/netgrif/application/engine/auth/service/AuthorityAuthorizationService.java create mode 100644 src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityAuthorizationService.java create mode 100644 src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java create mode 100644 src/main/java/com/netgrif/application/engine/auth/web/requestbodies/NewAuthorityRequest.java create mode 100644 src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthorityResource.java diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityAuthorizationService.java new file mode 100644 index 0000000000..e54a78b9cb --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityAuthorizationService.java @@ -0,0 +1,4 @@ +package com.netgrif.application.engine.auth.service; + +public class AuthorityAuthorizationService { +} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index 6df2d49515..0f1b7b34e4 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -46,11 +46,12 @@ public List getOrCreate(List authorities) { } @Override - public void delete(String name) { + public Authority delete(String name) { Authority authority = repository.findByName(name); if (authority == null) throw new IllegalArgumentException("Could not find authority with name [" + name + "]"); repository.delete(authority); + return authority; } public Authority getOne(String id) { diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityAuthorizationService.java new file mode 100644 index 0000000000..2b2dbb329c --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityAuthorizationService.java @@ -0,0 +1,4 @@ +package com.netgrif.application.engine.auth.service.interfaces; + +public interface IAuthorityAuthorizationService { +} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java index 865cfc67b1..1a80d7fec1 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java @@ -15,7 +15,7 @@ public interface IAuthorityService { List getOrCreate(List authorities); - void delete(String name); + Authority delete(String name); Authority getOne(String id); } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java new file mode 100644 index 0000000000..14d64ac961 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java @@ -0,0 +1,48 @@ +package com.netgrif.application.engine.auth.web; + +import com.netgrif.application.engine.auth.domain.Authority; +import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; +import com.netgrif.application.engine.auth.web.requestbodies.NewAuthorityRequest; +import com.netgrif.application.engine.auth.web.responsebodies.AuthorityResource; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.Authorization; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.MediaTypes; +import org.springframework.http.MediaType; +import org.springframework.security.core.Authentication; +import org.springframework.web.bind.annotation.*; + +import java.util.Locale; + +@Slf4j +@RestController +@RequestMapping("/api/authority") +@ConditionalOnProperty( + value = "nae.user.web.enabled", + havingValue = "true", + matchIfMissing = true +) +@Api(tags = {"Authority"}) +public class AuthorityController { + + @Autowired + private IAuthorityService authorityService; + + @ApiOperation(value = "Delete authority", authorizations = @Authorization("BasicAuth")) + @PostMapping(value = "/delete/{name}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) + public EntityModel delete(@PathVariable String name, Authentication auth, Locale locale) { + Authority deletedAuthority = authorityService.delete(name); + return AuthorityResource.of(deletedAuthority); + } + + @ApiOperation(value = "Delete authority", authorizations = @Authorization("BasicAuth")) + @PostMapping(value = "/create", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) + public EntityModel create(@RequestBody NewAuthorityRequest request, Authentication auth, Locale locale) { + Authority authority = authorityService.getOrCreate(request.name); + return AuthorityResource.of(authority); + } +} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/NewAuthorityRequest.java b/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/NewAuthorityRequest.java new file mode 100644 index 0000000000..82d6a98646 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/auth/web/requestbodies/NewAuthorityRequest.java @@ -0,0 +1,10 @@ +package com.netgrif.application.engine.auth.web.requestbodies; + +import lombok.Data; + +@Data +public class NewAuthorityRequest { + + public String name; + +} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthorityResource.java b/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthorityResource.java new file mode 100644 index 0000000000..5e81f69ee4 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthorityResource.java @@ -0,0 +1,13 @@ +package com.netgrif.application.engine.auth.web.responsebodies; + +import com.netgrif.application.engine.auth.domain.Authority; +import org.springframework.hateoas.EntityModel; + +import java.util.ArrayList; + +public class AuthorityResource extends EntityModel { + + public AuthorityResource(Authority content) { + super(content, new ArrayList<>()); + } +} From d0c02a292f2ce8641e8c257306298bd67553137e Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 2 May 2022 09:45:02 +0200 Subject: [PATCH 10/68] [NAE-1617] Refactor Authority - implemented new function in AbstractUserService to check whether user has authority - removed commented functions from UserService - refactored UserService according to suggestions --- .../auth/service/AbstractUserService.java | 10 ++++++ .../engine/auth/service/UserService.java | 33 +++---------------- .../auth/service/interfaces/IUserService.java | 4 +++ 3 files changed, 19 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java index a9d7a61f1d..691adfdd96 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java @@ -109,6 +109,16 @@ public IUser createSystemUser() { return system; } + @Override + public boolean hasAuthority(IUser user, Authority authority) { + return user.getAuthorities().stream().anyMatch(a -> a.getStringId().equals(authority.getStringId())); + } + + @Override + public boolean hasAuthority(IUser user, String authority) { + return user.getAuthorities().stream().anyMatch(a -> a.getName().equals(authority)); + } + public Page changeType(Page users, Pageable pageable) { return new PageImpl<>(changeType(users.getContent()), pageable, users.getTotalElements()); } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java index fff50d3eb8..02c91b1f4e 100755 --- a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java @@ -129,7 +129,7 @@ public void addAnonymousRole(User user) { public void addDefaultAuthorities(User user) { if (user.getAuthorities().isEmpty()) { - HashSet authorities = new HashSet(); + HashSet authorities = new HashSet<>(); Authority.defaultUserAuthorities.forEach(a -> authorities.add(authorityRepository.findByName(a.name()))); user.setAuthorities(authorities); } @@ -137,7 +137,7 @@ public void addDefaultAuthorities(User user) { public void addAnonymousAuthorities(User user) { if (user.getAuthorities().isEmpty()) { - HashSet authorities = new HashSet(); + HashSet authorities = new HashSet<>(); authorities.add(authorityRepository.findByName(AuthorityEnum.ANONYMOUS.name())); user.setAuthorities(authorities); } @@ -271,9 +271,9 @@ public void assignAuthority(String userId, String authorityId) { Optional user = userRepository.findById(userId); Optional authority = authorityRepository.findById(authorityId); - if (!user.isPresent()) + if (user.isEmpty()) throw new IllegalArgumentException("Could not find user with id [" + userId + "]"); - if (!authority.isPresent()) + if (authority.isEmpty()) throw new IllegalArgumentException("Could not find authority with id [" + authorityId + "]"); user.get().addAuthority(authority.get()); @@ -304,37 +304,14 @@ public LoggedUser getAnonymousLogged() { return (LoggedUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); } -// @Override -// public IUser addRole(IUser user, String roleStringId) { -// ProcessRole role = processRoleService.findById(roleStringId); -// user.addProcessRole(role); -// return userRepository.save(user); -// } -// -// @Override -// public IUser removeRole(IUser user, String roleStringId) { -// ProcessRole role = processRoleService.findByImportId(roleStringId); -// user.removeProcessRole(role); -// return userRepository.save(user); -// } - @Override public void deleteUser(IUser user) { User dbUser = (User) user; - if (!userRepository.findById(dbUser.getStringId()).isPresent()) + if (userRepository.findById(dbUser.getStringId()).isEmpty()) throw new IllegalArgumentException("Could not find user with id [" + dbUser.get_id() + "]"); userRepository.delete(dbUser); } - -/* private User loadProcessRoles(User user) { - if (user == null) - return null; - user.setProcessRoles(processRoleRepository.findAllById(user.getUserProcessRoles() - .stream().map(UserProcessRole::getRoleId).collect(Collectors.toList()))); - return user; - }*/ - private User loadGroups(User user) { if (user == null) return null; diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserService.java index b2d4f9c766..9ffada008f 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserService.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.auth.service.interfaces; import com.netgrif.application.engine.auth.domain.AnonymousUser; +import com.netgrif.application.engine.auth.domain.Authority; import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.web.requestbodies.UpdateUserRequest; @@ -73,4 +74,7 @@ public interface IUserService { IUser createSystemUser(); + boolean hasAuthority(IUser user, Authority authority); + + boolean hasAuthority(IUser user, String authority); } \ No newline at end of file From 4c1e918659654314ffe24ed8e17da318ded1384a Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 2 May 2022 10:20:09 +0200 Subject: [PATCH 11/68] [NAE-1617] Refactor Authority - implemented AbstractBaseAuthorizationService - implemented extending of AbstractBaseAuthorizationService in authorization services --- .../AbstractBaseAuthorizationService.java | 16 ++++++++++++++++ .../service/AuthorityAuthorizationService.java | 14 +++++++++++++- .../service/PetriNetAuthorizationService.java | 10 +++++++++- .../service/AbstractAuthorizationService.java | 8 +++++++- .../service/TaskAuthorizationService.java | 6 ++++++ .../service/WorkflowAuthorizationService.java | 5 +++++ 6 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java new file mode 100644 index 0000000000..06a2f3491d --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java @@ -0,0 +1,16 @@ +package com.netgrif.application.engine.auth.service; + +import com.netgrif.application.engine.auth.service.interfaces.IUserService; + +public abstract class AbstractBaseAuthorizationService { + + private final IUserService userService; + + public AbstractBaseAuthorizationService(IUserService userService) { + this.userService = userService; + } + + public boolean hasAuthority(String authority) { + return this.userService.getLoggedUser().getAuthorities().stream().anyMatch(a -> a.getName().equals(authority)); + } +} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityAuthorizationService.java index e54a78b9cb..09afbb0db8 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityAuthorizationService.java @@ -1,4 +1,16 @@ package com.netgrif.application.engine.auth.service; -public class AuthorityAuthorizationService { +import com.netgrif.application.engine.auth.service.interfaces.IAuthorityAuthorizationService; +import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import com.netgrif.application.engine.workflow.service.AbstractAuthorizationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class AuthorityAuthorizationService extends AbstractAuthorizationService implements IAuthorityAuthorizationService { + + public AuthorityAuthorizationService(@Autowired IUserService userService) { + super(userService); + } + } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java index 4cbee55a30..be9d83692c 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java @@ -1,11 +1,19 @@ package com.netgrif.application.engine.petrinet.service; import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.auth.service.AbstractBaseAuthorizationService; +import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetAuthorizationService; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service -public class PetriNetAuthorizationService implements IPetriNetAuthorizationService { +public class PetriNetAuthorizationService extends AbstractBaseAuthorizationService implements IPetriNetAuthorizationService { + + public PetriNetAuthorizationService(@Autowired IUserService userService) { + super(userService); + } + @Override public boolean canCallProcessDelete(LoggedUser loggedUser, String processId) { return loggedUser.isAdmin(); diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationService.java b/src/main/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationService.java index 19530c522d..6642f03ba9 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationService.java @@ -1,13 +1,19 @@ package com.netgrif.application.engine.workflow.service; import com.netgrif.application.engine.auth.domain.IUser; +import com.netgrif.application.engine.auth.service.AbstractBaseAuthorizationService; +import com.netgrif.application.engine.auth.service.interfaces.IUserService; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; -public abstract class AbstractAuthorizationService { +public abstract class AbstractAuthorizationService extends AbstractBaseAuthorizationService { + + public AbstractAuthorizationService(IUserService userService) { + super(userService); + } protected boolean hasPermission(Boolean hasPermission) { return hasPermission != null && hasPermission; diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/TaskAuthorizationService.java b/src/main/java/com/netgrif/application/engine/workflow/service/TaskAuthorizationService.java index 4484ed9e72..42f3a10691 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/TaskAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/TaskAuthorizationService.java @@ -3,6 +3,8 @@ import com.netgrif.application.engine.auth.domain.AnonymousUser; import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.auth.service.UserService; +import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.petrinet.domain.roles.RolePermission; import com.netgrif.application.engine.petrinet.domain.throwable.IllegalTaskStateException; import com.netgrif.application.engine.workflow.domain.Task; @@ -20,6 +22,10 @@ public class TaskAuthorizationService extends AbstractAuthorizationService imple @Autowired ITaskService taskService; + public TaskAuthorizationService(@Autowired IUserService userService) { + super(userService); + } + @Override public Boolean userHasAtLeastOneRolePermission(LoggedUser loggedUser, String taskId, RolePermission... permissions) { return userHasAtLeastOneRolePermission(loggedUser.transformToUser(), taskService.findById(taskId), permissions); diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowAuthorizationService.java b/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowAuthorizationService.java index c16613755b..9489e5d942 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowAuthorizationService.java @@ -2,6 +2,7 @@ import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.petrinet.domain.PetriNet; import com.netgrif.application.engine.petrinet.domain.roles.ProcessRolePermission; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; @@ -23,6 +24,10 @@ public class WorkflowAuthorizationService extends AbstractAuthorizationService i @Autowired private IPetriNetService petriNetService; + public WorkflowAuthorizationService(@Autowired IUserService userService) { + super(userService); + } + @Override public boolean canCallDelete(LoggedUser user, String caseId) { Case requestedCase = workflowService.findOne(caseId); From 6e4549126853a48c6db212e969e58522764db933 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 2 May 2022 13:05:37 +0200 Subject: [PATCH 12/68] [NAE-1617] Refactor Authority - refactored AuthorityEnum - implemented save function in AuthorityService - implemented preauthorized in PetriNetController --- .../engine/startup/SuperCreator.groovy | 7 +-- .../engine/auth/domain/Authority.java | 9 ++-- .../engine/auth/domain/AuthorityEnum.java | 49 +++++++++---------- .../engine/auth/service/AuthorityService.java | 5 ++ .../service/interfaces/IAuthorityService.java | 2 + .../petrinet/web/PetriNetController.java | 7 +-- 6 files changed, 42 insertions(+), 37 deletions(-) diff --git a/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy b/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy index a37b9545fb..4499c6390b 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy @@ -44,7 +44,6 @@ class SuperCreator extends AbstractOrderedCommandLineRunner { private IUser createSuperUser() { Authority adminAuthority = authorityService.getOrCreate(AuthorityEnum.ADMIN) - Authority systemAuthority = authorityService.getOrCreate(AuthorityEnum.ADMIN) IUser superUser = userService.findByEmail("super@netgrif.com", false) if (superUser == null) { @@ -54,7 +53,7 @@ class SuperCreator extends AbstractOrderedCommandLineRunner { email: "super@netgrif.com", password: superAdminPassword, state: UserState.ACTIVE, - authorities: [adminAuthority, systemAuthority] as Set, + authorities: [adminAuthority] as Set, processRoles: processRoleService.findAll() as Set)) log.info("Super user created") } else { @@ -62,13 +61,15 @@ class SuperCreator extends AbstractOrderedCommandLineRunner { this.superUser = superUser } + adminAuthority.addUser(this.superUser) + authorityService.save(adminAuthority) return this.superUser } void setAllToSuperUser() { setAllGroups() setAllProcessRoles() - setAllAuthorities() + //setAllAuthorities() log.info("Super user updated") } diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java index 074684be0e..83158c6e45 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java @@ -9,10 +9,7 @@ import org.springframework.security.core.GrantedAuthority; import javax.validation.constraints.NotNull; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; +import java.util.*; @Document public class Authority implements GrantedAuthority { @@ -37,14 +34,16 @@ public class Authority implements GrantedAuthority { private Set users; public Authority() { + this.users = new HashSet<>(); } public Authority(String name) { + this(); this.name = name; } public Authority(AuthorityEnum authority) { - this.name = authority.name(); + this(authority.name()); } public void addUser(IUser user) { diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java index 7f651226c4..0f62ee64b0 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java @@ -1,30 +1,27 @@ package com.netgrif.application.engine.auth.domain; public enum AuthorityEnum { - ADMIN("*"), - ANONYMOUS("-"), - PROCESS("PROCESS"), - FILTER("FILTER"), - USER("USER"), - GROUP("GROUP"), - ROLE("ROLE"), - AUTHORITY("AUTHORITY"), - PROCESS_UPLOAD("PROCESS.UPLOAD"), - PROCESS_DELETE("PROCESS.DELETE"), - FILTER_UPLOAD("FILTER.UPLOAD"), - FILTER_DELETE("FILTER.DELETE"), - USER_CREATE("USER.CREATE"), - USER_DELETE("USER.DELETE"), - USER_EDIT("USER.EDIT"), - GROUP_CREATE("GROUP.CREATE"), - GROUP_DELETE("GROUP.DELETE"), - GROUP_ADD_USER("GROUP.ADD_USER"), - GROUP_REMOVE_USER("GROUP.REMOVE_USER"), - ROLE_CREATE("ROLE.CREATE"), - ROLE_DELETE("ROLE.DELETE"), - AUTHORITY_CREATE("AUTHORITY.CREATE"), - AUTHORITY_DELETE("AUTHORITY.DELETE"); - - AuthorityEnum(String name) { - } + ADMIN, + ANONYMOUS, + PROCESS, + FILTER, + USER, + GROUP, + ROLE, + AUTHORITY, + PROCESS_UPLOAD, + PROCESS_DELETE, + FILTER_UPLOAD, + FILTER_DELETE, + USER_CREATE, + USER_DELETE, + USER_EDIT, + GROUP_CREATE, + GROUP_DELETE, + GROUP_ADD_USER, + GROUP_REMOVE_USER, + ROLE_CREATE, + ROLE_DELETE, + AUTHORITY_CREATE, + AUTHORITY_DELETE } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index 0f1b7b34e4..151eb3b67c 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -38,6 +38,11 @@ public Authority getOrCreate(AuthorityEnum authorityEnum) { return getOrCreate(authorityEnum.name()); } + @Override + public Authority save(Authority authority) { + return repository.save(authority); + } + @Override public List getOrCreate(List authorities) { if (authorities == null) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java index 1a80d7fec1..9d95fdf80a 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java @@ -13,6 +13,8 @@ public interface IAuthorityService { Authority getOrCreate(AuthorityEnum authorityEnum); + Authority save(Authority authority); + List getOrCreate(List authorities); Authority delete(String name); diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index 3ce326d7a7..49c4cc95fb 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -5,6 +5,7 @@ import com.netgrif.application.engine.importer.service.Importer; import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; import com.netgrif.application.engine.petrinet.domain.PetriNet; +import com.netgrif.application.engine.petrinet.domain.VersionType; import com.netgrif.application.engine.petrinet.domain.throwable.MissingPetriNetMetaDataException; import com.netgrif.application.engine.petrinet.domain.version.StringToVersionConverter; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; @@ -68,7 +69,7 @@ public class PetriNetController { @Autowired private StringToVersionConverter converter; - @PreAuthorize("hasRole('ADMIN')") + @PreAuthorize("@petriNetAuthorizationService.hasAuthority('ADMIN')") @ApiOperation(value = "Import new process", notes = "Caller must have the ADMIN role. Imports an entirely new process or a new version of an existing process.", authorizations = @Authorization("BasicAuth")) @@ -79,7 +80,7 @@ public class PetriNetController { }) @RequestMapping(value = "/import", method = POST, produces = MediaTypes.HAL_JSON_VALUE) public EntityModel importPetriNet( - @RequestParam(value = "file", required = true) MultipartFile multipartFile, + @RequestParam(value = "file") MultipartFile multipartFile, @RequestParam(value = "meta", required = false) String releaseType, Authentication auth, Locale locale) throws MissingPetriNetMetaDataException, MissingIconKeyException { try { @@ -87,7 +88,7 @@ public EntityModel importPetriNet( file.createNewFile(); FileOutputStream fout = new FileOutputStream(file); fout.write(multipartFile.getBytes()); - String release = releaseType == null ? "major" : releaseType; + VersionType release = releaseType == null ? VersionType.MAJOR : VersionType.valueOf(releaseType); ImportPetriNetEventOutcome importPetriNetOutcome = service.importPetriNet(new FileInputStream(file), release, (LoggedUser) auth.getPrincipal()); fout.close(); From 70574f9b05394757fac44ff847eb323676217a26 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 2 May 2022 13:52:40 +0200 Subject: [PATCH 13/68] [NAE-1617] Refactor Authority - implemented BaseAuthorizationService - reimplemented preauthorize in controllers - implemented interface for AbstractBaseAuthorizationService --- .../service/AbstractBaseAuthorizationService.java | 6 ++++-- .../auth/service/BaseAuthorizationService.java | 13 +++++++++++++ .../interfaces/IBaseAuthorizationService.java | 6 ++++++ .../engine/auth/web/UserController.java | 12 ++++++------ .../services/GroupAuthorizationService.java | 15 +++++++++++++++ .../interfaces/IGroupAuthorizationService.java | 7 +++++++ .../engine/orgstructure/web/GroupController.java | 4 +--- .../service/PetriNetAuthorizationService.java | 5 +++++ .../interfaces/IPetriNetAuthorizationService.java | 2 ++ .../engine/petrinet/web/PetriNetController.java | 2 +- .../engine/workflow/web/WorkflowController.java | 2 +- 11 files changed, 61 insertions(+), 13 deletions(-) create mode 100644 src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java create mode 100644 src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java create mode 100644 src/main/java/com/netgrif/application/engine/orgstructure/services/GroupAuthorizationService.java create mode 100644 src/main/java/com/netgrif/application/engine/orgstructure/services/interfaces/IGroupAuthorizationService.java diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java index 06a2f3491d..9683829e38 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java @@ -1,8 +1,9 @@ package com.netgrif.application.engine.auth.service; +import com.netgrif.application.engine.auth.service.interfaces.IBaseAuthorizationService; import com.netgrif.application.engine.auth.service.interfaces.IUserService; -public abstract class AbstractBaseAuthorizationService { +public abstract class AbstractBaseAuthorizationService implements IBaseAuthorizationService { private final IUserService userService; @@ -10,7 +11,8 @@ public AbstractBaseAuthorizationService(IUserService userService) { this.userService = userService; } - public boolean hasAuthority(String authority) { + @Override + public final boolean hasAuthority(String authority) { return this.userService.getLoggedUser().getAuthorities().stream().anyMatch(a -> a.getName().equals(authority)); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java new file mode 100644 index 0000000000..3880102837 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java @@ -0,0 +1,13 @@ +package com.netgrif.application.engine.auth.service; + +import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class BaseAuthorizationService extends AbstractBaseAuthorizationService { + + public BaseAuthorizationService(@Autowired IUserService userService) { + super(userService); + } +} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java new file mode 100644 index 0000000000..aca692b170 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java @@ -0,0 +1,6 @@ +package com.netgrif.application.engine.auth.service.interfaces; + +public interface IBaseAuthorizationService { + + boolean hasAuthority(String authority); +} diff --git a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java index 39e8db9b72..d28dbe2d9b 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java @@ -105,7 +105,7 @@ public PagedModel getAll(@RequestParam(value = "small", required = @ApiOperation(value = "Generic user search", authorizations = @Authorization("BasicAuth")) @PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public PagedModel search(@RequestParam(value = "small", required = false) Boolean small, @RequestBody UserSearchRequestBody query, Pageable pageable, PagedResourcesAssembler assembler, Authentication auth, Locale locale) { - small = small == null ? false : small; + small = small != null && small; List roles = query.getRoles() == null ? null : query.getRoles().stream().map(ObjectId::new).collect(Collectors.toList()); List negativeRoles = query.getNegativeRoles() == null ? null : query.getNegativeRoles().stream().map(ObjectId::new).collect(Collectors.toList()); Page page = userService.searchAllCoMembers(query.getFulltext(), @@ -135,7 +135,7 @@ public UserResource getUser(@PathVariable("id") String userId, @RequestParam(val @ApiOperation(value = "Get logged user", authorizations = @Authorization("BasicAuth")) @GetMapping(value = "/me", produces = MediaTypes.HAL_JSON_VALUE) public UserResource getLoggedUser(@RequestParam(value = "small", required = false) Boolean small, Authentication auth, Locale locale) { - small = small == null ? false : small; + small = small != null && small; if (!small) return new UserResource(userResponseFactory.getUser(userService.resolveById(((LoggedUser) auth.getPrincipal()).getId(), false), locale), "profile"); else @@ -165,7 +165,7 @@ public UserResource updateUser(@PathVariable("id") String userId, @RequestBody U @ApiOperation(value = "Get all users with specified roles", authorizations = @Authorization("BasicAuth")) @PostMapping(value = "/role", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public PagedModel getAllWithRole(@RequestBody Set roleIds, @RequestParam(value = "small", required = false) Boolean small, Pageable pageable, PagedResourcesAssembler assembler, Locale locale) { - small = small == null ? false : small; + small = small != null && small; Page page = userService.findAllActiveByProcessRoles(roleIds, small, pageable); Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(UserController.class) .getAllWithRole(roleIds, small, pageable, assembler, locale)).withRel("role"); @@ -174,7 +174,7 @@ public PagedModel getAllWithRole(@RequestBody Set roleIds, return resources; } - @PreAuthorize("hasRole('ADMIN')") + @PreAuthorize("@baseAuthorizationService.hasAuthority('ADMIN')") @ApiOperation(value = "Assign role to the user", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) @@ -194,7 +194,7 @@ public MessageResource assignRolesToUser(@PathVariable("id") String userId, @Req } } - @PreAuthorize("hasRole('ADMIN')") + @PreAuthorize("@baseAuthorizationService.hasAuthority('ADMIN')") @ApiOperation(value = "Get all authorities of the system", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) @@ -207,7 +207,7 @@ public AuthoritiesResources getAllAuthorities(Authentication auth) { return new AuthoritiesResources(authorityService.findAll()); } - @PreAuthorize("hasRole('ADMIN')") + @PreAuthorize("@baseAuthorizationService.hasAuthority('ADMIN')") @ApiOperation(value = "Assign authority to the user", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/services/GroupAuthorizationService.java b/src/main/java/com/netgrif/application/engine/orgstructure/services/GroupAuthorizationService.java new file mode 100644 index 0000000000..ee38c399b2 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/orgstructure/services/GroupAuthorizationService.java @@ -0,0 +1,15 @@ +package com.netgrif.application.engine.orgstructure.services; + +import com.netgrif.application.engine.auth.service.AbstractBaseAuthorizationService; +import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import com.netgrif.application.engine.orgstructure.services.interfaces.IGroupAuthorizationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class GroupAuthorizationService extends AbstractBaseAuthorizationService implements IGroupAuthorizationService { + + public GroupAuthorizationService(@Autowired IUserService userService) { + super(userService); + } +} diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/services/interfaces/IGroupAuthorizationService.java b/src/main/java/com/netgrif/application/engine/orgstructure/services/interfaces/IGroupAuthorizationService.java new file mode 100644 index 0000000000..100dfafa25 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/orgstructure/services/interfaces/IGroupAuthorizationService.java @@ -0,0 +1,7 @@ +package com.netgrif.application.engine.orgstructure.services.interfaces; + +import com.netgrif.application.engine.auth.service.interfaces.IBaseAuthorizationService; + +public interface IGroupAuthorizationService extends IBaseAuthorizationService { + +} diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java index 7876ae1d57..88607c794a 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java @@ -1,8 +1,6 @@ package com.netgrif.application.engine.orgstructure.web; -import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService; -import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.orgstructure.web.responsebodies.Group; import com.netgrif.application.engine.orgstructure.web.responsebodies.GroupsResource; import com.netgrif.application.engine.workflow.domain.Case; @@ -33,7 +31,7 @@ public class GroupController { @Autowired private INextGroupService service; - @PreAuthorize("hasRole('ADMIN')") + @PreAuthorize("@groupAuthorizationService.hasAuthority('ADMIN')") @ApiOperation(value = "Get all groups in the system", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java index be9d83692c..c29dc06ab9 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java @@ -14,6 +14,11 @@ public PetriNetAuthorizationService(@Autowired IUserService userService) { super(userService); } + @Override + public boolean canCallImport(LoggedUser loggedUser) { + return loggedUser.isAdmin(); + } + @Override public boolean canCallProcessDelete(LoggedUser loggedUser, String processId) { return loggedUser.isAdmin(); diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetAuthorizationService.java b/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetAuthorizationService.java index 2adb86c574..df1ab5a67b 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetAuthorizationService.java @@ -4,6 +4,8 @@ public interface IPetriNetAuthorizationService { + boolean canCallImport(LoggedUser loggedUser); + boolean canCallProcessDelete(LoggedUser loggedUser, String processId); } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index 49c4cc95fb..5f6d40f8c1 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -69,7 +69,7 @@ public class PetriNetController { @Autowired private StringToVersionConverter converter; - @PreAuthorize("@petriNetAuthorizationService.hasAuthority('ADMIN')") + @PreAuthorize("@petriNetAuthorizationService.canCallImport(#auth.principal)") @ApiOperation(value = "Import new process", notes = "Caller must have the ADMIN role. Imports an entirely new process or a new version of an existing process.", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java index 1835450e6d..c564be09f4 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java @@ -188,7 +188,7 @@ public MessageResource reloadTasks(@PathVariable("id") String caseId) { } @Deprecated - @PreAuthorize("hasRole('ADMIN')") + @PreAuthorize("@workflowAuthorizationService.hasAuthority('ADMIN')") @ApiOperation(value = "Get all case data", authorizations = @Authorization("BasicAuth")) @GetMapping(value = "/case/{id}/data", produces = MediaTypes.HAL_JSON_VALUE) public DataFieldsResource getAllCaseData(@PathVariable("id") String caseId, Locale locale) { From f022afc5836401670b067b0c17039e8bdff07954 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 3 May 2022 08:58:15 +0200 Subject: [PATCH 14/68] [NAE-1617] Refactor Authority - implemented new custom annotation for authorization - implemented preAuthorize in Authorize.java - reverted last commit when AbstractBaseAuthorizationService was included in WorkflowAuthorizationService - reimplemented check for authority domain --- .../engine/auth/domain/Authority.java | 4 ++-- .../engine/auth/domain/AuthorityEnum.java | 1 + .../engine/auth/domain/Authorize.java | 14 ++++++++++++++ .../AbstractBaseAuthorizationService.java | 5 +++-- .../auth/service/BaseAuthorizationService.java | 18 ++++++++++++++++++ .../interfaces/IBaseAuthorizationService.java | 4 +++- .../engine/auth/web/UserController.java | 8 +++++--- .../engine/elastic/web/ElasticController.java | 6 ++++-- .../orgstructure/web/GroupController.java | 4 +++- .../service/PetriNetAuthorizationService.java | 9 +-------- .../petrinet/web/PetriNetController.java | 4 +++- .../service/AbstractAuthorizationService.java | 8 +------- .../service/TaskAuthorizationService.java | 6 ------ .../service/WorkflowAuthorizationService.java | 4 ---- .../workflow/web/WorkflowController.java | 8 +++++--- 15 files changed, 63 insertions(+), 40 deletions(-) create mode 100644 src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java index 83158c6e45..662162afc6 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java @@ -86,7 +86,7 @@ public int hashCode() { return name.hashCode(); } - public boolean inDomain(AuthorityEnum domain) { - return this.name.startsWith(domain.name()) || this.name.equals(AuthorityEnum.ADMIN.name()); + public boolean includes(AuthorityEnum authority) { + return authority.name().equals(this.name) || authority.name().startsWith(this.name) || this.name.equals(AuthorityEnum.ADMIN.name()); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java index 0f62ee64b0..d23bfeb5e3 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java @@ -20,6 +20,7 @@ public enum AuthorityEnum { GROUP_DELETE, GROUP_ADD_USER, GROUP_REMOVE_USER, + GROUP_VIEW_ALL, ROLE_CREATE, ROLE_DELETE, AUTHORITY_CREATE, diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java new file mode 100644 index 0000000000..bd6eff81ac --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java @@ -0,0 +1,14 @@ +package com.netgrif.application.engine.auth.domain; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface Authorize { + + AuthorityEnum authority() default AuthorityEnum.ADMIN; + String preAuthorize() default ""; +} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java index 9683829e38..e4bfa6d059 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java @@ -1,5 +1,6 @@ package com.netgrif.application.engine.auth.service; +import com.netgrif.application.engine.auth.domain.AuthorityEnum; import com.netgrif.application.engine.auth.service.interfaces.IBaseAuthorizationService; import com.netgrif.application.engine.auth.service.interfaces.IUserService; @@ -12,7 +13,7 @@ public AbstractBaseAuthorizationService(IUserService userService) { } @Override - public final boolean hasAuthority(String authority) { - return this.userService.getLoggedUser().getAuthorities().stream().anyMatch(a -> a.getName().equals(authority)); + public final boolean hasAuthority(AuthorityEnum authority) { + return this.userService.getLoggedUser().getAuthorities().stream().anyMatch(a -> a.includes(authority)); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java index 3880102837..93088bd265 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java @@ -1,13 +1,31 @@ package com.netgrif.application.engine.auth.service; +import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.stereotype.Service; +@Slf4j +@Aspect @Service public class BaseAuthorizationService extends AbstractBaseAuthorizationService { public BaseAuthorizationService(@Autowired IUserService userService) { super(userService); } + + @Around("@annotation(authorize)") + @PreAuthorize("#authorize.preAuthorize()") + public Object authorize(ProceedingJoinPoint joinPoint, Authorize authorize) throws Throwable { + if (hasAuthority(authorize.authority())) { + return joinPoint.proceed(); + } else { + return null; + } + } } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java index aca692b170..2a749f23eb 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java @@ -1,6 +1,8 @@ package com.netgrif.application.engine.auth.service.interfaces; +import com.netgrif.application.engine.auth.domain.AuthorityEnum; + public interface IBaseAuthorizationService { - boolean hasAuthority(String authority); + boolean hasAuthority(AuthorityEnum authority); } diff --git a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java index d28dbe2d9b..e156a79a94 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java @@ -1,5 +1,7 @@ package com.netgrif.application.engine.auth.web; +import com.netgrif.application.engine.auth.domain.AuthorityEnum; +import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.domain.throwable.UnauthorisedRequestException; @@ -174,7 +176,7 @@ public PagedModel getAllWithRole(@RequestBody Set roleIds, return resources; } - @PreAuthorize("@baseAuthorizationService.hasAuthority('ADMIN')") + @Authorize(authority = AuthorityEnum.USER_EDIT) @ApiOperation(value = "Assign role to the user", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) @@ -194,7 +196,7 @@ public MessageResource assignRolesToUser(@PathVariable("id") String userId, @Req } } - @PreAuthorize("@baseAuthorizationService.hasAuthority('ADMIN')") + @Authorize(authority = AuthorityEnum.ADMIN) @ApiOperation(value = "Get all authorities of the system", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) @@ -207,7 +209,7 @@ public AuthoritiesResources getAllAuthorities(Authentication auth) { return new AuthoritiesResources(authorityService.findAll()); } - @PreAuthorize("@baseAuthorizationService.hasAuthority('ADMIN')") + @Authorize(authority = AuthorityEnum.USER_EDIT) @ApiOperation(value = "Assign authority to the user", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java b/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java index fdf39aeb03..023293d96f 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java +++ b/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java @@ -1,5 +1,7 @@ package com.netgrif.application.engine.elastic.web; +import com.netgrif.application.engine.auth.domain.AuthorityEnum; +import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.elastic.service.ReindexingTask; import com.netgrif.application.engine.workflow.service.CaseSearchService; @@ -48,7 +50,7 @@ public class ElasticController { @Value("${spring.data.elasticsearch.reindex-size}") private int pageSize; - @PreAuthorize("hasRole('ADMIN')") + @Authorize(authority = AuthorityEnum.ADMIN) @ApiOperation(value = "Reindex specified cases", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) @@ -65,7 +67,7 @@ public MessageResource reindex(@RequestBody Map searchBody, Auth if (count == 0) { log.info("No cases to reindex"); } else { - long numOfPages = (long) ((count / pageSize) + 1); + long numOfPages = (count / pageSize) + 1; log.info("Reindexing cases: " + numOfPages + " pages"); for (int page = 0; page < numOfPages; page++) { diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java index 88607c794a..c34bbb5b3b 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java @@ -1,5 +1,7 @@ package com.netgrif.application.engine.orgstructure.web; +import com.netgrif.application.engine.auth.domain.AuthorityEnum; +import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService; import com.netgrif.application.engine.orgstructure.web.responsebodies.Group; import com.netgrif.application.engine.orgstructure.web.responsebodies.GroupsResource; @@ -31,7 +33,7 @@ public class GroupController { @Autowired private INextGroupService service; - @PreAuthorize("@groupAuthorizationService.hasAuthority('ADMIN')") + @Authorize(authority = AuthorityEnum.GROUP_VIEW_ALL) @ApiOperation(value = "Get all groups in the system", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java index c29dc06ab9..45657c9dd1 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java @@ -1,18 +1,11 @@ package com.netgrif.application.engine.petrinet.service; import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.AbstractBaseAuthorizationService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetAuthorizationService; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service -public class PetriNetAuthorizationService extends AbstractBaseAuthorizationService implements IPetriNetAuthorizationService { - - public PetriNetAuthorizationService(@Autowired IUserService userService) { - super(userService); - } +public class PetriNetAuthorizationService implements IPetriNetAuthorizationService { @Override public boolean canCallImport(LoggedUser loggedUser) { diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index 5f6d40f8c1..fcad5691f2 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -1,5 +1,7 @@ package com.netgrif.application.engine.petrinet.web; +import com.netgrif.application.engine.auth.domain.AuthorityEnum; +import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.eventoutcomes.LocalisedEventOutcomeFactory; import com.netgrif.application.engine.importer.service.Importer; @@ -69,7 +71,7 @@ public class PetriNetController { @Autowired private StringToVersionConverter converter; - @PreAuthorize("@petriNetAuthorizationService.canCallImport(#auth.principal)") + @Authorize(authority = AuthorityEnum.PROCESS_UPLOAD) @ApiOperation(value = "Import new process", notes = "Caller must have the ADMIN role. Imports an entirely new process or a new version of an existing process.", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationService.java b/src/main/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationService.java index 6642f03ba9..19530c522d 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationService.java @@ -1,19 +1,13 @@ package com.netgrif.application.engine.workflow.service; import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.service.AbstractBaseAuthorizationService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; -public abstract class AbstractAuthorizationService extends AbstractBaseAuthorizationService { - - public AbstractAuthorizationService(IUserService userService) { - super(userService); - } +public abstract class AbstractAuthorizationService { protected boolean hasPermission(Boolean hasPermission) { return hasPermission != null && hasPermission; diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/TaskAuthorizationService.java b/src/main/java/com/netgrif/application/engine/workflow/service/TaskAuthorizationService.java index 42f3a10691..4484ed9e72 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/TaskAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/TaskAuthorizationService.java @@ -3,8 +3,6 @@ import com.netgrif.application.engine.auth.domain.AnonymousUser; import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.UserService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.petrinet.domain.roles.RolePermission; import com.netgrif.application.engine.petrinet.domain.throwable.IllegalTaskStateException; import com.netgrif.application.engine.workflow.domain.Task; @@ -22,10 +20,6 @@ public class TaskAuthorizationService extends AbstractAuthorizationService imple @Autowired ITaskService taskService; - public TaskAuthorizationService(@Autowired IUserService userService) { - super(userService); - } - @Override public Boolean userHasAtLeastOneRolePermission(LoggedUser loggedUser, String taskId, RolePermission... permissions) { return userHasAtLeastOneRolePermission(loggedUser.transformToUser(), taskService.findById(taskId), permissions); diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowAuthorizationService.java b/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowAuthorizationService.java index 9489e5d942..9928223784 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowAuthorizationService.java @@ -2,7 +2,6 @@ import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.petrinet.domain.PetriNet; import com.netgrif.application.engine.petrinet.domain.roles.ProcessRolePermission; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; @@ -24,9 +23,6 @@ public class WorkflowAuthorizationService extends AbstractAuthorizationService i @Autowired private IPetriNetService petriNetService; - public WorkflowAuthorizationService(@Autowired IUserService userService) { - super(userService); - } @Override public boolean canCallDelete(LoggedUser user, String caseId) { diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java index c564be09f4..246995d39d 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java @@ -1,5 +1,7 @@ package com.netgrif.application.engine.workflow.web; +import com.netgrif.application.engine.auth.domain.AuthorityEnum; +import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.elastic.domain.ElasticCase; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; @@ -165,7 +167,7 @@ public PagedModel findAllByAuthor(@PathVariable("id") String autho return resources; } - @PreAuthorize("hasRole('ADMIN')") + @Authorize(authority = AuthorityEnum.ADMIN) @ApiOperation(value = "Reload tasks of case", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) @@ -188,7 +190,7 @@ public MessageResource reloadTasks(@PathVariable("id") String caseId) { } @Deprecated - @PreAuthorize("@workflowAuthorizationService.hasAuthority('ADMIN')") + @Authorize(authority = AuthorityEnum.ADMIN) @ApiOperation(value = "Get all case data", authorizations = @Authorization("BasicAuth")) @GetMapping(value = "/case/{id}/data", produces = MediaTypes.HAL_JSON_VALUE) public DataFieldsResource getAllCaseData(@PathVariable("id") String caseId, Locale locale) { @@ -201,7 +203,7 @@ public DataFieldsResource getAllCaseData(@PathVariable("id") String caseId, Loca } } - @PreAuthorize("@workflowAuthorizationService.canCallDelete(#auth.getPrincipal(), #caseId)") + @Authorize(preAuthorize = "@workflowAuthorizationService.canCallDelete(#auth.getPrincipal(), #caseId)") @ApiOperation(value = "Delete case", authorizations = @Authorization("BasicAuth")) @DeleteMapping(value = "/case/{id}", produces = MediaTypes.HAL_JSON_VALUE) public EntityModel deleteCase(Authentication auth, @PathVariable("id") String caseId, @RequestParam(defaultValue = "false") boolean deleteSubtree) { From bd79076e0737b6bbb327f4a1668c4a594bc189b4 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Wed, 4 May 2022 11:32:41 +0200 Subject: [PATCH 15/68] [NAE-1617] Refactor Authority - implemented expression in Authorize annotation - implemented aspect and advise in BaseAuthorizationService - implemented use of PetriNetController --- pom.xml | 7 ++++ .../engine/auth/domain/Authorize.java | 15 ++++--- .../AuthorityAuthorizationService.java | 16 -------- .../service/BaseAuthorizationService.java | 41 +++++++++++++++++-- .../petrinet/web/PetriNetController.java | 3 +- .../workflow/web/WorkflowController.java | 2 +- 6 files changed, 55 insertions(+), 29 deletions(-) delete mode 100644 src/main/java/com/netgrif/application/engine/auth/service/AuthorityAuthorizationService.java diff --git a/pom.xml b/pom.xml index aefa919fc0..84751f67df 100644 --- a/pom.xml +++ b/pom.xml @@ -415,6 +415,13 @@ 2.2.0-rc2 + + + org.jetbrains + annotations + 23.0.0 + + org.springframework.boot diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java index bd6eff81ac..47b6497b00 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java @@ -1,14 +1,17 @@ package com.netgrif.application.engine.auth.domain; -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; +import org.intellij.lang.annotations.Language; + +import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.METHOD) +@Target({ ElementType.METHOD, ElementType.TYPE }) +@Inherited +@Documented public @interface Authorize { AuthorityEnum authority() default AuthorityEnum.ADMIN; - String preAuthorize() default ""; + + @Language("SpEL") + String expression() default ""; } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityAuthorizationService.java deleted file mode 100644 index 09afbb0db8..0000000000 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityAuthorizationService.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.netgrif.application.engine.auth.service; - -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityAuthorizationService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.workflow.service.AbstractAuthorizationService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class AuthorityAuthorizationService extends AbstractAuthorizationService implements IAuthorityAuthorizationService { - - public AuthorityAuthorizationService(@Autowired IUserService userService) { - super(userService); - } - -} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java index 93088bd265..fc31e052f2 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java @@ -2,14 +2,25 @@ import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import com.netgrif.application.engine.configuration.ApplicationContextProvider; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.context.expression.BeanFactoryResolver; +import org.springframework.expression.EvaluationException; +import org.springframework.expression.ExpressionParser; +import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.security.access.expression.ExpressionUtils; import org.springframework.stereotype.Service; +import java.util.Arrays; +import java.util.List; + @Slf4j @Aspect @Service @@ -19,13 +30,35 @@ public BaseAuthorizationService(@Autowired IUserService userService) { super(userService); } - @Around("@annotation(authorize)") - @PreAuthorize("#authorize.preAuthorize()") + @Pointcut(value = "@annotation(authorize) && execution(* *(.., org.springframework.security.core.Authentication, ..))") + private void authorizingMethod(Authorize authorize) {} + + @Around(value = "authorizingMethod(authorize)", argNames = "joinPoint,authorize") public Object authorize(ProceedingJoinPoint joinPoint, Authorize authorize) throws Throwable { - if (hasAuthority(authorize.authority())) { + if (isAllowed(joinPoint, authorize.expression()) && hasAuthority(authorize.authority())) { return joinPoint.proceed(); } else { return null; } } + + private boolean isAllowed(ProceedingJoinPoint joinPoint, String expression) { + ExpressionParser parser = new SpelExpressionParser(); + StandardEvaluationContext context = new StandardEvaluationContext(); + context.setBeanResolver(new BeanFactoryResolver(ApplicationContextProvider.getAppContext())); + + List args = Arrays.asList(joinPoint.getArgs()); + List argNames = Arrays.asList(((MethodSignature) joinPoint.getSignature()).getParameterNames()); + + argNames.forEach(name -> context.setVariable(name, args.get(argNames.indexOf(name)))); + + boolean allowed; + try { + allowed = ExpressionUtils.evaluateAsBoolean(parser.parseExpression(expression), context); + return allowed; + } catch (EvaluationException | NullPointerException e) { + log.warn("Failed to parse expression '" + expression + "'."); + return false; + } + } } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index fcad5691f2..1d573de5b2 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -1,6 +1,5 @@ package com.netgrif.application.engine.petrinet.web; -import com.netgrif.application.engine.auth.domain.AuthorityEnum; import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.eventoutcomes.LocalisedEventOutcomeFactory; @@ -71,7 +70,7 @@ public class PetriNetController { @Autowired private StringToVersionConverter converter; - @Authorize(authority = AuthorityEnum.PROCESS_UPLOAD) + @Authorize(expression = "@petriNetAuthorizationService.canCallImport(#auth.getPrincipal())") @ApiOperation(value = "Import new process", notes = "Caller must have the ADMIN role. Imports an entirely new process or a new version of an existing process.", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java index 246995d39d..7c9d3a0e52 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java @@ -203,7 +203,7 @@ public DataFieldsResource getAllCaseData(@PathVariable("id") String caseId, Loca } } - @Authorize(preAuthorize = "@workflowAuthorizationService.canCallDelete(#auth.getPrincipal(), #caseId)") + @Authorize(expression = "@workflowAuthorizationService.canCallDelete(#auth.getPrincipal(), #caseId)") @ApiOperation(value = "Delete case", authorizations = @Authorization("BasicAuth")) @DeleteMapping(value = "/case/{id}", produces = MediaTypes.HAL_JSON_VALUE) public EntityModel deleteCase(Authentication auth, @PathVariable("id") String caseId, @RequestParam(defaultValue = "false") boolean deleteSubtree) { From 043e4785e5e8bebd13e31d4ebb6cd055a09159e2 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Wed, 4 May 2022 13:33:41 +0200 Subject: [PATCH 16/68] [NAE-1617] Refactor Authority - refactored @PreAuthorize to @Authorize in PetriNetController --- .../application/engine/petrinet/web/PetriNetController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index 1d573de5b2..48752be68c 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -179,7 +179,7 @@ PagedModel searchPetriNets(@RequestBody Map Date: Wed, 4 May 2022 13:41:09 +0200 Subject: [PATCH 17/68] [NAE-1617] Refactor Authority - refactored @PreAuthorise to @Authorise in all controllers. --- .../petrinet/web/PetriNetController.java | 1 - .../workflow/web/PublicTaskController.java | 14 ++++++------- .../web/PublicWorkflowController.java | 3 ++- .../engine/workflow/web/TaskController.java | 20 +++++++++---------- .../workflow/web/WorkflowController.java | 2 +- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index 48752be68c..6d62606c91 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -32,7 +32,6 @@ import org.springframework.hateoas.PagedModel; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; import org.springframework.http.MediaType; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java b/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java index d8390bf91f..e9aec6ee6b 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.workflow.web; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.petrinet.domain.dataset.logic.ChangedFieldByFileFieldContainer; @@ -25,7 +26,6 @@ import org.springframework.hateoas.PagedModel; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -59,7 +59,7 @@ public List getTasksOfCase(@PathVariable("id") String caseId, Loc return this.taskService.findAllByCase(caseId, locale); } - @PreAuthorize("@taskAuthorizationService.canCallAssign(@userService.getAnonymousLogged(), #taskId)") + @Authorize(expression = "@taskAuthorizationService.canCallAssign(@userService.getAnonymousLogged(), #taskId)") @GetMapping(value = "/assign/{id}", produces = MediaTypes.HAL_JSON_VALUE) @ApiOperation(value = "Assign task", notes = "Caller must be able to perform the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -75,7 +75,7 @@ public EntityModel assign(@PathVariable("id") String ta return super.assign(loggedUser, taskId, locale); } - @PreAuthorize("@taskAuthorizationService.canCallFinish(@userService.getAnonymousLogged(), #taskId)") + @Authorize(expression = "@taskAuthorizationService.canCallFinish(@userService.getAnonymousLogged(), #taskId)") @GetMapping(value = "/finish/{id}", produces = MediaTypes.HAL_JSON_VALUE) @ApiOperation(value = "Finish task", notes = "Caller must be assigned to the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -91,7 +91,7 @@ public EntityModel finish(@PathVariable("id") String ta return super.finish(loggedUser, taskId, locale); } - @PreAuthorize("@taskAuthorizationService.canCallCancel(@userService.getAnonymousLogged(), #taskId)") + @Authorize(expression = "@taskAuthorizationService.canCallCancel(@userService.getAnonymousLogged(), #taskId)") @GetMapping(value = "/cancel/{id}", produces = MediaTypes.HAL_JSON_VALUE) @ApiOperation(value = "Cancel task", notes = "Caller must be assigned to the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -113,7 +113,7 @@ public EntityModel getData(@PathVariable("id") String t return super.getData(taskId, locale); } - @PreAuthorize("@taskAuthorizationService.canCallSaveData(@userService.getAnonymousLogged(), #taskId)") + @Authorize(expression = "@taskAuthorizationService.canCallSaveData(@userService.getAnonymousLogged(), #taskId)") @PostMapping(value = "/{id}/data", consumes = "application/json;charset=UTF-8", produces = "application/json;charset=UTF-8") @ApiOperation(value = "Set task data", notes = "Caller must be assigned to the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -128,7 +128,7 @@ public EntityModel setData(@PathVariable("id") String t return super.setData(taskId, dataBody); } - @PreAuthorize("@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") @ApiOperation(value = "Upload file into the task", notes = "Caller must be assigned to the task, or must be an ADMIN") @RequestMapping(value = "/{id}/file/{field}", method = RequestMethod.POST, produces = MediaTypes.HAL_JSON_VALUE) @@ -164,7 +164,7 @@ public ResponseEntity getFilePreview(@PathVariable("id") String taskId return super.getFilePreview(taskId, fieldId); } - @PreAuthorize("@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") @ApiOperation(value = "Upload multiple files into the task", notes = "Caller must be assigned to the task, or must be an ADMIN") @RequestMapping(value = "/{id}/files/{field}", method = RequestMethod.POST, produces = MediaTypes.HAL_JSON_VALUE) diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java b/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java index 9c045bae51..a764872472 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java @@ -1,5 +1,6 @@ package com.netgrif.application.engine.workflow.web; +import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.eventoutcomes.LocalisedEventOutcomeFactory; @@ -34,7 +35,7 @@ public PublicWorkflowController(IWorkflowService workflowService, IUserService u this.workflowService = workflowService; } - @PreAuthorize("@workflowAuthorizationService.canCallCreate(@userService.getAnonymousLogged(), #body.netId)") + @Authorize(expression = "@workflowAuthorizationService.canCallCreate(@userService.getAnonymousLogged(), #body.netId)") @PostMapping(value = "/case", consumes = "application/json;charset=UTF-8", produces = MediaTypes.HAL_JSON_VALUE) @ApiOperation(value = "Create new case") public EntityModel createCase(@RequestBody CreateCaseBody body, Locale locale) { diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java b/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java index b441b6e0fe..91ccec6aea 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.workflow.web; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService; import com.netgrif.application.engine.elastic.web.requestbodies.singleaslist.SingleElasticTaskSearchRequestAsList; @@ -27,7 +28,6 @@ import org.springframework.hateoas.PagedModel; 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 org.springframework.web.multipart.MultipartFile; @@ -82,7 +82,7 @@ public LocalisedTaskResource getOne(@PathVariable("id") String taskId, Locale lo return super.getOne(taskId, locale); } - @PreAuthorize("@taskAuthorizationService.canCallAssign(#auth.getPrincipal(), #taskId)") + @Authorize(expression = "@taskAuthorizationService.canCallAssign(#auth.getPrincipal(), #taskId)") @ApiOperation(value = "Assign task", notes = "Caller must be able to perform the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) @@ -96,7 +96,7 @@ public EntityModel assign(Authentication auth, @PathVar return super.assign(loggedUser, taskId, locale); } - @PreAuthorize("@taskAuthorizationService.canCallDelegate(#auth.getPrincipal(), #taskId)") + @Authorize(expression = "@taskAuthorizationService.canCallDelegate(#auth.getPrincipal(), #taskId)") @ApiOperation(value = "Delegate task", notes = "Caller must be able to delegate the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) @@ -110,7 +110,7 @@ public EntityModel delegate(Authentication auth, @Path return super.delegate(loggedUser, taskId, delegatedId, locale); } - @PreAuthorize("@taskAuthorizationService.canCallFinish(#auth.getPrincipal(), #taskId)") + @Authorize(expression = "@taskAuthorizationService.canCallFinish(#auth.getPrincipal(), #taskId)") @ApiOperation(value = "Finish task", notes = "Caller must be assigned to the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) @@ -124,7 +124,7 @@ public EntityModel finish(Authentication auth, @PathVa return super.finish(loggedUser, taskId, locale); } - @PreAuthorize("@taskAuthorizationService.canCallCancel(#auth.getPrincipal(), #taskId)") + @Authorize(expression = "@taskAuthorizationService.canCallCancel(#auth.getPrincipal(), #taskId)") @ApiOperation(value = "Cancel task", notes = "Caller must be assigned to the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) @@ -180,7 +180,7 @@ public EntityModel getData(@PathVariable("id") String return super.getData(taskId, locale); } - @PreAuthorize("@taskAuthorizationService.canCallSaveData(#auth.getPrincipal(), #taskId)") + @Authorize(expression = "@taskAuthorizationService.canCallSaveData(#auth.getPrincipal(), #taskId)") @ApiOperation(value = "Set task data", notes = "Caller must be assigned to the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) @@ -193,7 +193,7 @@ public EntityModel setData(Authentication auth, @PathV return super.setData(taskId, dataBody); } - @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") @ApiOperation(value = "Upload file into the task", notes = "Caller must be assigned to the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) @@ -213,7 +213,7 @@ public ResponseEntity getFile(@PathVariable("id") String taskId, @Path return super.getFile(taskId, fieldId); } - @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") @ApiOperation(value = "Remove file from the task", notes = "Caller must be assigned to the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) @@ -226,7 +226,7 @@ public MessageResource deleteFile(Authentication auth, @PathVariable("id") Strin return super.deleteFile(taskId, fieldId); } - @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") @ApiOperation(value = "Upload multiple files into the task", notes = "Caller must be assigned to the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) @@ -247,7 +247,7 @@ public ResponseEntity getNamedFile(@PathVariable("id") String taskId, return super.getNamedFile(taskId, fieldId, name); } - @PreAuthorize("@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") @ApiOperation(value = "Remove file from tasks file list field value", notes = "Caller must be assigned to the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java index 7c9d3a0e52..fe67451842 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java @@ -77,7 +77,7 @@ public class WorkflowController { private IDataService dataService; - @PreAuthorize("@workflowAuthorizationService.canCallCreate(#auth.getPrincipal(), #body.netId)") + @Authorize(expression = "@workflowAuthorizationService.canCallCreate(#auth.getPrincipal(), #body.netId)") @ApiOperation(value = "Create new case", authorizations = @Authorization("BasicAuth")) @PostMapping(value = "/case", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public EntityModel createCase(@RequestBody CreateCaseBody body, Authentication auth, Locale locale) { From 361e6609841b4ad02ea4f6583bdf5f28d02d9d41 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Wed, 4 May 2022 13:41:48 +0200 Subject: [PATCH 18/68] [NAE-1617] Refactor Authority - removed unused import. --- .../engine/workflow/web/PublicWorkflowController.java | 1 - .../application/engine/workflow/web/WorkflowController.java | 1 - 2 files changed, 2 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java b/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java index a764872472..91650e793c 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java @@ -13,7 +13,6 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.MediaTypes; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java index fe67451842..258ca4307e 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java @@ -40,7 +40,6 @@ import org.springframework.http.HttpHeaders; 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.*; From 1c090f2f429e3bdb77dd7e82ed9492b2ff2ac68c Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Wed, 4 May 2022 13:46:33 +0200 Subject: [PATCH 19/68] [NAE-1617] Refactor Authority - refactored filtering for @Authorize join point --- .../engine/auth/service/BaseAuthorizationService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java index fc31e052f2..0dfe2012c7 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java @@ -30,7 +30,7 @@ public BaseAuthorizationService(@Autowired IUserService userService) { super(userService); } - @Pointcut(value = "@annotation(authorize) && execution(* *(.., org.springframework.security.core.Authentication, ..))") + @Pointcut(value = "@annotation(authorize))") private void authorizingMethod(Authorize authorize) {} @Around(value = "authorizingMethod(authorize)", argNames = "joinPoint,authorize") From d93846c4f78d3817f7522c4017832cdfc891e274 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Wed, 4 May 2022 14:21:25 +0200 Subject: [PATCH 20/68] [NAE-1617] Refactor Authority - implemented authorization for several methods in ActionDelegate --- .../domain/dataset/logic/action/ActionDelegate.groovy | 8 ++++++++ .../engine/auth/service/BaseAuthorizationService.java | 4 ++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy index a39bc311d3..19daca34b9 100644 --- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy @@ -2,6 +2,8 @@ package com.netgrif.application.engine.petrinet.domain.dataset.logic.action import com.netgrif.application.engine.AsyncRunner import com.netgrif.application.engine.auth.domain.Author +import com.netgrif.application.engine.auth.domain.AuthorityEnum +import com.netgrif.application.engine.auth.domain.Authorize import com.netgrif.application.engine.auth.domain.IUser import com.netgrif.application.engine.auth.service.UserDetailsServiceImpl import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService @@ -842,6 +844,7 @@ class ActionDelegate { mailService.sendMail(mailDraft) } + @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.getLoggedUser().getEmail().equals(#email)") def changeUserByEmail(String email) { [email : { cl -> changeUserByEmail(email, "email", cl) @@ -858,6 +861,7 @@ class ActionDelegate { ] } + @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.getLoggedUser().getStringId().equals(#id)") def changeUser(String id) { [email : { cl -> changeUser(id, "email", cl) @@ -874,6 +878,7 @@ class ActionDelegate { ] } + @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.getLoggedUser().getStringId().equals(#user.getStringId())") def changeUser(IUser user) { [email : { cl -> changeUser(user, "email", cl) @@ -890,16 +895,19 @@ class ActionDelegate { ] } + @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.getLoggedUser().getEmail().equals(#email)") def changeUserByEmail(String email, String attribute, def cl) { IUser user = userService.findByEmail(email, false) changeUser(user, attribute, cl) } + @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.getLoggedUser().getStringId().equals(#id)") def changeUser(String id, String attribute, def cl) { IUser user = userService.findById(id, false) changeUser(user, attribute, cl) } + @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.getLoggedUser().getStringId().equals(#user.getStringId())") def changeUser(IUser user, String attribute, def cl) { if (user == null) { log.error("Cannot find user.") diff --git a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java index 0dfe2012c7..035f6f8307 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java @@ -35,14 +35,14 @@ private void authorizingMethod(Authorize authorize) {} @Around(value = "authorizingMethod(authorize)", argNames = "joinPoint,authorize") public Object authorize(ProceedingJoinPoint joinPoint, Authorize authorize) throws Throwable { - if (isAllowed(joinPoint, authorize.expression()) && hasAuthority(authorize.authority())) { + if (isAllowedByExpression(joinPoint, authorize.expression()) || hasAuthority(authorize.authority())) { return joinPoint.proceed(); } else { return null; } } - private boolean isAllowed(ProceedingJoinPoint joinPoint, String expression) { + private boolean isAllowedByExpression(ProceedingJoinPoint joinPoint, String expression) { ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); context.setBeanResolver(new BeanFactoryResolver(ApplicationContextProvider.getAppContext())); From bf5ae4063365eabb0a242f37509467b6b7b6682f Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Thu, 5 May 2022 10:09:50 +0200 Subject: [PATCH 21/68] [NAE-1617] Refactor Authority - implemented isLogged functions in UserServices --- .../dataset/logic/action/ActionDelegate.groovy | 12 ++++++------ .../engine/auth/service/AbstractUserService.java | 15 +++++++++++++++ .../auth/service/interfaces/IUserService.java | 6 ++++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy index 19daca34b9..b0de53a548 100644 --- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy @@ -844,7 +844,7 @@ class ActionDelegate { mailService.sendMail(mailDraft) } - @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.getLoggedUser().getEmail().equals(#email)") + @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.isLoggedByEmail(email)") def changeUserByEmail(String email) { [email : { cl -> changeUserByEmail(email, "email", cl) @@ -861,7 +861,7 @@ class ActionDelegate { ] } - @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.getLoggedUser().getStringId().equals(#id)") + @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.isLogged(#id)") def changeUser(String id) { [email : { cl -> changeUser(id, "email", cl) @@ -878,7 +878,7 @@ class ActionDelegate { ] } - @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.getLoggedUser().getStringId().equals(#user.getStringId())") + @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.isLogged(#user)") def changeUser(IUser user) { [email : { cl -> changeUser(user, "email", cl) @@ -895,19 +895,19 @@ class ActionDelegate { ] } - @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.getLoggedUser().getEmail().equals(#email)") + @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.isLoggedByEmail(#email)") def changeUserByEmail(String email, String attribute, def cl) { IUser user = userService.findByEmail(email, false) changeUser(user, attribute, cl) } - @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.getLoggedUser().getStringId().equals(#id)") + @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.isLogged(#id)") def changeUser(String id, String attribute, def cl) { IUser user = userService.findById(id, false) changeUser(user, attribute, cl) } - @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.getLoggedUser().getStringId().equals(#user.getStringId())") + @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.isLogged(#user)") def changeUser(IUser user, String attribute, def cl) { if (user == null) { log.error("Cannot find user.") diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java index 691adfdd96..a7fe79836f 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java @@ -119,6 +119,21 @@ public boolean hasAuthority(IUser user, String authority) { return user.getAuthorities().stream().anyMatch(a -> a.getName().equals(authority)); } + @Override + public boolean isLoggedByEmail(String email) { + return this.getLoggedUser().getEmail().equals(email); + } + + @Override + public boolean isLogged(String id) { + return this.getLoggedUser().getStringId().equals(id); + } + + @Override + public boolean isLogged(IUser user) { + return isLogged(user.getStringId()); + } + public Page changeType(Page users, Pageable pageable) { return new PageImpl<>(changeType(users.getContent()), pageable, users.getTotalElements()); } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserService.java index 9ffada008f..af8ab5e544 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserService.java @@ -77,4 +77,10 @@ public interface IUserService { boolean hasAuthority(IUser user, Authority authority); boolean hasAuthority(IUser user, String authority); + + boolean isLoggedByEmail(String email); + + boolean isLogged(String id); + + boolean isLogged(IUser user); } \ No newline at end of file From d07bb75a644578fc73d014629a971ca7e1a2872c Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Thu, 5 May 2022 12:56:45 +0200 Subject: [PATCH 22/68] [NAE-1617] Refactor Authority - documentation - renamed AuthorityEnum.java to AuthorizingObject.java --- .../logic/action/ActionDelegate.groovy | 14 ++++----- .../engine/startup/AuthorityRunner.groovy | 4 +-- .../engine/startup/ImportHelper.groovy | 2 +- .../engine/startup/SuperCreator.groovy | 2 +- .../engine/auth/domain/Authority.java | 8 ++--- .../engine/auth/domain/Authorize.java | 11 ++++++- ...horityEnum.java => AuthorizingObject.java} | 7 ++++- .../engine/auth/domain/LoggedUser.java | 2 +- .../AbstractBaseAuthorizationService.java | 4 +-- .../engine/auth/service/AuthorityService.java | 8 ++--- .../service/BaseAuthorizationService.java | 29 +++++++++++++++++-- .../engine/auth/service/UserService.java | 2 +- .../service/interfaces/IAuthorityService.java | 6 ++-- .../interfaces/IBaseAuthorizationService.java | 4 +-- .../engine/auth/web/UserController.java | 9 +++--- .../configuration/SecurityConfiguration.java | 4 +-- .../SecurityConfigurationLdap.java | 4 +-- .../engine/elastic/web/ElasticController.java | 5 ++-- .../orgstructure/web/GroupController.java | 5 ++-- .../workflow/web/WorkflowController.java | 6 ++-- .../engine/action/AssignActionTest.groovy | 4 +-- .../engine/action/RemoveActionTest.groovy | 4 +-- .../auth/TaskAuthorizationServiceTest.groovy | 4 +-- .../event/GroovyShellFactoryTest.groovy | 4 +-- 24 files changed, 94 insertions(+), 58 deletions(-) rename src/main/java/com/netgrif/application/engine/auth/domain/{AuthorityEnum.java => AuthorizingObject.java} (59%) diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy index b0de53a548..6b5ba8044a 100644 --- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy @@ -2,7 +2,7 @@ package com.netgrif.application.engine.petrinet.domain.dataset.logic.action import com.netgrif.application.engine.AsyncRunner import com.netgrif.application.engine.auth.domain.Author -import com.netgrif.application.engine.auth.domain.AuthorityEnum +import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.Authorize import com.netgrif.application.engine.auth.domain.IUser import com.netgrif.application.engine.auth.service.UserDetailsServiceImpl @@ -844,7 +844,7 @@ class ActionDelegate { mailService.sendMail(mailDraft) } - @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.isLoggedByEmail(email)") + @Authorize(authority = AuthorizingObject.ADMIN, expression = "@userService.isLoggedByEmail(email)") def changeUserByEmail(String email) { [email : { cl -> changeUserByEmail(email, "email", cl) @@ -861,7 +861,7 @@ class ActionDelegate { ] } - @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.isLogged(#id)") + @Authorize(authority = AuthorizingObject.ADMIN, expression = "@userService.isLogged(#id)") def changeUser(String id) { [email : { cl -> changeUser(id, "email", cl) @@ -878,7 +878,7 @@ class ActionDelegate { ] } - @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.isLogged(#user)") + @Authorize(authority = AuthorizingObject.ADMIN, expression = "@userService.isLogged(#user)") def changeUser(IUser user) { [email : { cl -> changeUser(user, "email", cl) @@ -895,19 +895,19 @@ class ActionDelegate { ] } - @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.isLoggedByEmail(#email)") + @Authorize(authority = AuthorizingObject.ADMIN, expression = "@userService.isLoggedByEmail(#email)") def changeUserByEmail(String email, String attribute, def cl) { IUser user = userService.findByEmail(email, false) changeUser(user, attribute, cl) } - @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.isLogged(#id)") + @Authorize(authority = AuthorizingObject.ADMIN, expression = "@userService.isLogged(#id)") def changeUser(String id, String attribute, def cl) { IUser user = userService.findById(id, false) changeUser(user, attribute, cl) } - @Authorize(authority = AuthorityEnum.ADMIN, expression = "@userService.isLogged(#user)") + @Authorize(authority = AuthorizingObject.ADMIN, expression = "@userService.isLogged(#user)") def changeUser(IUser user, String attribute, def cl) { if (user == null) { log.error("Cannot find user.") diff --git a/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy index 6e2111edfd..b6b79f5b02 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy @@ -1,6 +1,6 @@ package com.netgrif.application.engine.startup -import com.netgrif.application.engine.auth.domain.AuthorityEnum +import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService import org.springframework.beans.factory.annotation.Autowired import org.springframework.stereotype.Component @@ -13,6 +13,6 @@ class AuthorityRunner extends AbstractOrderedCommandLineRunner { @Override void run(String... strings) throws Exception { - AuthorityEnum.values().toList().forEach(authority -> service.getOrCreate(authority.name())) + AuthorizingObject.values().toList().forEach(authority -> service.getOrCreate(authority.name())) } } \ No newline at end of file diff --git a/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy b/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy index df59bfad08..dabcab6de3 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy @@ -91,7 +91,7 @@ class ImportHelper { @SuppressWarnings("GroovyAssignabilityCheck") - Map> createAuthorities(Map> authorities) { + Map> createAuthorities(Map> authorities) { HashMap> authoritities = new HashMap<>() authorities.each { authority -> authoritities.put(authority.key, new ArrayList()) diff --git a/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy b/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy index 4499c6390b..0bf6ec7a2e 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy @@ -43,7 +43,7 @@ class SuperCreator extends AbstractOrderedCommandLineRunner { } private IUser createSuperUser() { - Authority adminAuthority = authorityService.getOrCreate(AuthorityEnum.ADMIN) + Authority adminAuthority = authorityService.getOrCreate(AuthorizingObject.ADMIN) IUser superUser = userService.findByEmail("super@netgrif.com", false) if (superUser == null) { diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java index 662162afc6..e79f685149 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java @@ -16,7 +16,7 @@ public class Authority implements GrantedAuthority { public static final long serialVersionUID = 2839744057647464485L; - public static final List defaultUserAuthorities = Arrays.asList(AuthorityEnum.FILTER, AuthorityEnum.GROUP); + public static final List defaultUserAuthorities = Arrays.asList(AuthorizingObject.FILTER, AuthorizingObject.GROUP); @Id @Getter @@ -42,7 +42,7 @@ public Authority(String name) { this.name = name; } - public Authority(AuthorityEnum authority) { + public Authority(AuthorizingObject authority) { this(authority.name()); } @@ -86,7 +86,7 @@ public int hashCode() { return name.hashCode(); } - public boolean includes(AuthorityEnum authority) { - return authority.name().equals(this.name) || authority.name().startsWith(this.name) || this.name.equals(AuthorityEnum.ADMIN.name()); + public boolean includes(AuthorizingObject authority) { + return authority.name().equals(this.name) || authority.name().startsWith(this.name) || this.name.equals(AuthorizingObject.ADMIN.name()); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java index 47b6497b00..e53dc15757 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java @@ -4,14 +4,23 @@ import java.lang.annotation.*; +/** + * This annotation serves as marking for functions that requires additional authorization over the basic authentication. + * */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD, ElementType.TYPE }) @Inherited @Documented public @interface Authorize { - AuthorityEnum authority() default AuthorityEnum.ADMIN; + /** + * The authorizing object to be checked, whether the user has it assigned. + * */ + AuthorizingObject authority() default AuthorizingObject.ADMIN; + /** + * The Spring-EL expression to be evaluated before invoking the protected method. + * */ @Language("SpEL") String expression() default ""; } diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java similarity index 59% rename from src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java rename to src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java index d23bfeb5e3..d8f4702f76 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityEnum.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java @@ -1,6 +1,11 @@ package com.netgrif.application.engine.auth.domain; -public enum AuthorityEnum { +/** + * The enum of all possible authorizing objects, that are used for creating authority objects. Authorizing object is a + * term that defines the goal of the authority, e.g. what kind of system process is protected via an authority created + * using given authorizing object. + * */ +public enum AuthorizingObject { ADMIN, ANONYMOUS, PROCESS, diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java b/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java index b272a0ffef..7188eb5578 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java @@ -48,7 +48,7 @@ public void parseProcessRoles(Set processRoles) { } public boolean isAdmin() { - return getAuthorities().contains(new Authority(AuthorityEnum.ADMIN)); + return getAuthorities().contains(new Authority(AuthorizingObject.ADMIN)); } public String getEmail() { diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java index e4bfa6d059..3657899f5e 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.auth.service; -import com.netgrif.application.engine.auth.domain.AuthorityEnum; +import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.service.interfaces.IBaseAuthorizationService; import com.netgrif.application.engine.auth.service.interfaces.IUserService; @@ -13,7 +13,7 @@ public AbstractBaseAuthorizationService(IUserService userService) { } @Override - public final boolean hasAuthority(AuthorityEnum authority) { + public final boolean hasAuthority(AuthorizingObject authority) { return this.userService.getLoggedUser().getAuthorities().stream().anyMatch(a -> a.includes(authority)); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index 151eb3b67c..d89773fac3 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -1,7 +1,7 @@ package com.netgrif.application.engine.auth.service; import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.AuthorityEnum; +import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.domain.repositories.AuthorityRepository; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import org.springframework.beans.factory.annotation.Autowired; @@ -34,8 +34,8 @@ public Authority getOrCreate(String name) { } @Override - public Authority getOrCreate(AuthorityEnum authorityEnum) { - return getOrCreate(authorityEnum.name()); + public Authority getOrCreate(AuthorizingObject authorizingObject) { + return getOrCreate(authorizingObject.name()); } @Override @@ -44,7 +44,7 @@ public Authority save(Authority authority) { } @Override - public List getOrCreate(List authorities) { + public List getOrCreate(List authorities) { if (authorities == null) return Collections.emptyList(); return authorities.stream().map(this::getOrCreate).collect(Collectors.toList()); diff --git a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java index 035f6f8307..57611b8f35 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java @@ -21,6 +21,10 @@ import java.util.Arrays; import java.util.List; + +/** + * The aspect service for authorization system. + * */ @Slf4j @Aspect @Service @@ -30,11 +34,23 @@ public BaseAuthorizationService(@Autowired IUserService userService) { super(userService); } + /** + * Pointcut definition for {@link Authorize} annotation to connect authorization requests from join points to the + * {@link #authorize(ProceedingJoinPoint, Authorize)} advice. + * @param authorize the annotation with authorization requirements + * */ @Pointcut(value = "@annotation(authorize))") - private void authorizingMethod(Authorize authorize) {} + protected void authorizingMethod(Authorize authorize) {} + + /** + * The advice that handles incoming authorization requests from join points from + * {@link #authorizingMethod(Authorize)} pointcuts + * @param joinPoint the incoming method invocation join point + * @param authorize the incoming annotation with authorization parameters + * */ @Around(value = "authorizingMethod(authorize)", argNames = "joinPoint,authorize") - public Object authorize(ProceedingJoinPoint joinPoint, Authorize authorize) throws Throwable { + protected Object authorize(ProceedingJoinPoint joinPoint, Authorize authorize) throws Throwable { if (isAllowedByExpression(joinPoint, authorize.expression()) || hasAuthority(authorize.authority())) { return joinPoint.proceed(); } else { @@ -42,6 +58,15 @@ public Object authorize(ProceedingJoinPoint joinPoint, Authorize authorize) thro } } + /** + * Parser and evaluator function for Spring-EL expression. It creates parser for SpEL expression, context for it, + * and evaluates the authorization SpEL expression. It resolves the arguments of invoked method and sets as + * variables into the evaluation context, because in the SpEL expression there can be method arguments as variables + * alongside beans. + * @param joinPoint the incoming method invocation join point + * @param expression the SpEL expression + * @return the evaluated value, whether the SpEL expression returns true or not + * */ private boolean isAllowedByExpression(ProceedingJoinPoint joinPoint, String expression) { ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); diff --git a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java index 02c91b1f4e..a905684c43 100755 --- a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java @@ -138,7 +138,7 @@ public void addDefaultAuthorities(User user) { public void addAnonymousAuthorities(User user) { if (user.getAuthorities().isEmpty()) { HashSet authorities = new HashSet<>(); - authorities.add(authorityRepository.findByName(AuthorityEnum.ANONYMOUS.name())); + authorities.add(authorityRepository.findByName(AuthorizingObject.ANONYMOUS.name())); user.setAuthorities(authorities); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java index 9d95fdf80a..75166e6ae2 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java @@ -1,7 +1,7 @@ package com.netgrif.application.engine.auth.service.interfaces; import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.AuthorityEnum; +import com.netgrif.application.engine.auth.domain.AuthorizingObject; import java.util.List; @@ -11,11 +11,11 @@ public interface IAuthorityService { Authority getOrCreate(String name); - Authority getOrCreate(AuthorityEnum authorityEnum); + Authority getOrCreate(AuthorizingObject authorizingObject); Authority save(Authority authority); - List getOrCreate(List authorities); + List getOrCreate(List authorities); Authority delete(String name); diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java index 2a749f23eb..03c1162189 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java @@ -1,8 +1,8 @@ package com.netgrif.application.engine.auth.service.interfaces; -import com.netgrif.application.engine.auth.domain.AuthorityEnum; +import com.netgrif.application.engine.auth.domain.AuthorizingObject; public interface IBaseAuthorizationService { - boolean hasAuthority(AuthorityEnum authority); + boolean hasAuthority(AuthorizingObject authority); } diff --git a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java index e156a79a94..546a579964 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.auth.web; -import com.netgrif.application.engine.auth.domain.AuthorityEnum; +import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.auth.domain.LoggedUser; @@ -35,7 +35,6 @@ import org.springframework.hateoas.PagedModel; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; import org.springframework.http.MediaType; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.web.bind.annotation.*; @@ -176,7 +175,7 @@ public PagedModel getAllWithRole(@RequestBody Set roleIds, return resources; } - @Authorize(authority = AuthorityEnum.USER_EDIT) + @Authorize(authority = AuthorizingObject.USER_EDIT) @ApiOperation(value = "Assign role to the user", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) @@ -196,7 +195,7 @@ public MessageResource assignRolesToUser(@PathVariable("id") String userId, @Req } } - @Authorize(authority = AuthorityEnum.ADMIN) + @Authorize(authority = AuthorizingObject.ADMIN) @ApiOperation(value = "Get all authorities of the system", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) @@ -209,7 +208,7 @@ public AuthoritiesResources getAllAuthorities(Authentication auth) { return new AuthoritiesResources(authorityService.findAll()); } - @Authorize(authority = AuthorityEnum.USER_EDIT) + @Authorize(authority = AuthorizingObject.USER_EDIT) @ApiOperation(value = "Assign authority to the user", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/configuration/SecurityConfiguration.java b/src/main/java/com/netgrif/application/engine/configuration/SecurityConfiguration.java index 95288c1b6a..eb6574de8d 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/SecurityConfiguration.java +++ b/src/main/java/com/netgrif/application/engine/configuration/SecurityConfiguration.java @@ -1,7 +1,7 @@ package com.netgrif.application.engine.configuration; import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.AuthorityEnum; +import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.domain.UserProperties; import com.netgrif.application.engine.auth.service.AfterRegistrationAuthService; import com.netgrif.application.engine.auth.service.interfaces.IAfterRegistrationAuthService; @@ -176,7 +176,7 @@ protected Environment getEnvironment() { } private PublicAuthenticationFilter createPublicAuthenticationFilter() throws Exception { - Authority authority = authorityService.getOrCreate(AuthorityEnum.ANONYMOUS); + Authority authority = authorityService.getOrCreate(AuthorizingObject.ANONYMOUS); authority.setUsers(new HashSet<>()); return new PublicAuthenticationFilter( authenticationManager(), diff --git a/src/main/java/com/netgrif/application/engine/configuration/SecurityConfigurationLdap.java b/src/main/java/com/netgrif/application/engine/configuration/SecurityConfigurationLdap.java index 3019dc7985..57fe084786 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/SecurityConfigurationLdap.java +++ b/src/main/java/com/netgrif/application/engine/configuration/SecurityConfigurationLdap.java @@ -2,7 +2,7 @@ import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.AuthorityEnum; +import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.domain.IUser; import com.netgrif.application.engine.ldap.domain.LdapUser; import com.netgrif.application.engine.auth.service.AfterRegistrationAuthService; @@ -228,7 +228,7 @@ protected Environment getEnvironment() { } private PublicAuthenticationFilter createPublicAuthenticationFilter() throws Exception { - Authority authority = authorityService.getOrCreate(AuthorityEnum.ANONYMOUS); + Authority authority = authorityService.getOrCreate(AuthorizingObject.ANONYMOUS); authority.setUsers(new HashSet<>()); return new PublicAuthenticationFilter( authenticationManager(), diff --git a/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java b/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java index 023293d96f..0e9901d032 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java +++ b/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.elastic.web; -import com.netgrif.application.engine.auth.domain.AuthorityEnum; +import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.elastic.service.ReindexingTask; @@ -16,7 +16,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; @@ -50,7 +49,7 @@ public class ElasticController { @Value("${spring.data.elasticsearch.reindex-size}") private int pageSize; - @Authorize(authority = AuthorityEnum.ADMIN) + @Authorize(authority = AuthorizingObject.ADMIN) @ApiOperation(value = "Reindex specified cases", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java index c34bbb5b3b..a39d749d08 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.orgstructure.web; -import com.netgrif.application.engine.auth.domain.AuthorityEnum; +import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService; import com.netgrif.application.engine.orgstructure.web.responsebodies.Group; @@ -10,7 +10,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.hateoas.MediaTypes; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @@ -33,7 +32,7 @@ public class GroupController { @Autowired private INextGroupService service; - @Authorize(authority = AuthorityEnum.GROUP_VIEW_ALL) + @Authorize(authority = AuthorizingObject.GROUP_VIEW_ALL) @ApiOperation(value = "Get all groups in the system", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java index 258ca4307e..cb1c9558ee 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.workflow.web; -import com.netgrif.application.engine.auth.domain.AuthorityEnum; +import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.elastic.domain.ElasticCase; @@ -166,7 +166,7 @@ public PagedModel findAllByAuthor(@PathVariable("id") String autho return resources; } - @Authorize(authority = AuthorityEnum.ADMIN) + @Authorize(authority = AuthorizingObject.ADMIN) @ApiOperation(value = "Reload tasks of case", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) @@ -189,7 +189,7 @@ public MessageResource reloadTasks(@PathVariable("id") String caseId) { } @Deprecated - @Authorize(authority = AuthorityEnum.ADMIN) + @Authorize(authority = AuthorizingObject.ADMIN) @ApiOperation(value = "Get all case data", authorizations = @Authorization("BasicAuth")) @GetMapping(value = "/case/{id}/data", produces = MediaTypes.HAL_JSON_VALUE) public DataFieldsResource getAllCaseData(@PathVariable("id") String caseId, Locale locale) { diff --git a/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy index ee95156de6..a92b13b09a 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy @@ -2,7 +2,7 @@ package com.netgrif.application.engine.action import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.AuthorityEnum +import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.auth.domain.repositories.UserRepository @@ -91,7 +91,7 @@ class AssignActionTest { createMainAndSecondaryNet() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), [auths.get("user"), auths.get("admin")] as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy index f09f26d349..7178b7169c 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy @@ -2,7 +2,7 @@ package com.netgrif.application.engine.action import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.AuthorityEnum +import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.auth.domain.repositories.UserRepository @@ -97,7 +97,7 @@ class RemoveActionTest { this.petriNet = net.getNet() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), [auths.get("user")] as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy index de8ef33e64..1372642654 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy @@ -1,7 +1,7 @@ package com.netgrif.application.engine.auth import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.AuthorityEnum +import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.IUser import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState @@ -120,7 +120,7 @@ class TaskAuthorizationServiceTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) def processRoles = userProcessRoleRepository.findAllByNetId(this.net.getStringId()) def user = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_WITH_ROLE_EMAIL, password: "password", state: UserState.ACTIVE), diff --git a/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy b/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy index bb0a65ba94..2fd4efa420 100644 --- a/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy @@ -2,7 +2,7 @@ package com.netgrif.application.engine.event import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.AuthorityEnum +import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.LoggedUser import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState @@ -81,7 +81,7 @@ class GroovyShellFactoryTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["systemAdmin": [AuthorityEnum.ADMIN]]) + def auths = importHelper.createAuthorities(["systemAdmin": [AuthorizingObject.ADMIN]]) importHelper.createUser(new User(name: "Admin", surname: "User", email: USER_EMAIL, password: USER_PASSW, state: UserState.ACTIVE), [auths.get("systemAdmin")] as Authority[], [] as ProcessRole[]) From 81185d352a8c1ef8552b2590d785d35db21ae68b Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Fri, 6 May 2022 15:06:15 +0200 Subject: [PATCH 23/68] [NAE-1617] Refactor Authority - corrected tests - corrected authorizationservice according to tests --- .../auth/service/BaseAuthorizationService.java | 10 +++++++++- .../services/GroupAuthorizationService.java | 15 --------------- .../interfaces/IGroupAuthorizationService.java | 7 ------- .../engine/action/AssignActionTest.groovy | 6 +++++- .../auth/FilterAuthorizationServiceTest.groovy | 7 ++++--- .../auth/TaskAuthorizationServiceTest.groovy | 8 ++++---- .../auth/WorkflowAuthorizationServiceTest.groovy | 9 +++++---- .../engine/elastic/ElasticSearchTest.groovy | 4 ++-- .../engine/event/GroovyShellFactoryTest.groovy | 2 +- .../engine/filters/FilterImportExportTest.groovy | 5 +++-- .../engine/insurance/EncryptionTest.groovy | 4 ++-- .../engine/insurance/mvc/InsuranceTest.groovy | 8 ++++++-- .../engine/menu/MenuImportExportTest.groovy | 2 +- .../groups/NextGroupServiceTest.groovy | 7 ++++--- .../ElasticSearchViewPermissionTest.groovy | 8 +++++--- .../QueryDSLViewPermissionTest.groovy | 6 +++--- .../petrinet/domain/roles/ProcessRoleTest.groovy | 2 +- .../petrinet/service/PetriNetServiceTest.groovy | 5 +++-- .../petrinet/web/PetriNetControllerTest.groovy | 16 +++++++++++----- .../engine/workflow/TaskControllerTest.groovy | 3 ++- 20 files changed, 71 insertions(+), 63 deletions(-) delete mode 100644 src/main/java/com/netgrif/application/engine/orgstructure/services/GroupAuthorizationService.java delete mode 100644 src/main/java/com/netgrif/application/engine/orgstructure/services/interfaces/IGroupAuthorizationService.java diff --git a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java index 57611b8f35..b091261ba7 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java @@ -1,6 +1,9 @@ package com.netgrif.application.engine.auth.service; +import com.netgrif.application.engine.auth.domain.Author; import com.netgrif.application.engine.auth.domain.Authorize; +import com.netgrif.application.engine.auth.domain.AuthorizingObject; +import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.configuration.ApplicationContextProvider; import lombok.extern.slf4j.Slf4j; @@ -15,6 +18,7 @@ import org.springframework.expression.ExpressionParser; import org.springframework.expression.spel.standard.SpelExpressionParser; import org.springframework.expression.spel.support.StandardEvaluationContext; +import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.expression.ExpressionUtils; import org.springframework.stereotype.Service; @@ -54,7 +58,7 @@ protected Object authorize(ProceedingJoinPoint joinPoint, Authorize authorize) t if (isAllowedByExpression(joinPoint, authorize.expression()) || hasAuthority(authorize.authority())) { return joinPoint.proceed(); } else { - return null; + throw new AccessDeniedException("Access Denied"); } } @@ -68,6 +72,10 @@ protected Object authorize(ProceedingJoinPoint joinPoint, Authorize authorize) t * @return the evaluated value, whether the SpEL expression returns true or not * */ private boolean isAllowedByExpression(ProceedingJoinPoint joinPoint, String expression) { + if (expression == null || expression.equals("")) { + return true; + } + ExpressionParser parser = new SpelExpressionParser(); StandardEvaluationContext context = new StandardEvaluationContext(); context.setBeanResolver(new BeanFactoryResolver(ApplicationContextProvider.getAppContext())); diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/services/GroupAuthorizationService.java b/src/main/java/com/netgrif/application/engine/orgstructure/services/GroupAuthorizationService.java deleted file mode 100644 index ee38c399b2..0000000000 --- a/src/main/java/com/netgrif/application/engine/orgstructure/services/GroupAuthorizationService.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.netgrif.application.engine.orgstructure.services; - -import com.netgrif.application.engine.auth.service.AbstractBaseAuthorizationService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import com.netgrif.application.engine.orgstructure.services.interfaces.IGroupAuthorizationService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -@Service -public class GroupAuthorizationService extends AbstractBaseAuthorizationService implements IGroupAuthorizationService { - - public GroupAuthorizationService(@Autowired IUserService userService) { - super(userService); - } -} diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/services/interfaces/IGroupAuthorizationService.java b/src/main/java/com/netgrif/application/engine/orgstructure/services/interfaces/IGroupAuthorizationService.java deleted file mode 100644 index 100dfafa25..0000000000 --- a/src/main/java/com/netgrif/application/engine/orgstructure/services/interfaces/IGroupAuthorizationService.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.netgrif.application.engine.orgstructure.services.interfaces; - -import com.netgrif.application.engine.auth.service.interfaces.IBaseAuthorizationService; - -public interface IGroupAuthorizationService extends IBaseAuthorizationService { - -} diff --git a/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy index a92b13b09a..7f7aa864fd 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy @@ -34,6 +34,9 @@ import org.springframework.test.web.servlet.result.MockMvcResultMatchers import org.springframework.test.web.servlet.setup.MockMvcBuilders import org.springframework.web.context.WebApplicationContext +import java.util.stream.Collectors +import java.util.stream.Stream + import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity @ExtendWith(SpringExtension.class) @@ -92,9 +95,10 @@ class AssignActionTest { createMainAndSecondaryNet() def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) + def authorityList = Stream.concat(auths.get("user").stream(), auths.get("admin").stream()).collect(Collectors.toList()).toArray() importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), - [auths.get("user"), auths.get("admin")] as Authority[], + authorityList as Authority[], // [org] as Group[], [] as ProcessRole[]) } diff --git a/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy index c69abd7ecc..5f52bb5b47 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.auth import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole @@ -67,16 +68,16 @@ class FilterAuthorizationServiceTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], + auths.get("user").toArray() as Authority[], [] as ProcessRole[]) userAuth = new UsernamePasswordAuthenticationToken(USER_EMAIL, "password") importHelper.createUser(new User(name: "Admin", surname: "User", email: ADMIN_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("admin")] as Authority[], + auths.get("admin").toArray() as Authority[], [] as ProcessRole[]) adminAuth = new UsernamePasswordAuthenticationToken(ADMIN_EMAIL, "password") diff --git a/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy index 1372642654..4515434b4c 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy @@ -124,20 +124,20 @@ class TaskAuthorizationServiceTest { def processRoles = userProcessRoleRepository.findAllByNetId(this.net.getStringId()) def user = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_WITH_ROLE_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], + auths.get("user").toArray() as Authority[], [processRoles.find({ it.name.equals("role") })] as ProcessRole[]) userId = user.getStringId() this.userWithRoleAuth = new UsernamePasswordAuthenticationToken(USER_WITH_ROLE_EMAIL, "password") importHelper.createUser(new User(name: "NoRole", surname: "User", email: USER_WITHOUT_ROLE_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], + auths.get("user").toArray() as Authority[], [] as ProcessRole[]) this.userWithoutRoleAuth = new UsernamePasswordAuthenticationToken(USER_WITHOUT_ROLE_EMAIL, "password") importHelper.createUser(new User(name: "Admin", surname: "User", email: ADMIN_USER_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("admin")] as Authority[], + auths.get("admin").toArray() as Authority[], [] as ProcessRole[]) this.adminAuth = new UsernamePasswordAuthenticationToken(ADMIN_USER_EMAIL, "password") @@ -169,7 +169,7 @@ class TaskAuthorizationServiceTest { auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities]) testUser = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], [] as ProcessRole[]) + auths.get("user").toArray() as Authority[], [] as ProcessRole[]) } diff --git a/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy index 3fe3eeb725..7b415b4221 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.auth import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.IUser import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState @@ -96,17 +97,17 @@ class WorkflowAuthorizationServiceTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], + auths.get("user").toArray() as Authority[], // [] as Group[], [] as ProcessRole[]) userAuth = new UsernamePasswordAuthenticationToken(USER_EMAIL, "password") importHelper.createUser(new User(name: "Admin", surname: "User", email: ADMIN_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("admin")] as Authority[], + auths.get("admin").toArray() as Authority[], // [] as Group[], [] as ProcessRole[]) @@ -125,7 +126,7 @@ class WorkflowAuthorizationServiceTest { auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities]) testUser = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], [] as ProcessRole[]) + auths.get("user").toArray() as Authority[], [] as ProcessRole[]) } // @Test diff --git a/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy b/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy index 4baa823621..f9c0513b59 100644 --- a/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy @@ -109,10 +109,10 @@ class ElasticSearchTest { netId2 = net2.getStringId() // def org = importHelper.createGroup("Test") - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) // def processRoles = importHelper.getProcessRoles(net.get()) def testUser = importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSW, state: UserState.ACTIVE), - [auths.get("user")] as Authority[], + auths.get("user").toArray() as Authority[], [net.roles.values().find { it.importId == "process_role" }] as ProcessRole[]) 10.times { diff --git a/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy b/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy index 2fd4efa420..beb8e3be28 100644 --- a/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy @@ -83,7 +83,7 @@ class GroovyShellFactoryTest { def auths = importHelper.createAuthorities(["systemAdmin": [AuthorizingObject.ADMIN]]) importHelper.createUser(new User(name: "Admin", surname: "User", email: USER_EMAIL, password: USER_PASSW, state: UserState.ACTIVE), - [auths.get("systemAdmin")] as Authority[], + auths.get("systemAdmin").toArray() as Authority[], [] as ProcessRole[]) def adminAuth = new UsernamePasswordAuthenticationToken(USER_EMAIL, USER_PASSW) diff --git a/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy b/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy index 25ade537ef..05b711a046 100644 --- a/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.filters import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.petrinet.domain.PetriNet @@ -299,9 +300,9 @@ class FilterImportExportTest { } private User createDummyUser() { - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) return importHelper.createUser(new User(name: "Dummy", surname: "User", email: DUMMY_USER_MAIL, password: DUMMY_USER_PASSWORD, state: UserState.ACTIVE), - [auths.get("user")] as Authority[], + auths.get("user").toArray() as Authority[], [] as ProcessRole[]) } diff --git a/src/test/groovy/com/netgrif/application/engine/insurance/EncryptionTest.groovy b/src/test/groovy/com/netgrif/application/engine/insurance/EncryptionTest.groovy index 45bdfdda82..1cec68988e 100644 --- a/src/test/groovy/com/netgrif/application/engine/insurance/EncryptionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/insurance/EncryptionTest.groovy @@ -87,7 +87,7 @@ class EncryptionTest { } LoggedUser mockLoggedUser() { - def authorityUser = authorityService.getOrCreate(Authority.user) - return new LoggedUser(superCreator.getSuperUser().getStringId(), "super@netgrif.com", "password", [authorityUser]) + def authorityUser = authorityService.getOrCreate(Authority.defaultUserAuthorities) + return new LoggedUser(superCreator.getSuperUser().getStringId(), "super@netgrif.com", "password", authorityUser) } } \ No newline at end of file diff --git a/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy b/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy index 36d8e8e229..d074561723 100644 --- a/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy @@ -3,6 +3,7 @@ package com.netgrif.application.engine.insurance.mvc import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.ApplicationEngine import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.auth.service.interfaces.IUserService @@ -15,6 +16,7 @@ import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import groovy.json.JsonOutput import groovy.json.JsonSlurper +import org.assertj.core.util.Streams import org.hamcrest.CoreMatchers import org.junit.jupiter.api.BeforeEach @@ -39,6 +41,7 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders import org.springframework.web.context.WebApplicationContext import java.nio.charset.StandardCharsets +import java.util.stream.Stream import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf @@ -133,10 +136,11 @@ class InsuranceTest { netId = net.getNet().getStringId() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) + def authorityArray = Stream.concat(auths.get("user").stream(), auths.get("admin").stream()).toArray() def processRoles = importHelper.getProcessRolesByImportId(net.getNet(), ["agent": "1", "company": "2"]) importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user"), auths.get("admin")] as Authority[], + authorityArray as Authority[], [processRoles.get("agent"), processRoles.get("company")] as ProcessRole[]) List roles = processRoleService.findAll(netId) processRoleService.assignRolesToUser(userService.findByEmail(USER_EMAIL, false).getId(), roles.findAll { it.importId in ["1", "2"] }.collect { it.stringId } as Set, userService.getLoggedOrSystem().transformToLoggedUser()) diff --git a/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy b/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy index 5773b3c9df..21116126fb 100644 --- a/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy @@ -199,7 +199,7 @@ class MenuImportExportTest { } private User createDummyUser() { - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) return importHelper.createUser(new User(name: "Dummy", surname: "User", email: DUMMY_USER_MAIL, password: DUMMY_USER_PASSWORD, state: UserState.ACTIVE), [auths.get("user")] as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy index ba909b539e..9353763ea6 100644 --- a/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.orgstructure.groups import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.auth.service.UserService @@ -45,12 +46,12 @@ class NextGroupServiceTest { @Test void groupTest() { testHelper.truncateDbs() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) importHelper.createUser(new User(name: "Dummy", surname: "User", email: DUMMY_USER_MAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], + auths.get("user").toArray() as Authority[], [] as ProcessRole[]) importHelper.createUser(new User(name: "Customer", surname: "User", email: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], + auths.get("user").toArray() as Authority[], [] as ProcessRole[]) Optional groupNet = importGroup() diff --git a/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy b/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy index 80d9a97d95..9f32992026 100644 --- a/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy @@ -31,6 +31,8 @@ import org.springframework.data.domain.PageRequest import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension +import java.lang.reflect.Array + @ExtendWith(SpringExtension.class) @ActiveProfiles(["test"]) @SpringBootTest @@ -71,7 +73,7 @@ class ElasticSearchViewPermissionTest { private PetriNet net private PetriNet netWithUserRefs private IUser testUser - private Authority userAuthority + private List userAuthority @BeforeEach void inti() { @@ -83,10 +85,10 @@ class ElasticSearchViewPermissionTest { assert netWithUserRefs.getNet() != null this.netWithUserRefs = netWithUserRefs.getNet() - userAuthority = authorityService.getOrCreate(Authority.user) + userAuthority = authorityService.getOrCreate(Authority.defaultUserAuthorities) testUser = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), - [userAuthority] as Authority[], [] as ProcessRole[]) + userAuthority.toArray() as Authority[], [] as ProcessRole[]) } @Test diff --git a/src/test/groovy/com/netgrif/application/engine/permissions/QueryDSLViewPermissionTest.groovy b/src/test/groovy/com/netgrif/application/engine/permissions/QueryDSLViewPermissionTest.groovy index ffc493130a..ec39ad63ee 100644 --- a/src/test/groovy/com/netgrif/application/engine/permissions/QueryDSLViewPermissionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/permissions/QueryDSLViewPermissionTest.groovy @@ -64,7 +64,7 @@ class QueryDSLViewPermissionTest { private PetriNet net private PetriNet netWithUserRefs private IUser testUser - private Authority userAuthority + private List userAuthority @BeforeEach void inti() { @@ -77,10 +77,10 @@ class QueryDSLViewPermissionTest { assert netWithUserRefs.getNet() != null this.netWithUserRefs = netWithUserRefs.getNet() - userAuthority = authorityService.getOrCreate(Authority.user) + userAuthority = authorityService.getOrCreate(Authority.defaultUserAuthorities) testUser = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), - [userAuthority] as Authority[], [] as ProcessRole[]) + userAuthority.toArray() as Authority[], [] as ProcessRole[]) } @Test diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy index 5fd11958ca..04084cb2f5 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy @@ -85,7 +85,7 @@ class ProcessRoleTest { String netId = net.getNet().getStringId() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) def processRoles = userProcessRoleRepository.findAllByNetId(netId) importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL_VIEW, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy index 29de899123..2fd108c173 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.petrinet.service import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.auth.service.interfaces.IUserService @@ -73,9 +74,9 @@ class PetriNetServiceTest { @BeforeEach void setup() { testHelper.truncateDbs() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) importHelper.createUser(new User(name: "Customer", surname: "User", email: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], + auths.get("user").toArray() as Authority[], [] as ProcessRole[]) } diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy index f421e77b3b..cbc82684a1 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy @@ -2,8 +2,10 @@ package com.netgrif.application.engine.petrinet.webprocessRolesAndPermissionses import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState +import com.netgrif.application.engine.auth.service.interfaces.IUserService import com.netgrif.application.engine.ipc.TaskApiTest import com.netgrif.application.engine.petrinet.domain.PetriNet import com.netgrif.application.engine.petrinet.domain.VersionType @@ -11,6 +13,7 @@ import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator +import org.junit.Before import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test @@ -61,6 +64,9 @@ class PetriNetControllerTest { @Autowired private TestHelper testHelper + @Autowired + private IUserService userService + private def stream = { String name -> return TaskApiTest.getClassLoader().getResourceAsStream(name) } @@ -79,21 +85,21 @@ class PetriNetControllerTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorityEnum.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], + auths.get("user").toArray() as Authority[], // [] as Group[], [] as ProcessRole[]) - userAuth = new UsernamePasswordAuthenticationToken(USER_EMAIL, "password") + userAuth = new UsernamePasswordAuthenticationToken(userService.findByEmail(USER_EMAIL, false).transformToLoggedUser(), "password", auths.get("user")) importHelper.createUser(new User(name: "Admin", surname: "User", email: ADMIN_EMAIL, password: "password", state: UserState.ACTIVE), - [auths.get("admin")] as Authority[], + auths.get("admin").toArray() as Authority[], // [] as Group[], [] as ProcessRole[]) - adminAuth = new UsernamePasswordAuthenticationToken(ADMIN_EMAIL, "password") + adminAuth = new UsernamePasswordAuthenticationToken(userService.findByEmail(ADMIN_EMAIL, false).transformToLoggedUser(), "password", auths.get("admin")) } private PetriNet net diff --git a/src/test/groovy/com/netgrif/application/engine/workflow/TaskControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/workflow/TaskControllerTest.groovy index 83a50110a8..578657b395 100644 --- a/src/test/groovy/com/netgrif/application/engine/workflow/TaskControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/workflow/TaskControllerTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.workflow import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService @@ -92,7 +93,7 @@ class TaskControllerTest { email: DUMMY_USER_MAIL, password: "superAdminPassword", state: UserState.ACTIVE, - authorities: [authorityService.getOrCreate(Authority.user)] as Set, + authorities: authorityService.getOrCreate(Authority.defaultUserAuthorities).toSet() as Set, processRoles: [] as Set)) importNet() } From 3e20ed29ed868b26d567c259719150c3a609f605 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 9 May 2022 11:59:31 +0200 Subject: [PATCH 24/68] [NAE-1617] Refactor Authority - added transactional annotation into AuthorityService - added authorization into some ActionDelegate methods --- .../dataset/logic/action/ActionDelegate.groovy | 16 ++++++++++------ .../engine/auth/service/AuthorityService.java | 1 + 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy index 2f7b060e62..c67369ac74 100644 --- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy @@ -847,7 +847,7 @@ class ActionDelegate { mailService.sendMail(mailDraft) } - @Authorize(authority = AuthorizingObject.ADMIN, expression = "@userService.isLoggedByEmail(email)") + @Authorize(authority = AuthorizingObject.USER_EDIT, expression = "@userService.isLoggedByEmail(email)") def changeUserByEmail(String email) { [email : { cl -> changeUserByEmail(email, "email", cl) @@ -864,7 +864,7 @@ class ActionDelegate { ] } - @Authorize(authority = AuthorizingObject.ADMIN, expression = "@userService.isLogged(#id)") + @Authorize(authority = AuthorizingObject.USER_EDIT, expression = "@userService.isLogged(#id)") def changeUser(String id) { [email : { cl -> changeUser(id, "email", cl) @@ -881,7 +881,7 @@ class ActionDelegate { ] } - @Authorize(authority = AuthorizingObject.ADMIN, expression = "@userService.isLogged(#user)") + @Authorize(authority = AuthorizingObject.USER_EDIT, expression = "@userService.isLogged(#user)") def changeUser(IUser user) { [email : { cl -> changeUser(user, "email", cl) @@ -898,19 +898,19 @@ class ActionDelegate { ] } - @Authorize(authority = AuthorizingObject.ADMIN, expression = "@userService.isLoggedByEmail(#email)") + @Authorize(authority = AuthorizingObject.USER_EDIT, expression = "@userService.isLoggedByEmail(#email)") def changeUserByEmail(String email, String attribute, def cl) { IUser user = userService.findByEmail(email, false) changeUser(user, attribute, cl) } - @Authorize(authority = AuthorizingObject.ADMIN, expression = "@userService.isLogged(#id)") + @Authorize(authority = AuthorizingObject.USER_EDIT, expression = "@userService.isLogged(#id)") def changeUser(String id, String attribute, def cl) { IUser user = userService.findById(id, false) changeUser(user, attribute, cl) } - @Authorize(authority = AuthorizingObject.ADMIN, expression = "@userService.isLogged(#user)") + @Authorize(authority = AuthorizingObject.USER_EDIT, expression = "@userService.isLogged(#user)") def changeUser(IUser user, String attribute, def cl) { if (user == null) { log.error("Cannot find user.") @@ -926,6 +926,7 @@ class ActionDelegate { userService.save(user) } + @Authorize(authority = AuthorizingObject.USER_CREATE) MessageResource inviteUser(String email) { NewUserRequest newUserRequest = new NewUserRequest() newUserRequest.email = email @@ -934,6 +935,7 @@ class ActionDelegate { return inviteUser(newUserRequest) } + @Authorize(authority = AuthorizingObject.USER_CREATE) MessageResource inviteUser(NewUserRequest newUserRequest) { IUser user = registrationService.createNewUser(newUserRequest); if (user == null) @@ -944,6 +946,7 @@ class ActionDelegate { return MessageResource.successMessage("Done"); } + @Authorize(authority = AuthorizingObject.USER_DELETE) void deleteUser(String email) { IUser user = userService.findByEmail(email, false) if (user == null) @@ -951,6 +954,7 @@ class ActionDelegate { deleteUser(user) } + @Authorize(authority = AuthorizingObject.USER_DELETE) void deleteUser(IUser user) { List tasks = taskService.findByUser(new FullPageRequest(), user).toList() if (tasks != null && tasks.size() > 0) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index d89773fac3..1da7a2f8e8 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -34,6 +34,7 @@ public Authority getOrCreate(String name) { } @Override + @Transactional public Authority getOrCreate(AuthorizingObject authorizingObject) { return getOrCreate(authorizingObject.name()); } From f45da116b1e007954618e869931cd0f457c4a1cb Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 16 May 2022 08:03:07 +0200 Subject: [PATCH 25/68] [NAE-1617] Refactor Authority - refactored Authorize - implemented Authorizations --- .../engine/auth/domain/Authorizations.java | 12 ++++++++++++ .../application/engine/auth/domain/Authorize.java | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/netgrif/application/engine/auth/domain/Authorizations.java diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authorizations.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authorizations.java new file mode 100644 index 0000000000..b446d3ffcc --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authorizations.java @@ -0,0 +1,12 @@ +package com.netgrif.application.engine.auth.domain; + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.METHOD, ElementType.TYPE }) +@Inherited +@Documented +public @interface Authorizations { + + Authorize[] value(); +} diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java index e53dc15757..8098e78e11 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java @@ -16,7 +16,7 @@ /** * The authorizing object to be checked, whether the user has it assigned. * */ - AuthorizingObject authority() default AuthorizingObject.ADMIN; + String authority() default ""; /** * The Spring-EL expression to be evaluated before invoking the protected method. From af0da4c8aca2fbc3b682d1e655cc5bf3420804e5 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 16 May 2022 08:04:01 +0200 Subject: [PATCH 26/68] [NAE-1617] Refactor Authority - removed unnecessary scope objects from AuthorizingObject - renamed BaseAuthorizationServiceAspect --- .../engine/auth/domain/AuthorizingObject.java | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java index d8f4702f76..70fc808440 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java @@ -6,14 +6,6 @@ * using given authorizing object. * */ public enum AuthorizingObject { - ADMIN, - ANONYMOUS, - PROCESS, - FILTER, - USER, - GROUP, - ROLE, - AUTHORITY, PROCESS_UPLOAD, PROCESS_DELETE, FILTER_UPLOAD, @@ -26,8 +18,8 @@ public enum AuthorizingObject { GROUP_ADD_USER, GROUP_REMOVE_USER, GROUP_VIEW_ALL, - ROLE_CREATE, - ROLE_DELETE, + ROLE_CREATE, // refactor for user "assign" + ROLE_DELETE, // refactor for user "deassign" AUTHORITY_CREATE, AUTHORITY_DELETE } From 8e34591475eb7cd1b2cf28308959b28a430a323b Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 16 May 2022 09:50:44 +0200 Subject: [PATCH 27/68] [NAE-1617] Refactor Authority - refactored AuthorizationObject values to string - refactored tests --- docs/authorization/authority.md | 14 ++++++++ pom.xml | 15 -------- .../logic/action/ActionDelegate.groovy | 20 +++++------ .../engine/startup/SuperCreator.groovy | 2 +- .../engine/auth/domain/Authority.java | 8 ++--- .../engine/auth/domain/LoggedUser.java | 2 +- .../AbstractBaseAuthorizationService.java | 12 ++++--- .../engine/auth/service/AuthorityService.java | 34 ++++++++++++++----- ...va => BaseAuthorizationServiceAspect.java} | 8 ++--- .../engine/auth/service/UserService.java | 10 +++--- .../service/interfaces/IAuthorityService.java | 12 +++++-- .../interfaces/IBaseAuthorizationService.java | 2 +- .../engine/auth/web/UserController.java | 11 +++--- .../configuration/SecurityConfiguration.java | 7 ++-- .../SecurityConfigurationLdap.java | 10 +++--- .../security/PublicAuthenticationFilter.java | 10 +++--- .../security/jwt/IJwtService.java | 3 +- .../security/jwt/JwtService.java | 4 +-- .../engine/elastic/web/ElasticController.java | 3 +- .../orgstructure/web/GroupController.java | 2 +- .../workflow/web/WorkflowController.java | 5 +-- .../engine/action/AssignActionTest.groovy | 2 +- .../engine/action/RemoveActionTest.groovy | 2 +- .../FilterAuthorizationServiceTest.groovy | 2 +- .../engine/elastic/ElasticSearchTest.groovy | 2 +- .../event/GroovyShellFactoryTest.groovy | 2 +- .../filters/FilterImportExportTest.groovy | 2 +- .../engine/insurance/mvc/InsuranceTest.groovy | 2 +- .../engine/menu/MenuImportExportTest.groovy | 2 +- .../groups/NextGroupServiceTest.groovy | 2 +- .../domain/roles/ProcessRoleTest.groovy | 2 +- .../service/PetriNetServiceTest.groovy | 2 +- .../web/PetriNetControllerTest.groovy | 2 +- 33 files changed, 122 insertions(+), 96 deletions(-) create mode 100644 docs/authorization/authority.md rename src/main/java/com/netgrif/application/engine/auth/service/{BaseAuthorizationService.java => BaseAuthorizationServiceAspect.java} (92%) diff --git a/docs/authorization/authority.md b/docs/authorization/authority.md new file mode 100644 index 0000000000..fb47c9f9dd --- /dev/null +++ b/docs/authorization/authority.md @@ -0,0 +1,14 @@ +# Authority management +Netgrif Application Engine implements authority objects to manage access +to resources, to protect resources from unauthorized access. Then these +authorities can be assigned to users to provide access to those secured +resources. + +## Authorizing objects +Authorizing objects are Java enum values, that represent authorities, +that are needed to access a resource or use an action. E.g. to be able to import new +process (Petri Net) into the application, the user must have authority +created from ``AuthorizingObject.PROCESS_UPLOAD`` authorizing object. + +These authorizing objects are predefined, and they are used to create the +``Authority`` objects/entities at application startup. \ No newline at end of file diff --git a/pom.xml b/pom.xml index 5e4ef7f8ef..11ed1326dc 100644 --- a/pom.xml +++ b/pom.xml @@ -98,21 +98,6 @@ jcommander 1.75 - - org.apache.commons - commons-compress - 1.21 - - - commons-beanutils - commons-beanutils - 1.9.4 - - - com.beust - jcommander - 1.75 - diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy index c67369ac74..e02688c6d3 100644 --- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy @@ -847,7 +847,7 @@ class ActionDelegate { mailService.sendMail(mailDraft) } - @Authorize(authority = AuthorizingObject.USER_EDIT, expression = "@userService.isLoggedByEmail(email)") + @Authorize(authority = "USER_EDIT", expression = "@userService.isLoggedByEmail(email)") def changeUserByEmail(String email) { [email : { cl -> changeUserByEmail(email, "email", cl) @@ -864,7 +864,7 @@ class ActionDelegate { ] } - @Authorize(authority = AuthorizingObject.USER_EDIT, expression = "@userService.isLogged(#id)") + @Authorize(authority = "USER_EDIT", expression = "@userService.isLogged(#id)") def changeUser(String id) { [email : { cl -> changeUser(id, "email", cl) @@ -881,7 +881,7 @@ class ActionDelegate { ] } - @Authorize(authority = AuthorizingObject.USER_EDIT, expression = "@userService.isLogged(#user)") + @Authorize(authority = "USER_EDIT", expression = "@userService.isLogged(#user)") def changeUser(IUser user) { [email : { cl -> changeUser(user, "email", cl) @@ -898,19 +898,19 @@ class ActionDelegate { ] } - @Authorize(authority = AuthorizingObject.USER_EDIT, expression = "@userService.isLoggedByEmail(#email)") + @Authorize(authority = "USER_EDIT", expression = "@userService.isLoggedByEmail(#email)") def changeUserByEmail(String email, String attribute, def cl) { IUser user = userService.findByEmail(email, false) changeUser(user, attribute, cl) } - @Authorize(authority = AuthorizingObject.USER_EDIT, expression = "@userService.isLogged(#id)") + @Authorize(authority = "USER_EDIT", expression = "@userService.isLogged(#id)") def changeUser(String id, String attribute, def cl) { IUser user = userService.findById(id, false) changeUser(user, attribute, cl) } - @Authorize(authority = AuthorizingObject.USER_EDIT, expression = "@userService.isLogged(#user)") + @Authorize(authority = "USER_EDIT", expression = "@userService.isLogged(#user)") def changeUser(IUser user, String attribute, def cl) { if (user == null) { log.error("Cannot find user.") @@ -926,7 +926,7 @@ class ActionDelegate { userService.save(user) } - @Authorize(authority = AuthorizingObject.USER_CREATE) + @Authorize(authority = "USER_CREATE") MessageResource inviteUser(String email) { NewUserRequest newUserRequest = new NewUserRequest() newUserRequest.email = email @@ -935,7 +935,7 @@ class ActionDelegate { return inviteUser(newUserRequest) } - @Authorize(authority = AuthorizingObject.USER_CREATE) + @Authorize(authority = "USER_CREATE") MessageResource inviteUser(NewUserRequest newUserRequest) { IUser user = registrationService.createNewUser(newUserRequest); if (user == null) @@ -946,7 +946,7 @@ class ActionDelegate { return MessageResource.successMessage("Done"); } - @Authorize(authority = AuthorizingObject.USER_DELETE) + @Authorize(authority = "USER_DELETE") void deleteUser(String email) { IUser user = userService.findByEmail(email, false) if (user == null) @@ -954,7 +954,7 @@ class ActionDelegate { deleteUser(user) } - @Authorize(authority = AuthorizingObject.USER_DELETE) + @Authorize(authority = "USER_DELETE") void deleteUser(IUser user) { List tasks = taskService.findByUser(new FullPageRequest(), user).toList() if (tasks != null && tasks.size() > 0) diff --git a/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy b/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy index 0bf6ec7a2e..b2476432e1 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy @@ -43,7 +43,7 @@ class SuperCreator extends AbstractOrderedCommandLineRunner { } private IUser createSuperUser() { - Authority adminAuthority = authorityService.getOrCreate(AuthorizingObject.ADMIN) + Authority adminAuthority = authorityService.getOrCreate(Authority.defaultAdminAuthority) IUser superUser = userService.findByEmail("super@netgrif.com", false) if (superUser == null) { diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java index e79f685149..758fcfc24e 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java @@ -16,7 +16,9 @@ public class Authority implements GrantedAuthority { public static final long serialVersionUID = 2839744057647464485L; - public static final List defaultUserAuthorities = Arrays.asList(AuthorizingObject.FILTER, AuthorizingObject.GROUP); + public static final String defaultAdminAuthority = "*"; + public static final List defaultUserAuthorities = Arrays.asList("FILTER_*", "GROUP_*"); + public static final List defaultAnonymousAuthorities = Arrays.asList("FILTER_*", "GROUP_*"); @Id @Getter @@ -85,8 +87,4 @@ public String toString() { public int hashCode() { return name.hashCode(); } - - public boolean includes(AuthorizingObject authority) { - return authority.name().equals(this.name) || authority.name().startsWith(this.name) || this.name.equals(AuthorizingObject.ADMIN.name()); - } } diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java b/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java index 7188eb5578..5705da6ba1 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java @@ -48,7 +48,7 @@ public void parseProcessRoles(Set processRoles) { } public boolean isAdmin() { - return getAuthorities().contains(new Authority(AuthorizingObject.ADMIN)); + return getAuthorities().contains(new Authority(Authority.defaultAdminAuthority)); } public String getEmail() { diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java index 3657899f5e..9c629853ce 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java @@ -1,19 +1,23 @@ package com.netgrif.application.engine.auth.service; -import com.netgrif.application.engine.auth.domain.AuthorizingObject; +import com.netgrif.application.engine.auth.domain.Authority; +import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.auth.service.interfaces.IBaseAuthorizationService; import com.netgrif.application.engine.auth.service.interfaces.IUserService; public abstract class AbstractBaseAuthorizationService implements IBaseAuthorizationService { private final IUserService userService; + private final IAuthorityService authorityService; - public AbstractBaseAuthorizationService(IUserService userService) { + public AbstractBaseAuthorizationService(IUserService userService, IAuthorityService authorityService) { this.userService = userService; + this.authorityService = authorityService; } @Override - public final boolean hasAuthority(AuthorizingObject authority) { - return this.userService.getLoggedUser().getAuthorities().stream().anyMatch(a -> a.includes(authority)); + public final boolean hasAuthority(String authorizingObject) { + + return this.userService.getLoggedUser().getAuthorities().stream().anyMatch(a -> a.equals(authorizingObject)); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index 1da7a2f8e8..566982bebd 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -1,7 +1,6 @@ package com.netgrif.application.engine.auth.service; import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.domain.repositories.AuthorityRepository; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import org.springframework.beans.factory.annotation.Autowired; @@ -33,19 +32,13 @@ public Authority getOrCreate(String name) { return authority; } - @Override - @Transactional - public Authority getOrCreate(AuthorizingObject authorizingObject) { - return getOrCreate(authorizingObject.name()); - } - @Override public Authority save(Authority authority) { return repository.save(authority); } @Override - public List getOrCreate(List authorities) { + public List getOrCreate(List authorities) { if (authorities == null) return Collections.emptyList(); return authorities.stream().map(this::getOrCreate).collect(Collectors.toList()); @@ -60,6 +53,31 @@ public Authority delete(String name) { return authority; } + @Override + public List findByScope(String scope) { + List authorities; + if (scope.equals("*")) + authorities = repository.findAll(); + else { + String prefix = scope.replace("*", ""); + authorities = repository.findAll().stream().filter(authority -> authority.getName().startsWith(prefix)).collect(Collectors.toList()); + } + return authorities; + } + + @Override + public Authority findByName(String name) { + Authority authority = repository.findByName(name); + if (authority == null) + throw new IllegalArgumentException("Could not find authority with name [" + name + "]"); + return authority; + } + + @Override + public Optional findById(String id) { + return repository.findById(id); + } + public Authority getOne(String id) { Optional authority = repository.findById(id); if (authority.isEmpty()) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java similarity index 92% rename from src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java rename to src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java index b091261ba7..5b291bdde1 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java @@ -1,8 +1,6 @@ package com.netgrif.application.engine.auth.service; -import com.netgrif.application.engine.auth.domain.Author; import com.netgrif.application.engine.auth.domain.Authorize; -import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.configuration.ApplicationContextProvider; @@ -32,10 +30,10 @@ @Slf4j @Aspect @Service -public class BaseAuthorizationService extends AbstractBaseAuthorizationService { +public class BaseAuthorizationServiceAspect extends AbstractBaseAuthorizationService { - public BaseAuthorizationService(@Autowired IUserService userService) { - super(userService); + public BaseAuthorizationServiceAspect(@Autowired IUserService userService, @Autowired IAuthorityService authorityService) { + super(userService, authorityService); } /** diff --git a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java index a905684c43..d408f16dfb 100755 --- a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java @@ -1,9 +1,9 @@ package com.netgrif.application.engine.auth.service; import com.netgrif.application.engine.auth.domain.*; -import com.netgrif.application.engine.auth.domain.repositories.AuthorityRepository; import com.netgrif.application.engine.auth.domain.repositories.UserRepository; import com.netgrif.application.engine.auth.service.interfaces.IAfterRegistrationAuthService; +import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService; import com.netgrif.application.engine.auth.web.requestbodies.UpdateUserRequest; import com.netgrif.application.engine.event.events.user.UserRegistrationEvent; @@ -31,7 +31,7 @@ public class UserService extends AbstractUserService { protected UserRepository userRepository; @Autowired - protected AuthorityRepository authorityRepository; + protected IAuthorityService authorityService; @Autowired protected IProcessRoleService processRoleService; @@ -130,7 +130,7 @@ public void addAnonymousRole(User user) { public void addDefaultAuthorities(User user) { if (user.getAuthorities().isEmpty()) { HashSet authorities = new HashSet<>(); - Authority.defaultUserAuthorities.forEach(a -> authorities.add(authorityRepository.findByName(a.name()))); + Authority.defaultUserAuthorities.forEach(a -> authorities.add(authorityService.findByName(a))); user.setAuthorities(authorities); } } @@ -138,7 +138,7 @@ public void addDefaultAuthorities(User user) { public void addAnonymousAuthorities(User user) { if (user.getAuthorities().isEmpty()) { HashSet authorities = new HashSet<>(); - authorities.add(authorityRepository.findByName(AuthorizingObject.ANONYMOUS.name())); + Authority.defaultAnonymousAuthorities.forEach(a -> authorities.add(authorityService.findByName(a))); user.setAuthorities(authorities); } } @@ -269,7 +269,7 @@ public IUser getLoggedOrSystem() { @Override public void assignAuthority(String userId, String authorityId) { Optional user = userRepository.findById(userId); - Optional authority = authorityRepository.findById(authorityId); + Optional authority = authorityService.findById(authorityId); if (user.isEmpty()) throw new IllegalArgumentException("Could not find user with id [" + userId + "]"); diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java index 75166e6ae2..36b8b78958 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java @@ -1,21 +1,27 @@ package com.netgrif.application.engine.auth.service.interfaces; +import com.netgrif.application.engine.auth.domain.Author; import com.netgrif.application.engine.auth.domain.Authority; import com.netgrif.application.engine.auth.domain.AuthorizingObject; import java.util.List; +import java.util.Optional; public interface IAuthorityService { List findAll(); - Authority getOrCreate(String name); + List findByScope(String scope); + + Authority findByName(String name); - Authority getOrCreate(AuthorizingObject authorizingObject); + Optional findById(String id); + + Authority getOrCreate(String name); Authority save(Authority authority); - List getOrCreate(List authorities); + List getOrCreate(List authorities); Authority delete(String name); diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java index 03c1162189..85808a1c71 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java @@ -4,5 +4,5 @@ public interface IBaseAuthorizationService { - boolean hasAuthority(AuthorizingObject authority); + boolean hasAuthority(String authorityName); } diff --git a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java index 546a579964..d4c21efa54 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java @@ -1,9 +1,6 @@ package com.netgrif.application.engine.auth.web; -import com.netgrif.application.engine.auth.domain.AuthorizingObject; -import com.netgrif.application.engine.auth.domain.Authorize; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.auth.domain.*; import com.netgrif.application.engine.auth.domain.throwable.UnauthorisedRequestException; import com.netgrif.application.engine.auth.service.UserDetailsServiceImpl; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; @@ -175,7 +172,7 @@ public PagedModel getAllWithRole(@RequestBody Set roleIds, return resources; } - @Authorize(authority = AuthorizingObject.USER_EDIT) + @Authorize(authority = "USER_EDIT") @ApiOperation(value = "Assign role to the user", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) @@ -195,7 +192,7 @@ public MessageResource assignRolesToUser(@PathVariable("id") String userId, @Req } } - @Authorize(authority = AuthorizingObject.ADMIN) + @Authorize(authority = Authority.defaultAdminAuthority) @ApiOperation(value = "Get all authorities of the system", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) @@ -208,7 +205,7 @@ public AuthoritiesResources getAllAuthorities(Authentication auth) { return new AuthoritiesResources(authorityService.findAll()); } - @Authorize(authority = AuthorizingObject.USER_EDIT) + @Authorize(authority = "USER_EDIT") @ApiOperation(value = "Assign authority to the user", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/configuration/SecurityConfiguration.java b/src/main/java/com/netgrif/application/engine/configuration/SecurityConfiguration.java index eb6574de8d..0c385e3c84 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/SecurityConfiguration.java +++ b/src/main/java/com/netgrif/application/engine/configuration/SecurityConfiguration.java @@ -40,6 +40,7 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import java.util.HashSet; +import java.util.List; import static org.springframework.http.HttpMethod.OPTIONS; @@ -176,12 +177,12 @@ protected Environment getEnvironment() { } private PublicAuthenticationFilter createPublicAuthenticationFilter() throws Exception { - Authority authority = authorityService.getOrCreate(AuthorizingObject.ANONYMOUS); - authority.setUsers(new HashSet<>()); + List authorities = authorityService.getOrCreate(Authority.defaultAnonymousAuthorities); + authorities.forEach(a -> a.setUsers(new HashSet<>())); return new PublicAuthenticationFilter( authenticationManager(), new AnonymousAuthenticationProvider(UserProperties.ANONYMOUS_AUTH_KEY), - authority, + authorities, this.serverPatterns, this.anonymousExceptions, this.jwtService, diff --git a/src/main/java/com/netgrif/application/engine/configuration/SecurityConfigurationLdap.java b/src/main/java/com/netgrif/application/engine/configuration/SecurityConfigurationLdap.java index 57fe084786..d9fc039b14 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/SecurityConfigurationLdap.java +++ b/src/main/java/com/netgrif/application/engine/configuration/SecurityConfigurationLdap.java @@ -4,6 +4,7 @@ import com.netgrif.application.engine.auth.domain.Authority; import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.domain.IUser; +import com.netgrif.application.engine.auth.domain.UserProperties; import com.netgrif.application.engine.ldap.domain.LdapUser; import com.netgrif.application.engine.auth.service.AfterRegistrationAuthService; import com.netgrif.application.engine.auth.service.interfaces.IAfterRegistrationAuthService; @@ -54,6 +55,7 @@ import java.util.Collection; import java.util.HashSet; +import java.util.List; import static org.springframework.http.HttpMethod.OPTIONS; @@ -228,12 +230,12 @@ protected Environment getEnvironment() { } private PublicAuthenticationFilter createPublicAuthenticationFilter() throws Exception { - Authority authority = authorityService.getOrCreate(AuthorizingObject.ANONYMOUS); - authority.setUsers(new HashSet<>()); + List authorities = authorityService.getOrCreate(Authority.defaultAnonymousAuthorities); + authorities.forEach(a -> a.setUsers(new HashSet<>())); return new PublicAuthenticationFilter( authenticationManager(), - new AnonymousAuthenticationProvider(ANONYMOUS_USER), - authority, + new AnonymousAuthenticationProvider(UserProperties.ANONYMOUS_AUTH_KEY), + authorities, this.serverPatterns, this.anonymousExceptions, this.jwtService, diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/PublicAuthenticationFilter.java b/src/main/java/com/netgrif/application/engine/configuration/security/PublicAuthenticationFilter.java index 25c078f065..a0ea8657f9 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/security/PublicAuthenticationFilter.java +++ b/src/main/java/com/netgrif/application/engine/configuration/security/PublicAuthenticationFilter.java @@ -27,7 +27,7 @@ public class PublicAuthenticationFilter extends OncePerRequestFilter { private final ProviderManager authenticationManager; private final AuthenticationDetailsSource authenticationDetailsSource = new WebAuthenticationDetailsSource(); - private final Authority anonymousAuthority; + private final List anonymousAuthorities; private final static String JWT_HEADER_NAME = "X-Jwt-Token"; private final static String BEARER = "Bearer "; @@ -38,11 +38,11 @@ public class PublicAuthenticationFilter extends OncePerRequestFilter { private final IUserService userService; public PublicAuthenticationFilter(ProviderManager authenticationManager, AnonymousAuthenticationProvider provider, - Authority anonymousAuthority, String[] urls, String[] exceptions, IJwtService jwtService, + List anonymousAuthorities, String[] urls, String[] exceptions, IJwtService jwtService, IUserService userService) { this.authenticationManager = authenticationManager; this.authenticationManager.getProviders().add(provider); - this.anonymousAuthority = anonymousAuthority; + this.anonymousAuthorities = anonymousAuthorities; this.anonymousAccessUrls = urls; this.exceptions = exceptions; this.jwtService = jwtService; @@ -63,8 +63,8 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse private void authenticate(HttpServletRequest request, String jwtToken) { AnonymousAuthenticationToken authRequest = new AnonymousAuthenticationToken( UserProperties.ANONYMOUS_AUTH_KEY, - jwtService.getLoggedUser(jwtToken, this.anonymousAuthority), - Collections.singleton(this.anonymousAuthority) + jwtService.getLoggedUser(jwtToken, this.anonymousAuthorities), + this.anonymousAuthorities ); authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request)); Authentication authResult = this.authenticationManager.authenticate(authRequest); diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/jwt/IJwtService.java b/src/main/java/com/netgrif/application/engine/configuration/security/jwt/IJwtService.java index 724089a3df..8358a9ec8f 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/security/jwt/IJwtService.java +++ b/src/main/java/com/netgrif/application/engine/configuration/security/jwt/IJwtService.java @@ -3,6 +3,7 @@ import com.netgrif.application.engine.auth.domain.Authority; import com.netgrif.application.engine.auth.domain.LoggedUser; +import java.util.List; import java.util.Map; public interface IJwtService { @@ -10,5 +11,5 @@ public interface IJwtService { void isExpired(String token); - LoggedUser getLoggedUser(String token, Authority anonymousRole); + LoggedUser getLoggedUser(String token, List anonymousRole); } diff --git a/src/main/java/com/netgrif/application/engine/configuration/security/jwt/JwtService.java b/src/main/java/com/netgrif/application/engine/configuration/security/jwt/JwtService.java index cdfcc1a226..52d6c450f7 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/security/jwt/JwtService.java +++ b/src/main/java/com/netgrif/application/engine/configuration/security/jwt/JwtService.java @@ -53,13 +53,13 @@ public void isExpired(String token) throws ExpiredJwtException { } @Override - public LoggedUser getLoggedUser(String token, Authority anonymousAuthority) { + public LoggedUser getLoggedUser(String token, List anonymousAuthority) { LinkedHashMap userMap = (LinkedHashMap) getAllClaimsFromToken(token).get("user"); LoggedUser user = new LoggedUser( userMap.get("id").toString(), userMap.get("username").toString(), userMap.get("password").toString(), - Collections.singleton(anonymousAuthority) + anonymousAuthority ); user.setFullName(userMap.get("fullName").toString()); user.setAnonymous((boolean) userMap.get("anonymous")); diff --git a/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java b/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java index 0e9901d032..a9e62f9814 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java +++ b/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java @@ -1,5 +1,6 @@ package com.netgrif.application.engine.elastic.web; +import com.netgrif.application.engine.auth.domain.Authority; import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; @@ -49,7 +50,7 @@ public class ElasticController { @Value("${spring.data.elasticsearch.reindex-size}") private int pageSize; - @Authorize(authority = AuthorizingObject.ADMIN) + @Authorize(authority = Authority.defaultAdminAuthority) @ApiOperation(value = "Reindex specified cases", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java index a39d749d08..ae6973721b 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java @@ -32,7 +32,7 @@ public class GroupController { @Autowired private INextGroupService service; - @Authorize(authority = AuthorizingObject.GROUP_VIEW_ALL) + @Authorize(authority = "GROUP_VIEW_ALL") @ApiOperation(value = "Get all groups in the system", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java index cb1c9558ee..6d7e3bf15b 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java @@ -1,5 +1,6 @@ package com.netgrif.application.engine.workflow.web; +import com.netgrif.application.engine.auth.domain.Authority; import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; @@ -166,7 +167,7 @@ public PagedModel findAllByAuthor(@PathVariable("id") String autho return resources; } - @Authorize(authority = AuthorizingObject.ADMIN) + @Authorize(authority = Authority.defaultAdminAuthority) @ApiOperation(value = "Reload tasks of case", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) @@ -189,7 +190,7 @@ public MessageResource reloadTasks(@PathVariable("id") String caseId) { } @Deprecated - @Authorize(authority = AuthorizingObject.ADMIN) + @Authorize(authority = Authority.defaultAdminAuthority) @ApiOperation(value = "Get all case data", authorizations = @Authorization("BasicAuth")) @GetMapping(value = "/case/{id}/data", produces = MediaTypes.HAL_JSON_VALUE) public DataFieldsResource getAllCaseData(@PathVariable("id") String caseId, Locale locale) { diff --git a/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy index 7f7aa864fd..8d4f4166b0 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy @@ -94,7 +94,7 @@ class AssignActionTest { createMainAndSecondaryNet() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) def authorityList = Stream.concat(auths.get("user").stream(), auths.get("admin").stream()).collect(Collectors.toList()).toArray() importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), diff --git a/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy index 7178b7169c..f8554c3bdf 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy @@ -97,7 +97,7 @@ class RemoveActionTest { this.petriNet = net.getNet() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), [auths.get("user")] as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy index 5f52bb5b47..d24d6d8cb5 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy @@ -68,7 +68,7 @@ class FilterAuthorizationServiceTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy b/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy index f9c0513b59..9003da5163 100644 --- a/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy @@ -109,7 +109,7 @@ class ElasticSearchTest { netId2 = net2.getStringId() // def org = importHelper.createGroup("Test") - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) // def processRoles = importHelper.getProcessRoles(net.get()) def testUser = importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSW, state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy b/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy index beb8e3be28..0af6e67a7f 100644 --- a/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy @@ -81,7 +81,7 @@ class GroovyShellFactoryTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["systemAdmin": [AuthorizingObject.ADMIN]]) + def auths = importHelper.createAuthorities(["systemAdmin": [Authority.defaultAdminAuthority]]) importHelper.createUser(new User(name: "Admin", surname: "User", email: USER_EMAIL, password: USER_PASSW, state: UserState.ACTIVE), auths.get("systemAdmin").toArray() as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy b/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy index 05b711a046..9c46911782 100644 --- a/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy @@ -300,7 +300,7 @@ class FilterImportExportTest { } private User createDummyUser() { - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) return importHelper.createUser(new User(name: "Dummy", surname: "User", email: DUMMY_USER_MAIL, password: DUMMY_USER_PASSWORD, state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy b/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy index d074561723..cdf03fe4ef 100644 --- a/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy @@ -136,7 +136,7 @@ class InsuranceTest { netId = net.getNet().getStringId() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) def authorityArray = Stream.concat(auths.get("user").stream(), auths.get("admin").stream()).toArray() def processRoles = importHelper.getProcessRolesByImportId(net.getNet(), ["agent": "1", "company": "2"]) importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), diff --git a/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy b/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy index 21116126fb..8888ced299 100644 --- a/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy @@ -199,7 +199,7 @@ class MenuImportExportTest { } private User createDummyUser() { - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) return importHelper.createUser(new User(name: "Dummy", surname: "User", email: DUMMY_USER_MAIL, password: DUMMY_USER_PASSWORD, state: UserState.ACTIVE), [auths.get("user")] as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy index 9353763ea6..a30903dbcb 100644 --- a/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy @@ -46,7 +46,7 @@ class NextGroupServiceTest { @Test void groupTest() { testHelper.truncateDbs() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) importHelper.createUser(new User(name: "Dummy", surname: "User", email: DUMMY_USER_MAIL, password: "password", state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy index 3d88ebef9b..53a98d1152 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy @@ -91,7 +91,7 @@ class ProcessRoleTest { String netId = net.getNet().getStringId() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) def processRoles = userProcessRoleRepository.findAllByNetId(netId) importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL_VIEW, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy index 2fd108c173..06d3ae57a9 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy @@ -74,7 +74,7 @@ class PetriNetServiceTest { @BeforeEach void setup() { testHelper.truncateDbs() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) importHelper.createUser(new User(name: "Customer", surname: "User", email: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy index cbc82684a1..154cf7944f 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy @@ -85,7 +85,7 @@ class PetriNetControllerTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [AuthorizingObject.ADMIN]]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], From cb19c591ef6047f53481752ebc23f4e50c1f91c6 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 16 May 2022 10:03:35 +0200 Subject: [PATCH 28/68] [NAE-1617] Refactor Authority - refactored BaseAuthorizationServiceAspect to resolve multiple authorize annotations --- .../BaseAuthorizationServiceAspect.java | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java index 5b291bdde1..9ba41bbb33 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java @@ -1,5 +1,6 @@ package com.netgrif.application.engine.auth.service; +import com.netgrif.application.engine.auth.domain.Authorizations; import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.auth.service.interfaces.IUserService; @@ -37,23 +38,31 @@ public BaseAuthorizationServiceAspect(@Autowired IUserService userService, @Auto } /** - * Pointcut definition for {@link Authorize} annotation to connect authorization requests from join points to the - * {@link #authorize(ProceedingJoinPoint, Authorize)} advice. - * @param authorize the annotation with authorization requirements + * Pointcut definition for {@link Authorizations} annotation to connect authorization requests from join points to the + * {@link #authorize(ProceedingJoinPoint, Authorizations)} advice. + * @param authorizations the annotation with authorization requirements * */ - @Pointcut(value = "@annotation(authorize))") - protected void authorizingMethod(Authorize authorize) {} + @Pointcut(value = "@annotation(authorizations))") + protected void authorizingMethod(Authorizations authorizations) {} /** * The advice that handles incoming authorization requests from join points from - * {@link #authorizingMethod(Authorize)} pointcuts + * {@link #authorizingMethod(Authorizations)} pointcuts * @param joinPoint the incoming method invocation join point - * @param authorize the incoming annotation with authorization parameters + * @param authorizations the incoming annotation with authorization parameters * */ - @Around(value = "authorizingMethod(authorize)", argNames = "joinPoint,authorize") - protected Object authorize(ProceedingJoinPoint joinPoint, Authorize authorize) throws Throwable { - if (isAllowedByExpression(joinPoint, authorize.expression()) || hasAuthority(authorize.authority())) { + @Around(value = "authorizingMethod(authorizations)", argNames = "joinPoint,authorizations") + protected Object authorize(ProceedingJoinPoint joinPoint, Authorizations authorizations) throws Throwable { + boolean result = false; + + if (authorizations.value() != null && authorizations.value().length > 0) { + for (Authorize authorize : authorizations.value()) { + result = result || (isAllowedByExpression(joinPoint, authorize.expression()) && hasAuthority(authorize.authority())); + } + } + + if (result) { return joinPoint.proceed(); } else { throw new AccessDeniedException("Access Denied"); From f6b7fe5b85b2c0f979ac505c93b0eb6ac35c5028 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 16 May 2022 10:24:23 +0200 Subject: [PATCH 29/68] [NAE-1617] Refactor Authority - refactored Authorize annotations over methods to use Authorizations annotation - created new AuthorizingObject --- .../logic/action/ActionDelegate.groovy | 41 ++++++++++++++----- .../engine/auth/domain/Authorizations.java | 6 +++ .../engine/auth/domain/AuthorizingObject.java | 22 ++++++---- .../engine/auth/web/UserController.java | 12 ++++-- .../petrinet/web/PetriNetController.java | 9 +++- .../engine/workflow/web/TaskController.java | 38 +++++++++++++---- .../workflow/web/WorkflowController.java | 21 ++++++---- 7 files changed, 110 insertions(+), 39 deletions(-) diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy index e02688c6d3..f3e36761d8 100644 --- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.petrinet.domain.dataset.logic.action import com.netgrif.application.engine.AsyncRunner import com.netgrif.application.engine.auth.domain.Author +import com.netgrif.application.engine.auth.domain.Authorizations import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.Authorize import com.netgrif.application.engine.auth.domain.IUser @@ -847,7 +848,9 @@ class ActionDelegate { mailService.sendMail(mailDraft) } - @Authorize(authority = "USER_EDIT", expression = "@userService.isLoggedByEmail(email)") + @Authorizations(value = [ + @Authorize(authority = "USER_EDIT") + ]) def changeUserByEmail(String email) { [email : { cl -> changeUserByEmail(email, "email", cl) @@ -864,7 +867,9 @@ class ActionDelegate { ] } - @Authorize(authority = "USER_EDIT", expression = "@userService.isLogged(#id)") + @Authorizations(value = [ + @Authorize(authority = "USER_EDIT") + ]) def changeUser(String id) { [email : { cl -> changeUser(id, "email", cl) @@ -881,7 +886,9 @@ class ActionDelegate { ] } - @Authorize(authority = "USER_EDIT", expression = "@userService.isLogged(#user)") + @Authorizations(value = [ + @Authorize(authority = "USER_EDIT") + ]) def changeUser(IUser user) { [email : { cl -> changeUser(user, "email", cl) @@ -898,19 +905,25 @@ class ActionDelegate { ] } - @Authorize(authority = "USER_EDIT", expression = "@userService.isLoggedByEmail(#email)") + @Authorizations(value = [ + @Authorize(authority = "USER_EDIT") + ]) def changeUserByEmail(String email, String attribute, def cl) { IUser user = userService.findByEmail(email, false) changeUser(user, attribute, cl) } - @Authorize(authority = "USER_EDIT", expression = "@userService.isLogged(#id)") + @Authorizations(value = [ + @Authorize(authority = "USER_EDIT") + ]) def changeUser(String id, String attribute, def cl) { IUser user = userService.findById(id, false) changeUser(user, attribute, cl) } - @Authorize(authority = "USER_EDIT", expression = "@userService.isLogged(#user)") + @Authorizations(value = [ + @Authorize(authority = "USER_EDIT") + ]) def changeUser(IUser user, String attribute, def cl) { if (user == null) { log.error("Cannot find user.") @@ -926,7 +939,9 @@ class ActionDelegate { userService.save(user) } - @Authorize(authority = "USER_CREATE") + @Authorizations(value = [ + @Authorize(authority = "USER_CREATE") + ]) MessageResource inviteUser(String email) { NewUserRequest newUserRequest = new NewUserRequest() newUserRequest.email = email @@ -935,7 +950,9 @@ class ActionDelegate { return inviteUser(newUserRequest) } - @Authorize(authority = "USER_CREATE") + @Authorizations(value = [ + @Authorize(authority = "USER_CREATE") + ]) MessageResource inviteUser(NewUserRequest newUserRequest) { IUser user = registrationService.createNewUser(newUserRequest); if (user == null) @@ -946,7 +963,9 @@ class ActionDelegate { return MessageResource.successMessage("Done"); } - @Authorize(authority = "USER_DELETE") + @Authorizations(value = [ + @Authorize(authority = "USER_DELETE") + ]) void deleteUser(String email) { IUser user = userService.findByEmail(email, false) if (user == null) @@ -954,7 +973,9 @@ class ActionDelegate { deleteUser(user) } - @Authorize(authority = "USER_DELETE") + @Authorizations(value = [ + @Authorize(authority = "USER_DELETE") + ]) void deleteUser(IUser user) { List tasks = taskService.findByUser(new FullPageRequest(), user).toList() if (tasks != null && tasks.size() > 0) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authorizations.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authorizations.java index b446d3ffcc..7fb58a2771 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authorizations.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authorizations.java @@ -2,11 +2,17 @@ import java.lang.annotation.*; +/** + * Annotation to define set of authorizing statements + * */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD, ElementType.TYPE }) @Inherited @Documented public @interface Authorizations { + /** + * The array of authorizing statements, access will be granted, if one of these is true. + * */ Authorize[] value(); } diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java index 70fc808440..6a8233031b 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java @@ -7,19 +7,27 @@ * */ public enum AuthorizingObject { PROCESS_UPLOAD, - PROCESS_DELETE, + PROCESS_DELETE_MY, + PROCESS_DELETE_ALL, FILTER_UPLOAD, - FILTER_DELETE, + FILTER_DELETE_MY, + FILTER_DELETE_ALL, USER_CREATE, USER_DELETE, - USER_EDIT, + USER_EDIT_MY, + USER_EDIT_ALL, GROUP_CREATE, - GROUP_DELETE, + GROUP_DELETE_MY, + GROUP_DELETE_ALL, GROUP_ADD_USER, GROUP_REMOVE_USER, GROUP_VIEW_ALL, - ROLE_CREATE, // refactor for user "assign" - ROLE_DELETE, // refactor for user "deassign" + GROUP_VIEW_MY, + ROLE_ASSIGN_TO_USER, + ROLE_REMOVE_FROM_USER, AUTHORITY_CREATE, - AUTHORITY_DELETE + AUTHORITY_DELETE, + AUTHORITY_VIEW_ALL, + TASK_RELOAD, + CASE_DATA_GET_ALL, } diff --git a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java index d4c21efa54..3c81085b3d 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java @@ -172,7 +172,9 @@ public PagedModel getAllWithRole(@RequestBody Set roleIds, return resources; } - @Authorize(authority = "USER_EDIT") + @Authorizations(value = { + @Authorize(authority = "USER_EDIT", expression = "@userService.isLogged(#id)") + }) @ApiOperation(value = "Assign role to the user", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) @@ -192,7 +194,9 @@ public MessageResource assignRolesToUser(@PathVariable("id") String userId, @Req } } - @Authorize(authority = Authority.defaultAdminAuthority) + @Authorizations(value = { + @Authorize(authority = "AUTHORITY_VIEW_ALL") + }) @ApiOperation(value = "Get all authorities of the system", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) @@ -205,7 +209,9 @@ public AuthoritiesResources getAllAuthorities(Authentication auth) { return new AuthoritiesResources(authorityService.findAll()); } - @Authorize(authority = "USER_EDIT") + @Authorizations(value = { + @Authorize(authority = "USER_EDIT") + }) @ApiOperation(value = "Assign authority to the user", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index 6d62606c91..e34f42e73d 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -1,5 +1,6 @@ package com.netgrif.application.engine.petrinet.web; +import com.netgrif.application.engine.auth.domain.Authorizations; import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.eventoutcomes.LocalisedEventOutcomeFactory; @@ -69,7 +70,9 @@ public class PetriNetController { @Autowired private StringToVersionConverter converter; - @Authorize(expression = "@petriNetAuthorizationService.canCallImport(#auth.getPrincipal())") + @Authorizations(value = { + @Authorize(expression = "@petriNetAuthorizationService.canCallImport(#auth.getPrincipal())") + }) @ApiOperation(value = "Import new process", notes = "Caller must have the ADMIN role. Imports an entirely new process or a new version of an existing process.", authorizations = @Authorization("BasicAuth")) @@ -178,7 +181,9 @@ PagedModel searchPetriNets(@RequestBody Map assign(Authentication auth, @PathVar return super.assign(loggedUser, taskId, locale); } - @Authorize(expression = "@taskAuthorizationService.canCallDelegate(#auth.getPrincipal(), #taskId)") + @Authorizations(value = { + @Authorize(expression = "@taskAuthorizationService.canCallDelegate(#auth.getPrincipal(), #taskId)") + }) @ApiOperation(value = "Delegate task", notes = "Caller must be able to delegate the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) @@ -110,7 +115,9 @@ public EntityModel delegate(Authentication auth, @Path return super.delegate(loggedUser, taskId, delegatedId, locale); } - @Authorize(expression = "@taskAuthorizationService.canCallFinish(#auth.getPrincipal(), #taskId)") + @Authorizations(value = { + @Authorize(expression = "@taskAuthorizationService.canCallFinish(#auth.getPrincipal(), #taskId)") + }) @ApiOperation(value = "Finish task", notes = "Caller must be assigned to the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) @@ -124,7 +131,9 @@ public EntityModel finish(Authentication auth, @PathVa return super.finish(loggedUser, taskId, locale); } - @Authorize(expression = "@taskAuthorizationService.canCallCancel(#auth.getPrincipal(), #taskId)") + @Authorizations(value = { + @Authorize(expression = "@taskAuthorizationService.canCallCancel(#auth.getPrincipal(), #taskId)") + }) @ApiOperation(value = "Cancel task", notes = "Caller must be assigned to the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) @@ -180,7 +189,10 @@ public EntityModel getData(@PathVariable("id") String return super.getData(taskId, locale); } - @Authorize(expression = "@taskAuthorizationService.canCallSaveData(#auth.getPrincipal(), #taskId)") + + @Authorizations(value = { + @Authorize(expression = "@taskAuthorizationService.canCallSaveData(#auth.getPrincipal(), #taskId)") + }) @ApiOperation(value = "Set task data", notes = "Caller must be assigned to the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) @@ -193,7 +205,9 @@ public EntityModel setData(Authentication auth, @PathV return super.setData(taskId, dataBody); } - @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + @Authorizations(value = { + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + }) @ApiOperation(value = "Upload file into the task", notes = "Caller must be assigned to the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) @@ -213,7 +227,9 @@ public ResponseEntity getFile(@PathVariable("id") String taskId, @Path return super.getFile(taskId, fieldId); } - @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + @Authorizations(value = { + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + }) @ApiOperation(value = "Remove file from the task", notes = "Caller must be assigned to the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) @@ -226,7 +242,9 @@ public MessageResource deleteFile(Authentication auth, @PathVariable("id") Strin return super.deleteFile(taskId, fieldId); } - @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + @Authorizations(value = { + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + }) @ApiOperation(value = "Upload multiple files into the task", notes = "Caller must be assigned to the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) @@ -247,7 +265,9 @@ public ResponseEntity getNamedFile(@PathVariable("id") String taskId, return super.getNamedFile(taskId, fieldId, name); } - @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + @Authorizations(value = { + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") + }) @ApiOperation(value = "Remove file from tasks file list field value", notes = "Caller must be assigned to the task, or must be an ADMIN", authorizations = @Authorization("BasicAuth")) diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java index 6d7e3bf15b..f833b87d84 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java @@ -1,9 +1,6 @@ package com.netgrif.application.engine.workflow.web; -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.AuthorizingObject; -import com.netgrif.application.engine.auth.domain.Authorize; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.auth.domain.*; import com.netgrif.application.engine.elastic.domain.ElasticCase; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.elastic.web.requestbodies.singleaslist.SingleCaseSearchRequestAsList; @@ -77,7 +74,9 @@ public class WorkflowController { private IDataService dataService; - @Authorize(expression = "@workflowAuthorizationService.canCallCreate(#auth.getPrincipal(), #body.netId)") + @Authorizations(value = { + @Authorize(expression = "@workflowAuthorizationService.canCallCreate(#auth.getPrincipal(), #body.netId)") + }) @ApiOperation(value = "Create new case", authorizations = @Authorization("BasicAuth")) @PostMapping(value = "/case", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public EntityModel createCase(@RequestBody CreateCaseBody body, Authentication auth, Locale locale) { @@ -167,7 +166,9 @@ public PagedModel findAllByAuthor(@PathVariable("id") String autho return resources; } - @Authorize(authority = Authority.defaultAdminAuthority) + @Authorizations(value = { + @Authorize(authority = "TASK_RELOAD") + }) @ApiOperation(value = "Reload tasks of case", notes = "Caller must have the ADMIN role", authorizations = @Authorization("BasicAuth")) @@ -190,7 +191,9 @@ public MessageResource reloadTasks(@PathVariable("id") String caseId) { } @Deprecated - @Authorize(authority = Authority.defaultAdminAuthority) + @Authorizations(value = { + @Authorize(authority = "CASE_DATA_GET_ALL") + }) @ApiOperation(value = "Get all case data", authorizations = @Authorization("BasicAuth")) @GetMapping(value = "/case/{id}/data", produces = MediaTypes.HAL_JSON_VALUE) public DataFieldsResource getAllCaseData(@PathVariable("id") String caseId, Locale locale) { @@ -203,7 +206,9 @@ public DataFieldsResource getAllCaseData(@PathVariable("id") String caseId, Loca } } - @Authorize(expression = "@workflowAuthorizationService.canCallDelete(#auth.getPrincipal(), #caseId)") + @Authorizations(value = { + @Authorize(expression = "@workflowAuthorizationService.canCallDelete(#auth.getPrincipal(), #caseId)") + }) @ApiOperation(value = "Delete case", authorizations = @Authorization("BasicAuth")) @DeleteMapping(value = "/case/{id}", produces = MediaTypes.HAL_JSON_VALUE) public EntityModel deleteCase(Authentication auth, @PathVariable("id") String caseId, @RequestParam(defaultValue = "false") boolean deleteSubtree) { From 012922a9bbd564ec4c05755d810292e582d26ac4 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 16 May 2022 10:31:29 +0200 Subject: [PATCH 30/68] [NAE-1617] Refactor Authority - implemented new endpoint to get only groups of logged user --- .../orgstructure/web/GroupController.java | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java index ae6973721b..6a9ef9b740 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java @@ -1,7 +1,6 @@ package com.netgrif.application.engine.orgstructure.web; -import com.netgrif.application.engine.auth.domain.AuthorizingObject; -import com.netgrif.application.engine.auth.domain.Authorize; +import com.netgrif.application.engine.auth.domain.*; import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService; import com.netgrif.application.engine.orgstructure.web.responsebodies.Group; import com.netgrif.application.engine.orgstructure.web.responsebodies.GroupsResource; @@ -10,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.hateoas.MediaTypes; +import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @@ -32,9 +32,11 @@ public class GroupController { @Autowired private INextGroupService service; - @Authorize(authority = "GROUP_VIEW_ALL") + @Authorizations(value = { + @Authorize(authority = "GROUP_VIEW_ALL") + }) @ApiOperation(value = "Get all groups in the system", - notes = "Caller must have the ADMIN role", + notes = "Caller must have the GROUP_VIEW_ALL authority", authorizations = @Authorization("BasicAuth")) @RequestMapping(value = "/all", method = RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE) @ApiResponses(value = { @@ -49,6 +51,27 @@ public GroupsResource getAllGroups() { return new GroupsResource(groupResponse); } + @Authorizations(value = { + @Authorize(authority = "GROUP_VIEW_MY") + }) + @ApiOperation(value = "Get logged user's groups in the system", + notes = "Caller must have the GROUP_VIEW_MY authority", + authorizations = @Authorization("BasicAuth")) + @RequestMapping(value = "/all", method = RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK", response = GroupsResource.class), + @ApiResponse(code = 403, message = "Caller doesn't fulfill the authorisation requirements"), + }) + public GroupsResource getMyGroups(Authentication auth) { + String loggedUserId = ((LoggedUser)auth.getPrincipal()).getId(); + List groups = service.findAllGroups(); + Set groupResponse = groups.stream() + .filter(aCase -> aCase.getAuthor().getId().equals(loggedUserId)) + .map(aCase -> new Group(aCase.getStringId(), aCase.getTitle())) + .collect(Collectors.toCollection(HashSet::new)); + return new GroupsResource(groupResponse); + } + // @ApiOperation(value = "Get all the user's groups", authorizations = @Authorization("BasicAuth")) // @GetMapping(value = "/my", produces = MediaTypes.HAL_JSON_VALUE) // public GroupsResource getGroupsOfUser(Authentication auth) { From 47044e3db94802ac20325e310da48741b6fb2db1 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 16 May 2022 10:32:50 +0200 Subject: [PATCH 31/68] [NAE-1617] Refactor Authority - renamed requestmapping in GroupController --- .../application/engine/orgstructure/web/GroupController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java index 6a9ef9b740..648f0ecb7d 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java @@ -57,7 +57,7 @@ public GroupsResource getAllGroups() { @ApiOperation(value = "Get logged user's groups in the system", notes = "Caller must have the GROUP_VIEW_MY authority", authorizations = @Authorization("BasicAuth")) - @RequestMapping(value = "/all", method = RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE) + @RequestMapping(value = "/my", method = RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE) @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = GroupsResource.class), @ApiResponse(code = 403, message = "Caller doesn't fulfill the authorisation requirements"), From adf1710b505104c3cfd32b9b61381f4e7960d91d Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 16 May 2022 10:37:54 +0200 Subject: [PATCH 32/68] [NAE-1617] Refactor Authority - implemented endpoint to remove authority from user --- .../engine/auth/domain/AbstractUser.java | 6 ++++++ .../engine/auth/domain/Authority.java | 4 ++++ .../application/engine/auth/domain/IUser.java | 2 ++ .../engine/auth/service/AbstractUserService.java | 10 ++++++++++ .../engine/auth/service/UserService.java | 16 ++++++++++++++++ .../auth/service/interfaces/IUserService.java | 2 ++ .../engine/auth/web/UserController.java | 16 ++++++++++++++++ 7 files changed, 56 insertions(+) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AbstractUser.java b/src/main/java/com/netgrif/application/engine/auth/domain/AbstractUser.java index cc81528313..d5fa705389 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AbstractUser.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AbstractUser.java @@ -40,6 +40,12 @@ public void addAuthority(Authority authority) { authorities.add(authority); } + public void removeAuthority(Authority authority) { + if (authorities.stream().noneMatch(it -> it.get_id().equals(authority.get_id()))) + return; + authorities.remove(authority); + } + public void addProcessRole(ProcessRole role) { if (processRoles.stream().anyMatch(it -> it.getStringId().equals(role.getStringId()))) return; diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java index 758fcfc24e..6347664fe4 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java @@ -52,6 +52,10 @@ public void addUser(IUser user) { users.add(user.getStringId()); } + public void removeUser(IUser user) { + users.remove(user.getStringId()); + } + public String getStringId() { return _id.toString(); } diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/IUser.java b/src/main/java/com/netgrif/application/engine/auth/domain/IUser.java index 3e69928dab..1cb61ca2b6 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/IUser.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/IUser.java @@ -48,6 +48,8 @@ public interface IUser { void addAuthority(Authority authority); + void removeAuthority(Authority authority); + void addProcessRole(ProcessRole role); void removeProcessRole(ProcessRole role); diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java index a7fe79836f..da4b050045 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java @@ -63,6 +63,16 @@ public void assignAuthority(String userId, String authorityId) { save(user); } + @Override + public void removeAuthority(String userId, String authorityId) { + IUser user = resolveById(userId, true); + Authority authority = authorityService.getOne(authorityId); + user.removeAuthority(authority); + authority.removeUser(user); + + save(user); + } + @Override public LoggedUser getAnonymousLogged() { if (SecurityContextHolder.getContext().getAuthentication().getPrincipal().equals(UserProperties.ANONYMOUS_AUTH_KEY)) { diff --git a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java index d408f16dfb..5228737cbe 100755 --- a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java @@ -282,6 +282,22 @@ public void assignAuthority(String userId, String authorityId) { userRepository.save(user.get()); } + @Override + public void removeAuthority(String userId, String authorityId) { + Optional user = userRepository.findById(userId); + Optional authority = authorityService.findById(authorityId); + + if (user.isEmpty()) + throw new IllegalArgumentException("Could not find user with id [" + userId + "]"); + if (authority.isEmpty()) + throw new IllegalArgumentException("Could not find authority with id [" + authorityId + "]"); + + user.get().removeAuthority(authority.get()); + authority.get().removeUser(user.get()); + + userRepository.save(user.get()); + } + @Override public IUser getSystem() { return userRepository.findByEmail(SystemUserRunner.SYSTEM_USER_EMAIL); diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserService.java index af8ab5e544..a55553848a 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserService.java @@ -52,6 +52,8 @@ public interface IUserService { void assignAuthority(String userId, String authorityId); + void removeAuthority(String userId, String authorityId); + IUser getLoggedOrSystem(); IUser getLoggedUser(); diff --git a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java index 3c81085b3d..393d8b969b 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java @@ -225,6 +225,22 @@ public MessageResource assignAuthorityToUser(@PathVariable("id") String userId, return MessageResource.successMessage("Authority " + authorityId + " assigned to user " + userId); } + @Authorizations(value = { + @Authorize(authority = "USER_EDIT") + }) + @ApiOperation(value = "Assign authority to the user", + notes = "Caller must have the USER_EDIT authority", + authorizations = @Authorization("BasicAuth")) + @DeleteMapping(value = "/{id}/authority/remove", consumes = MediaType.TEXT_PLAIN_VALUE, produces = MediaTypes.HAL_JSON_VALUE) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK", response = MessageResource.class), + @ApiResponse(code = 403, message = "Caller doesn't fulfill the authorisation requirements"), + }) + public MessageResource removeAuthorityFromUser(@PathVariable("id") String userId, @RequestBody String authorityId) { + userService.removeAuthority(userId, authorityId); + return MessageResource.successMessage("Authority " + authorityId + " removed from user " + userId); + } + @ApiOperation(value = "Get user's preferences", authorizations = @Authorization("BasicAuth")) @GetMapping(value = "/preferences", produces = MediaTypes.HAL_JSON_VALUE) public PreferencesResource preferences(Authentication auth) { From 6dfca41a41d660e912ee256978977d07c2e84b0f Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 16 May 2022 13:01:05 +0200 Subject: [PATCH 33/68] [NAE-1617] Refactor Authority - implemented adding of additional authorities --- .../engine/startup/AuthorityRunner.groovy | 8 ++++++++ .../application/engine/startup/SuperCreator.groovy | 14 ++++++++------ src/main/resources/application.properties | 5 ++++- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy index b6b79f5b02..d6101c55fd 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy @@ -2,17 +2,25 @@ package com.netgrif.application.engine.startup import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService +import groovy.util.logging.Slf4j import org.springframework.beans.factory.annotation.Autowired +import org.springframework.beans.factory.annotation.Value import org.springframework.stereotype.Component +@Slf4j @Component class AuthorityRunner extends AbstractOrderedCommandLineRunner { + @Value('${nae.authority.additional:}') + private String[] additionalAuthorities + @Autowired private IAuthorityService service @Override void run(String... strings) throws Exception { AuthorizingObject.values().toList().forEach(authority -> service.getOrCreate(authority.name())) + additionalAuthorities.toList().forEach(authority -> service.getOrCreate(authority)) + log.info("Authorities created.") } } \ No newline at end of file diff --git a/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy b/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy index b2476432e1..aa7058a0a4 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy @@ -43,8 +43,7 @@ class SuperCreator extends AbstractOrderedCommandLineRunner { } private IUser createSuperUser() { - Authority adminAuthority = authorityService.getOrCreate(Authority.defaultAdminAuthority) - + List adminAuthorities = authorityService.findByScope(Authority.defaultAdminAuthority) IUser superUser = userService.findByEmail("super@netgrif.com", false) if (superUser == null) { this.superUser = userService.saveNew(new User( @@ -53,7 +52,7 @@ class SuperCreator extends AbstractOrderedCommandLineRunner { email: "super@netgrif.com", password: superAdminPassword, state: UserState.ACTIVE, - authorities: [adminAuthority] as Set, + authorities: adminAuthorities as Set, processRoles: processRoleService.findAll() as Set)) log.info("Super user created") } else { @@ -61,15 +60,18 @@ class SuperCreator extends AbstractOrderedCommandLineRunner { this.superUser = superUser } - adminAuthority.addUser(this.superUser) - authorityService.save(adminAuthority) + adminAuthorities.forEach({ + it.addUser(this.superUser) + authorityService.save(it) + }) + return this.superUser } void setAllToSuperUser() { setAllGroups() setAllProcessRoles() - //setAllAuthorities() + setAllAuthorities() log.info("Super user updated") } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index e3181ad0cc..8cd1101360 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -159,4 +159,7 @@ nae.field-runner.cache-size.namespace-functions=500 # Filter export file name nae.filter.export.file-name=filters.xml -#server.port=8080 \ No newline at end of file +#server.port=8080 + +# Authorities +nae.authority.additional=SCOPE_AUTHORITY_EXAMPLE \ No newline at end of file From c554bfa78b3c54367812f32a63937a9fdad93ec7 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 16 May 2022 14:21:26 +0200 Subject: [PATCH 34/68] [NAE-1617] Refactor Authority - refactored annotations and removed isAdmin function from LoggedUser - implemented hasAuthority to loggedUser --- .../engine/auth/domain/Authority.java | 4 ++-- .../engine/auth/domain/AuthorizingObject.java | 17 ++++++++++++-- .../engine/auth/domain/LoggedUser.java | 8 +++---- .../AbstractBaseAuthorizationService.java | 5 ++-- .../service/interfaces/IAuthorityService.java | 2 -- .../auth/web/AuthenticationController.java | 9 ++++++-- .../engine/auth/web/UserController.java | 4 ++-- .../service/PetriNetAuthorizationService.java | 19 --------------- .../petrinet/service/PetriNetService.java | 2 +- .../IPetriNetAuthorizationService.java | 11 --------- .../petrinet/web/PetriNetController.java | 7 ++++-- .../service/FilterAuthorizationService.java | 2 +- .../service/TaskAuthorizationService.java | 12 +++++----- .../service/WorkflowAuthorizationService.java | 4 ++-- .../engine/workflow/web/FilterController.java | 5 ++++ .../workflow/web/PublicTaskController.java | 23 ++++++++++++++----- .../engine/workflow/web/TaskController.java | 10 ++++++++ .../workflow/web/WorkflowController.java | 5 ++++ 18 files changed, 85 insertions(+), 64 deletions(-) delete mode 100644 src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java delete mode 100644 src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetAuthorizationService.java diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java index 6347664fe4..5d048abbc6 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java @@ -17,8 +17,8 @@ public class Authority implements GrantedAuthority { public static final long serialVersionUID = 2839744057647464485L; public static final String defaultAdminAuthority = "*"; - public static final List defaultUserAuthorities = Arrays.asList("FILTER_*", "GROUP_*"); - public static final List defaultAnonymousAuthorities = Arrays.asList("FILTER_*", "GROUP_*"); + public static final List defaultUserAuthorities = Arrays.asList("FILTER_*", "GROUP_VIEW_MY"); + public static final List defaultAnonymousAuthorities = Collections.emptyList(); @Id @Getter diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java index 6a8233031b..3e7b1beb2d 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java @@ -7,6 +7,8 @@ * */ public enum AuthorizingObject { PROCESS_UPLOAD, + PROCESS_VIEW_ALL, + PROCESS_VIEW_MY, PROCESS_DELETE_MY, PROCESS_DELETE_ALL, FILTER_UPLOAD, @@ -14,8 +16,10 @@ public enum AuthorizingObject { FILTER_DELETE_ALL, USER_CREATE, USER_DELETE, - USER_EDIT_MY, USER_EDIT_ALL, + USER_EDIT_MY, + USER_VIEW_ALL, + USER_VIEW_MY, GROUP_CREATE, GROUP_DELETE_MY, GROUP_DELETE_ALL, @@ -28,6 +32,15 @@ public enum AuthorizingObject { AUTHORITY_CREATE, AUTHORITY_DELETE, AUTHORITY_VIEW_ALL, - TASK_RELOAD, + CASE_VIEW_ALL, + CASE_VIEW_MY, + CASE_CREATE, + CASE_DELETE, CASE_DATA_GET_ALL, + TASK_RELOAD, + TASK_ASSIGN, + TASK_FINISH, + TASK_CANCEL, + TASK_DELEGATE, + TASK_SAVE_DATA } diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java b/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java index 5705da6ba1..ee8a6fc235 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/LoggedUser.java @@ -47,10 +47,6 @@ public void parseProcessRoles(Set processRoles) { processRoles.forEach(role -> this.processRoles.add(role.getStringId())); } - public boolean isAdmin() { - return getAuthorities().contains(new Authority(Authority.defaultAdminAuthority)); - } - public String getEmail() { return getUsername(); } @@ -109,4 +105,8 @@ public Author transformToAuthor() { return author; } + + public boolean hasAuthority(String authorityName) { + return this.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals(authorityName)); + } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java index 9c629853ce..972e68b135 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java @@ -17,7 +17,8 @@ public AbstractBaseAuthorizationService(IUserService userService, IAuthorityServ @Override public final boolean hasAuthority(String authorizingObject) { - - return this.userService.getLoggedUser().getAuthorities().stream().anyMatch(a -> a.equals(authorizingObject)); + if (authorizingObject == null || authorizingObject.length() == 0) + return true; + return this.userService.getLoggedUser().getAuthorities().stream().anyMatch(a -> a.getAuthority().equals(authorizingObject)); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java index 36b8b78958..0d8419b2c6 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java @@ -1,8 +1,6 @@ package com.netgrif.application.engine.auth.service.interfaces; -import com.netgrif.application.engine.auth.domain.Author; import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.AuthorizingObject; import java.util.List; import java.util.Optional; diff --git a/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java b/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java index 25b3fd2029..0c7cb5cce6 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java @@ -1,5 +1,7 @@ package com.netgrif.application.engine.auth.web; +import com.netgrif.application.engine.auth.domain.Authorizations; +import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.domain.RegisteredUser; import com.netgrif.application.engine.auth.service.InvalidUserTokenException; @@ -90,12 +92,15 @@ public MessageResource signup(@RequestBody RegistrationRequest regRequest) { } } + @Authorizations(value = { + @Authorize(authority = "USER_CREATE") + }) @ApiOperation(value = "Send invitation to a new user", authorizations = @Authorization("BasicAuth")) @PostMapping(value = "/invite", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public MessageResource invite(@RequestBody NewUserRequest newUserRequest, Authentication auth) { try { - if (!serverAuthProperties.isOpenRegistration() && (auth == null || !((LoggedUser) auth.getPrincipal()).isAdmin())) { - return MessageResource.errorMessage("Only admin can invite new users!"); + if (!serverAuthProperties.isOpenRegistration()) { + return MessageResource.errorMessage("Registration is disabled."); } newUserRequest.email = URLDecoder.decode(newUserRequest.email, StandardCharsets.UTF_8.name()); diff --git a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java index 393d8b969b..cbb00a9268 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java @@ -122,7 +122,7 @@ public PagedModel search(@RequestParam(value = "small", required = public UserResource getUser(@PathVariable("id") String userId, @RequestParam(value = "small", required = false) Boolean small, Locale locale) { small = small != null && small; LoggedUser loggedUser = (LoggedUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - if (!loggedUser.isAdmin() && !Objects.equals(loggedUser.getId(), userId)) { + if (!loggedUser.hasAuthority("USER_VIEW_ALL") && !Objects.equals(loggedUser.getId(), userId)) { log.info("User " + loggedUser.getUsername() + " trying to get another user with ID " + userId); throw new IllegalArgumentException("Could not find user with id [" + userId + "]"); } @@ -147,7 +147,7 @@ public UserResource updateUser(@PathVariable("id") String userId, @RequestBody U LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); IUser user = userService.resolveById(userId, false); - if (user == null || (!loggedUser.isAdmin() && !Objects.equals(loggedUser.getId(), userId))) + if (user == null || (!loggedUser.hasAuthority("USER_EDIT_ALL") && !Objects.equals(loggedUser.getId(), userId))) throw new UnauthorisedRequestException("User " + loggedUser.getUsername() + " doesn't have permission to modify profile of " + user.transformToLoggedUser().getUsername()); user = userService.update(user, updates); diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java deleted file mode 100644 index 45657c9dd1..0000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetAuthorizationService.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.netgrif.application.engine.petrinet.service; - -import com.netgrif.application.engine.auth.domain.LoggedUser; -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetAuthorizationService; -import org.springframework.stereotype.Service; - -@Service -public class PetriNetAuthorizationService implements IPetriNetAuthorizationService { - - @Override - public boolean canCallImport(LoggedUser loggedUser) { - return loggedUser.isAdmin(); - } - - @Override - public boolean canCallProcessDelete(LoggedUser loggedUser, String processId) { - return loggedUser.isAdmin(); - } -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index 18228cf4d1..52c339110e 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -377,7 +377,7 @@ public Page search(Map criteria, LoggedUser u Query query = new Query(); Query query_total = new Query(); - if (!user.isAdmin()) + if (user.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("PROCESS_VIEW_ALL"))) query.addCriteria(getProcessRolesCriteria(user)); criteria.forEach((key, value) -> { diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetAuthorizationService.java b/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetAuthorizationService.java deleted file mode 100644 index df1ab5a67b..0000000000 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/interfaces/IPetriNetAuthorizationService.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.netgrif.application.engine.petrinet.service.interfaces; - -import com.netgrif.application.engine.auth.domain.LoggedUser; - -public interface IPetriNetAuthorizationService { - - boolean canCallImport(LoggedUser loggedUser); - - boolean canCallProcessDelete(LoggedUser loggedUser, String processId); - -} diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index e34f42e73d..a511882e37 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -71,7 +71,7 @@ public class PetriNetController { private StringToVersionConverter converter; @Authorizations(value = { - @Authorize(expression = "@petriNetAuthorizationService.canCallImport(#auth.getPrincipal())") + @Authorize(authority = "PROCESS_UPLOAD") }) @ApiOperation(value = "Import new process", notes = "Caller must have the ADMIN role. Imports an entirely new process or a new version of an existing process.", @@ -103,6 +103,9 @@ public EntityModel importPetriNet( } } + @Authorizations(value = { + @Authorize(authority = "PROCESS_VIEW_ALL") + }) @ApiOperation(value = "Get all processes", authorizations = @Authorization("BasicAuth")) @RequestMapping(method = GET, produces = MediaTypes.HAL_JSON_VALUE) public PetriNetReferenceResources getAll(@RequestParam(value = "indentifier", required = false) String identifier, @RequestParam(value = "version", required = false) String version, Authentication auth, Locale locale) { @@ -182,7 +185,7 @@ PagedModel searchPetriNets(@RequestBody Map getTasksOfCase(@PathVariable("id") String caseId, Loc return this.taskService.findAllByCase(caseId, locale); } - @Authorize(expression = "@taskAuthorizationService.canCallAssign(@userService.getAnonymousLogged(), #taskId)") + @Authorizations(value = { + @Authorize(expression = "@taskAuthorizationService.canCallAssign(@userService.getAnonymousLogged(), #taskId)") + }) @GetMapping(value = "/assign/{id}", produces = MediaTypes.HAL_JSON_VALUE) @ApiOperation(value = "Assign task", notes = "Caller must be able to perform the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -75,7 +79,9 @@ public EntityModel assign(@PathVariable("id") String ta return super.assign(loggedUser, taskId, locale); } - @Authorize(expression = "@taskAuthorizationService.canCallFinish(@userService.getAnonymousLogged(), #taskId)") + @Authorizations(value = { + @Authorize(expression = "@taskAuthorizationService.canCallFinish(@userService.getAnonymousLogged(), #taskId)") + }) @GetMapping(value = "/finish/{id}", produces = MediaTypes.HAL_JSON_VALUE) @ApiOperation(value = "Finish task", notes = "Caller must be assigned to the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -91,7 +97,9 @@ public EntityModel finish(@PathVariable("id") String ta return super.finish(loggedUser, taskId, locale); } - @Authorize(expression = "@taskAuthorizationService.canCallCancel(@userService.getAnonymousLogged(), #taskId)") + @Authorizations(value = { + @Authorize(expression = "@taskAuthorizationService.canCallCancel(@userService.getAnonymousLogged(), #taskId)") + }) @GetMapping(value = "/cancel/{id}", produces = MediaTypes.HAL_JSON_VALUE) @ApiOperation(value = "Cancel task", notes = "Caller must be assigned to the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -113,7 +121,9 @@ public EntityModel getData(@PathVariable("id") String t return super.getData(taskId, locale); } - @Authorize(expression = "@taskAuthorizationService.canCallSaveData(@userService.getAnonymousLogged(), #taskId)") + @Authorizations(value = { + @Authorize(expression = "@taskAuthorizationService.canCallSaveData(@userService.getAnonymousLogged(), #taskId)") + }) @PostMapping(value = "/{id}/data", consumes = "application/json;charset=UTF-8", produces = "application/json;charset=UTF-8") @ApiOperation(value = "Set task data", notes = "Caller must be assigned to the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -128,7 +138,9 @@ public EntityModel setData(@PathVariable("id") String t return super.setData(taskId, dataBody); } - @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") + @Authorizations(value = { + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") + }) @ApiOperation(value = "Upload file into the task", notes = "Caller must be assigned to the task, or must be an ADMIN") @RequestMapping(value = "/{id}/file/{field}", method = RequestMethod.POST, produces = MediaTypes.HAL_JSON_VALUE) @@ -164,7 +176,6 @@ public ResponseEntity getFilePreview(@PathVariable("id") String taskId return super.getFilePreview(taskId, fieldId); } - @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") @ApiOperation(value = "Upload multiple files into the task", notes = "Caller must be assigned to the task, or must be an ADMIN") @RequestMapping(value = "/{id}/files/{field}", method = RequestMethod.POST, produces = MediaTypes.HAL_JSON_VALUE) diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java b/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java index e004de29f9..e96a2a0040 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java @@ -18,6 +18,7 @@ import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; import com.netgrif.application.engine.workflow.web.responsebodies.TaskReference; import io.swagger.annotations.*; +import org.checkerframework.checker.units.qual.A; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -84,6 +85,7 @@ public LocalisedTaskResource getOne(@PathVariable("id") String taskId, Locale lo } @Authorizations(value = { + @Authorize(authority = "TASK_ASSIGN"), @Authorize(expression = "@taskAuthorizationService.canCallAssign(#auth.getPrincipal(), #taskId)") }) @ApiOperation(value = "Assign task", @@ -100,6 +102,7 @@ public EntityModel assign(Authentication auth, @PathVar } @Authorizations(value = { + @Authorize(authority = "TASK_DELEGATE"), @Authorize(expression = "@taskAuthorizationService.canCallDelegate(#auth.getPrincipal(), #taskId)") }) @ApiOperation(value = "Delegate task", @@ -116,6 +119,7 @@ public EntityModel delegate(Authentication auth, @Path } @Authorizations(value = { + @Authorize(authority = "TASK_FINISH"), @Authorize(expression = "@taskAuthorizationService.canCallFinish(#auth.getPrincipal(), #taskId)") }) @ApiOperation(value = "Finish task", @@ -132,6 +136,7 @@ public EntityModel finish(Authentication auth, @PathVa } @Authorizations(value = { + @Authorize(authority = "TASK_CANCEL"), @Authorize(expression = "@taskAuthorizationService.canCallCancel(#auth.getPrincipal(), #taskId)") }) @ApiOperation(value = "Cancel task", @@ -191,6 +196,7 @@ public EntityModel getData(@PathVariable("id") String @Authorizations(value = { + @Authorize(authority = "TASK_SAVE_DATA"), @Authorize(expression = "@taskAuthorizationService.canCallSaveData(#auth.getPrincipal(), #taskId)") }) @ApiOperation(value = "Set task data", @@ -206,6 +212,7 @@ public EntityModel setData(Authentication auth, @PathV } @Authorizations(value = { + @Authorize(authority = "TASK_SAVE_DATA"), @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") }) @ApiOperation(value = "Upload file into the task", @@ -228,6 +235,7 @@ public ResponseEntity getFile(@PathVariable("id") String taskId, @Path } @Authorizations(value = { + @Authorize(authority = "TASK_SAVE_DATA"), @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") }) @ApiOperation(value = "Remove file from the task", @@ -243,6 +251,7 @@ public MessageResource deleteFile(Authentication auth, @PathVariable("id") Strin } @Authorizations(value = { + @Authorize(authority = "TASK_SAVE_DATA"), @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") }) @ApiOperation(value = "Upload multiple files into the task", @@ -266,6 +275,7 @@ public ResponseEntity getNamedFile(@PathVariable("id") String taskId, } @Authorizations(value = { + @Authorize(authority = "TASK_SAVE_DATA"), @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") }) @ApiOperation(value = "Remove file from tasks file list field value", diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java index f833b87d84..a1a84c631b 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java @@ -75,6 +75,7 @@ public class WorkflowController { @Authorizations(value = { + @Authorize(authority = "CASE_CREATE"), @Authorize(expression = "@workflowAuthorizationService.canCallCreate(#auth.getPrincipal(), #body.netId)") }) @ApiOperation(value = "Create new case", authorizations = @Authorization("BasicAuth")) @@ -91,6 +92,9 @@ public EntityModel createCase(@RequestBody CreateCaseBo } } + @Authorizations(value = { + @Authorize(authority = "CASE_VIEW_ALL") + }) @ApiOperation(value = "Get all cases of the system", authorizations = @Authorization("BasicAuth")) @GetMapping(value = "/all", produces = MediaTypes.HAL_JSON_VALUE) public PagedModel getAll(Pageable pageable, PagedResourcesAssembler assembler) { @@ -207,6 +211,7 @@ public DataFieldsResource getAllCaseData(@PathVariable("id") String caseId, Loca } @Authorizations(value = { + @Authorize(authority = "CASE_DELETE"), @Authorize(expression = "@workflowAuthorizationService.canCallDelete(#auth.getPrincipal(), #caseId)") }) @ApiOperation(value = "Delete case", authorizations = @Authorization("BasicAuth")) From 534dbdf87380c5c550b01a6d6ac908f64070b02c Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Wed, 18 May 2022 07:06:43 +0200 Subject: [PATCH 35/68] [NAE-1617] Refactor authority - implemented test for authority - corrected tests --- .../engine/startup/AuthorityRunner.groovy | 4 + .../engine/startup/ImportHelper.groovy | 9 +- .../engine/auth/domain/AuthorizingObject.java | 10 +- .../AbstractBaseAuthorizationService.java | 2 +- .../auth/service/AbstractUserService.java | 2 +- .../engine/auth/service/UserService.java | 2 +- .../engine/auth/web/AuthorityController.java | 10 +- .../engine/auth/web/UserController.java | 6 +- .../petrinet/web/PetriNetController.java | 2 +- .../service/FilterAuthorizationService.java | 5 +- .../engine/workflow/web/FilterController.java | 4 +- .../engine/action/AssignActionTest.groovy | 3 +- .../engine/auth/AuthorityTest.groovy | 118 ++++++++++++++++++ .../FilterAuthorizationServiceTest.groovy | 3 +- .../web/PetriNetControllerTest.groovy | 5 +- 15 files changed, 166 insertions(+), 19 deletions(-) create mode 100644 src/test/groovy/com/netgrif/application/engine/auth/AuthorityTest.groovy diff --git a/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy index d6101c55fd..00d14ebdb9 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy @@ -19,6 +19,10 @@ class AuthorityRunner extends AbstractOrderedCommandLineRunner { @Override void run(String... strings) throws Exception { + createAll() + } + + void createAll() { AuthorizingObject.values().toList().forEach(authority -> service.getOrCreate(authority.name())) additionalAuthorities.toList().forEach(authority -> service.getOrCreate(authority)) log.info("Authorities created.") diff --git a/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy b/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy index dabcab6de3..9b0b6d5d73 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/ImportHelper.groovy @@ -91,13 +91,12 @@ class ImportHelper { @SuppressWarnings("GroovyAssignabilityCheck") - Map> createAuthorities(Map> authorities) { + Map> createAuthorities(Map> authorities) { HashMap> authoritities = new HashMap<>() authorities.each { authority -> - authoritities.put(authority.key, new ArrayList()) - authority.value.forEach( a -> - authoritities.get(authority.key).add(authorityService.getOrCreate(a)) - ) + if (!authoritities.containsKey(authority.key)) + authoritities.put(authority.key, new ArrayList()) + authoritities.get(authority.key).addAll(authorityService.getOrCreate(authority.value)) } log.info("Creating ${authoritities.size()} authorities") diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java index 3e7b1beb2d..94d0cd2a40 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java @@ -1,5 +1,9 @@ package com.netgrif.application.engine.auth.domain; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + /** * The enum of all possible authorizing objects, that are used for creating authority objects. Authorizing object is a * term that defines the goal of the authority, e.g. what kind of system process is protected via an authority created @@ -42,5 +46,9 @@ public enum AuthorizingObject { TASK_FINISH, TASK_CANCEL, TASK_DELEGATE, - TASK_SAVE_DATA + TASK_SAVE_DATA; + + public static List stringValues() { + return Arrays.stream(AuthorizingObject.values()).map(Enum::name).collect(Collectors.toList()); + } } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java index 972e68b135..9e31c9fb7e 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java @@ -19,6 +19,6 @@ public AbstractBaseAuthorizationService(IUserService userService, IAuthorityServ public final boolean hasAuthority(String authorizingObject) { if (authorizingObject == null || authorizingObject.length() == 0) return true; - return this.userService.getLoggedUser().getAuthorities().stream().anyMatch(a -> a.getAuthority().equals(authorizingObject)); + return this.userService.getLoggedUser().getAuthorities().stream().anyMatch(a -> a.getName().equals(authorizingObject)); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java index da4b050045..0827243f01 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java @@ -48,7 +48,7 @@ public void addDefaultRole(IUser user) { public void addDefaultAuthorities(IUser user) { if (user.getAuthorities().isEmpty()) { HashSet authorities = new HashSet<>(); - Authority.defaultUserAuthorities.forEach(a -> authorities.add(authorityService.getOrCreate(a))); + Authority.defaultUserAuthorities.forEach(a -> authorities.addAll(authorityService.findByScope(a))); user.setAuthorities(authorities); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java index 5228737cbe..19d6586eb7 100755 --- a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java @@ -130,7 +130,7 @@ public void addAnonymousRole(User user) { public void addDefaultAuthorities(User user) { if (user.getAuthorities().isEmpty()) { HashSet authorities = new HashSet<>(); - Authority.defaultUserAuthorities.forEach(a -> authorities.add(authorityService.findByName(a))); + Authority.defaultUserAuthorities.forEach(a -> authorities.addAll(authorityService.findByScope(a))); user.setAuthorities(authorities); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java index 14d64ac961..0810351926 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java @@ -1,6 +1,8 @@ package com.netgrif.application.engine.auth.web; import com.netgrif.application.engine.auth.domain.Authority; +import com.netgrif.application.engine.auth.domain.Authorizations; +import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.auth.web.requestbodies.NewAuthorityRequest; import com.netgrif.application.engine.auth.web.responsebodies.AuthorityResource; @@ -32,13 +34,19 @@ public class AuthorityController { @Autowired private IAuthorityService authorityService; + @Authorizations(value = { + @Authorize(authority = "AUTHORITY_DELETE") + }) @ApiOperation(value = "Delete authority", authorizations = @Authorization("BasicAuth")) - @PostMapping(value = "/delete/{name}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) + @DeleteMapping(value = "/delete/{name}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public EntityModel delete(@PathVariable String name, Authentication auth, Locale locale) { Authority deletedAuthority = authorityService.delete(name); return AuthorityResource.of(deletedAuthority); } + @Authorizations(value = { + @Authorize(authority = "AUTHORITY_CREATE") + }) @ApiOperation(value = "Delete authority", authorizations = @Authorization("BasicAuth")) @PostMapping(value = "/create", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public EntityModel create(@RequestBody NewAuthorityRequest request, Authentication auth, Locale locale) { diff --git a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java index cbb00a9268..8b6eb37fc8 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java @@ -173,7 +173,7 @@ public PagedModel getAllWithRole(@RequestBody Set roleIds, } @Authorizations(value = { - @Authorize(authority = "USER_EDIT", expression = "@userService.isLogged(#id)") + @Authorize(authority = "USER_EDIT_ALL", expression = "@userService.isLogged(#userId)") }) @ApiOperation(value = "Assign role to the user", notes = "Caller must have the ADMIN role", @@ -210,7 +210,7 @@ public AuthoritiesResources getAllAuthorities(Authentication auth) { } @Authorizations(value = { - @Authorize(authority = "USER_EDIT") + @Authorize(authority = "USER_EDIT_ALL") }) @ApiOperation(value = "Assign authority to the user", notes = "Caller must have the ADMIN role", @@ -226,7 +226,7 @@ public MessageResource assignAuthorityToUser(@PathVariable("id") String userId, } @Authorizations(value = { - @Authorize(authority = "USER_EDIT") + @Authorize(authority = "USER_EDIT_ALL") }) @ApiOperation(value = "Assign authority to the user", notes = "Caller must have the USER_EDIT authority", diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index a511882e37..b7231dd998 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -185,7 +185,7 @@ PagedModel searchPetriNets(@RequestBody Map a.getAuthority().equals("FILTER_DELETE_ALL")) || user.getId().equals(filter.getAuthor().getId()); } } diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/FilterController.java b/src/main/java/com/netgrif/application/engine/workflow/web/FilterController.java index b8c92816d5..febfba85be 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/FilterController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/FilterController.java @@ -6,6 +6,7 @@ import com.netgrif.application.engine.auth.domain.throwable.UnauthorisedRequestException; import com.netgrif.application.engine.workflow.domain.Filter; import com.netgrif.application.engine.workflow.domain.MergeFilterOperation; +import com.netgrif.application.engine.workflow.service.interfaces.IFilterAuthorizationService; import com.netgrif.application.engine.workflow.service.interfaces.IFilterService; import com.netgrif.application.engine.workflow.web.requestbodies.CreateFilterBody; import com.netgrif.application.engine.workflow.web.responsebodies.FilterResourceAssembler; @@ -57,7 +58,8 @@ public MessageResource createFilter(@RequestBody CreateFilterBody newFilter, @Re } @Authorizations(value = { - @Authorize(authority = "FILTER_DELETE") + @Authorize(authority = "FILTER_DELETE_ALL"), + @Authorize(authority = "FILTER_DELETE_MY") }) @ApiOperation(value = "Delete filter specified by id", authorizations = @Authorization("BasicAuth")) @RequestMapping(value = "/{id}", method = RequestMethod.DELETE, produces = MediaTypes.HAL_JSON_VALUE) diff --git a/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy index 8d4f4166b0..082fa04c74 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy @@ -94,7 +94,8 @@ class AssignActionTest { createMainAndSecondaryNet() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) + def auths = importHelper.createAuthorities(["user": [AuthorizingObject.FILTER_UPLOAD.name(), + AuthorizingObject.FILTER_DELETE_MY.name()], "admin": AuthorizingObject.stringValues()]) def authorityList = Stream.concat(auths.get("user").stream(), auths.get("admin").stream()).collect(Collectors.toList()).toArray() importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), diff --git a/src/test/groovy/com/netgrif/application/engine/auth/AuthorityTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/AuthorityTest.groovy new file mode 100644 index 0000000000..9e12d3f01d --- /dev/null +++ b/src/test/groovy/com/netgrif/application/engine/auth/AuthorityTest.groovy @@ -0,0 +1,118 @@ +package com.netgrif.application.engine.auth + +import com.netgrif.application.engine.TestHelper +import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorizingObject +import com.netgrif.application.engine.auth.domain.User +import com.netgrif.application.engine.auth.domain.UserState +import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService +import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole +import com.netgrif.application.engine.startup.ImportHelper +import groovy.json.JsonOutput +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.hateoas.MediaTypes +import org.springframework.http.MediaType +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken +import org.springframework.security.core.Authentication +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors +import org.springframework.test.context.ActiveProfiles +import org.springframework.test.context.junit.jupiter.SpringExtension +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders +import org.springframework.test.web.servlet.result.MockMvcResultMatchers +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import org.springframework.web.context.WebApplicationContext + +import static org.junit.jupiter.api.Assertions.assertThrows +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity + +@ExtendWith(SpringExtension.class) +@ActiveProfiles(["test"]) +@SpringBootTest +class AuthorityTest { + + private static final String GROUP_NAME = "Test group" + public static final String USER_EMAIL = "test@mail.sk" + public static final String USER_PASSWORD = "password" + + public static final String AUTHORITY_DELETE_API = "/api/authority/delete/{name}" + public static final String AUTHORITY_CREATE_API = "/api/authority/create" + + @Autowired + private ImportHelper importHelper + + @Autowired + private WebApplicationContext wac + + @Autowired + private TestHelper testHelper + + @Autowired + private IAuthorityService authorityService + + private MockMvc mvc + private Authentication authentication + + @BeforeEach + void before() { + testHelper.truncateDbs() + mvc = MockMvcBuilders + .webAppContextSetup(wac) + .apply(springSecurity()) + .build() + + def auths = importHelper.createAuthorities(["user": [AuthorizingObject.AUTHORITY_CREATE.name(), + AuthorizingObject.AUTHORITY_DELETE.name()]]) + def authorityList = auths.get("user").toArray() + + importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), + authorityList as Authority[], [] as ProcessRole[]) + } + + @Test + void testCreateAuthority() { + authentication = new UsernamePasswordAuthenticationToken(USER_EMAIL, USER_PASSWORD) + + def content = JsonOutput.toJson(["name": "TEST_AUTHORITY"]) + + mvc.perform(MockMvcRequestBuilders.post(AUTHORITY_CREATE_API) + .accept(MediaTypes.HAL_JSON_VALUE) + .content(content) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .with(SecurityMockMvcRequestPostProcessors.csrf().asHeader()) + .with(SecurityMockMvcRequestPostProcessors.authentication(authentication))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn() + + def newAuthority = authorityService.findByName("TEST_AUTHORITY") + + assert newAuthority != null + } + + @Test + void testDeleteAuthority() { + Authority a = authorityService.getOrCreate("TEST_AUTHORITY") + + assert a != null + + authentication = new UsernamePasswordAuthenticationToken(USER_EMAIL, USER_PASSWORD) + + mvc.perform(MockMvcRequestBuilders.delete(AUTHORITY_DELETE_API.replace("{name}", "TEST_AUTHORITY")) + .accept(MediaTypes.HAL_JSON_VALUE) + .contentType(MediaType.APPLICATION_JSON_VALUE) + .with(SecurityMockMvcRequestPostProcessors.csrf().asHeader()) + .with(SecurityMockMvcRequestPostProcessors.authentication(authentication))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn() + + Exception exception = assertThrows(IllegalArgumentException.class, () -> { + authorityService.findByName("TEST_AUTHORITY") + }) + + assert exception.getMessage() == "Could not find authority with name [TEST_AUTHORITY]" + } +} diff --git a/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy index d24d6d8cb5..0915f61ab1 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy @@ -68,7 +68,8 @@ class FilterAuthorizationServiceTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) + def auths = importHelper.createAuthorities(["user": [AuthorizingObject.FILTER_UPLOAD.name(), + AuthorizingObject.FILTER_DELETE_MY.name()], "admin": AuthorizingObject.stringValues()]) importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy index 154cf7944f..f246731077 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy @@ -11,6 +11,7 @@ import com.netgrif.application.engine.petrinet.domain.PetriNet import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService +import com.netgrif.application.engine.startup.AuthorityRunner import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator import org.junit.Before @@ -85,7 +86,9 @@ class PetriNetControllerTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) + + def auths = importHelper.createAuthorities(["user": [AuthorizingObject.FILTER_UPLOAD.name(), + AuthorizingObject.FILTER_DELETE_MY.name()], "admin": AuthorizingObject.stringValues()]) importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], From 8c6fa3fc9de507f805b397ca1c249b578e455c36 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Wed, 18 May 2022 07:12:53 +0200 Subject: [PATCH 36/68] [NAE-1617] Refactor authority - corrected AuthorityService --- .../engine/auth/service/AuthorityService.java | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index 566982bebd..db7fe1266f 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -7,6 +7,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -26,6 +27,9 @@ public List findAll() { @Override @Transactional public Authority getOrCreate(String name) { + if (isScope(name)) { + throw new IllegalArgumentException("The authority name is not valid. Scope is suitable for this function."); + } Authority authority = repository.findByName(name); if (authority == null) authority = repository.save(new Authority(name)); @@ -41,11 +45,22 @@ public Authority save(Authority authority) { public List getOrCreate(List authorities) { if (authorities == null) return Collections.emptyList(); - return authorities.stream().map(this::getOrCreate).collect(Collectors.toList()); + List result = new ArrayList<>(); + authorities.forEach(a -> { + if (isScope(a)) { + result.addAll(findByScope(a)); + } else { + result.add(getOrCreate(a)); + } + }); + return result; } @Override public Authority delete(String name) { + if (isScope(name)) { + throw new IllegalArgumentException("The authority name is not valid. Scope is suitable for this function."); + } Authority authority = repository.findByName(name); if (authority == null) throw new IllegalArgumentException("Could not find authority with name [" + name + "]"); @@ -67,6 +82,9 @@ public List findByScope(String scope) { @Override public Authority findByName(String name) { + if (isScope(name)) { + throw new IllegalArgumentException("The authority name is not valid. Scope is suitable for this function."); + } Authority authority = repository.findByName(name); if (authority == null) throw new IllegalArgumentException("Could not find authority with name [" + name + "]"); @@ -84,4 +102,13 @@ public Authority getOne(String id) { throw new IllegalArgumentException("Could not find authority with id [" + id + "]"); return authority.get(); } + + private boolean isScope(String authorityName) { + if (authorityName.endsWith("*")) + return true; + else if (authorityName.contains("*")) + throw new IllegalArgumentException("The authority name or scope is not valid."); + else + return false; + } } \ No newline at end of file From 0240935638b69198d85ac8e098e3522192b38881 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Wed, 18 May 2022 08:55:45 +0200 Subject: [PATCH 37/68] [NAE-1617] Refactor authority - corrected findById in AuthorityService - implemented tests for authority controller --- .../engine/startup/AuthorityRunner.groovy | 6 +- .../repositories/AuthorityRepository.java | 3 + .../engine/auth/service/AuthorityService.java | 7 +- .../engine/auth/web/UserController.java | 3 + src/main/resources/application.properties | 2 +- .../engine/auth/AuthorityTest.groovy | 68 +++++++++++++++++-- 6 files changed, 78 insertions(+), 11 deletions(-) diff --git a/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy b/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy index 00d14ebdb9..b3515f5945 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/AuthorityRunner.groovy @@ -11,8 +11,8 @@ import org.springframework.stereotype.Component @Component class AuthorityRunner extends AbstractOrderedCommandLineRunner { - @Value('${nae.authority.additional:}') - private String[] additionalAuthorities + @Value('${nae.authority.authorizing-objects:}') + private String[] additionalAuthorizingObjects @Autowired private IAuthorityService service @@ -24,7 +24,7 @@ class AuthorityRunner extends AbstractOrderedCommandLineRunner { void createAll() { AuthorizingObject.values().toList().forEach(authority -> service.getOrCreate(authority.name())) - additionalAuthorities.toList().forEach(authority -> service.getOrCreate(authority)) + additionalAuthorizingObjects.toList().forEach(authority -> service.getOrCreate(authority)) log.info("Authorities created.") } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/repositories/AuthorityRepository.java b/src/main/java/com/netgrif/application/engine/auth/domain/repositories/AuthorityRepository.java index c93622a2c4..9d13105e7b 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/repositories/AuthorityRepository.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/repositories/AuthorityRepository.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.auth.domain.repositories; import com.netgrif.application.engine.auth.domain.Authority; +import org.bson.types.ObjectId; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.querydsl.QuerydslPredicateExecutor; import org.springframework.stereotype.Repository; @@ -12,5 +13,7 @@ public interface AuthorityRepository extends MongoRepository, Authority findByName(String name); + Authority findBy_id(ObjectId id); + List findAllByNameStartsWith(String prefix); } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index db7fe1266f..52553febf1 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -3,6 +3,7 @@ import com.netgrif.application.engine.auth.domain.Authority; import com.netgrif.application.engine.auth.domain.repositories.AuthorityRepository; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; +import org.bson.types.ObjectId; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -11,7 +12,6 @@ import java.util.Collections; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; @Service public class AuthorityService implements IAuthorityService { @@ -42,6 +42,7 @@ public Authority save(Authority authority) { } @Override + @Transactional public List getOrCreate(List authorities) { if (authorities == null) return Collections.emptyList(); @@ -75,7 +76,7 @@ public List findByScope(String scope) { authorities = repository.findAll(); else { String prefix = scope.replace("*", ""); - authorities = repository.findAll().stream().filter(authority -> authority.getName().startsWith(prefix)).collect(Collectors.toList()); + authorities = repository.findAllByNameStartsWith(prefix); } return authorities; } @@ -93,7 +94,7 @@ public Authority findByName(String name) { @Override public Optional findById(String id) { - return repository.findById(id); + return Optional.of(repository.findBy_id(new ObjectId(id))); } public Authority getOne(String id) { diff --git a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java index 8b6eb37fc8..dc1cf3ba97 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java @@ -87,6 +87,9 @@ protected UserResourceAssembler getUserResourceAssembler(Locale locale, boolean return result; } + @Authorizations(value = { + @Authorize(authority = "USER_VIEW_ALL") + }) @ApiOperation(value = "Get all users", authorizations = @Authorization("BasicAuth")) @GetMapping(produces = MediaTypes.HAL_JSON_VALUE) public PagedModel getAll(@RequestParam(value = "small", required = false) Boolean small, Pageable pageable, PagedResourcesAssembler assembler, Authentication auth, Locale locale) { diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 8cd1101360..16a8c59fe6 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -162,4 +162,4 @@ nae.filter.export.file-name=filters.xml #server.port=8080 # Authorities -nae.authority.additional=SCOPE_AUTHORITY_EXAMPLE \ No newline at end of file +nae.authority.authorizing-objects=EXAMPLE_AUTHORITY_1,EXAMPLE_AUTHORITY_2 \ No newline at end of file diff --git a/src/test/groovy/com/netgrif/application/engine/auth/AuthorityTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/AuthorityTest.groovy index 9e12d3f01d..b0ef284444 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/AuthorityTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/auth/AuthorityTest.groovy @@ -3,9 +3,11 @@ package com.netgrif.application.engine.auth import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority import com.netgrif.application.engine.auth.domain.AuthorizingObject +import com.netgrif.application.engine.auth.domain.IUser import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService +import com.netgrif.application.engine.auth.service.interfaces.IUserService import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole import com.netgrif.application.engine.startup.ImportHelper import groovy.json.JsonOutput @@ -39,12 +41,20 @@ class AuthorityTest { public static final String USER_EMAIL = "test@mail.sk" public static final String USER_PASSWORD = "password" + public static final String ADMIN_EMAIL = "admin@mail.sk" + public static final String ADMIN_PASSWORD = "password" + public static final String AUTHORITY_DELETE_API = "/api/authority/delete/{name}" public static final String AUTHORITY_CREATE_API = "/api/authority/create" + public static final String AUTHORITY_ASSIGN_API = "/api/user/{id}/authority/assign" + public static final String AUTHORITY_REMOVE_API = "/api/user/{id}/authority/remove" @Autowired private ImportHelper importHelper + @Autowired + private IUserService userService + @Autowired private WebApplicationContext wac @@ -65,12 +75,16 @@ class AuthorityTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["user": [AuthorizingObject.AUTHORITY_CREATE.name(), - AuthorizingObject.AUTHORITY_DELETE.name()]]) - def authorityList = auths.get("user").toArray() + def auths = importHelper.createAuthorities(["user": ["AUTHORITY_CREATE", "AUTHORITY_DELETE", "TEST_AUTHORITY"], + "admin": AuthorizingObject.stringValues()]) + def userAuths = auths.get("user").toArray() + def adminAuths = auths.get("admin").toArray() importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), - authorityList as Authority[], [] as ProcessRole[]) + userAuths as Authority[], [] as ProcessRole[]) + + importHelper.createUser(new User(name: "Test", surname: "Integration", email: ADMIN_EMAIL, password: ADMIN_PASSWORD, state: UserState.ACTIVE), + adminAuths as Authority[], [] as ProcessRole[]) } @Test @@ -115,4 +129,50 @@ class AuthorityTest { assert exception.getMessage() == "Could not find authority with name [TEST_AUTHORITY]" } + + @Test + void testAssignAuthorityToUser() { + authentication = new UsernamePasswordAuthenticationToken(ADMIN_EMAIL, ADMIN_PASSWORD) + + IUser user = userService.findByEmail(USER_EMAIL, false) + Authority testAuthority = authorityService.getOrCreate("CREATED_AUTHORITY") + + assert user.getAuthorities().size() == 3 + + def content = testAuthority.stringId + mvc.perform(MockMvcRequestBuilders.post(AUTHORITY_ASSIGN_API.replace("{id}", user.stringId)) + .accept(MediaTypes.HAL_JSON_VALUE) + .content(content) + .contentType(MediaType.TEXT_PLAIN_VALUE) + .with(SecurityMockMvcRequestPostProcessors.csrf().asHeader()) + .with(SecurityMockMvcRequestPostProcessors.authentication(authentication))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn() + + user = userService.findByEmail(USER_EMAIL, false) + assert user.getAuthorities().size() == 4 + } + + @Test + void testRemoveAuthorityFromUser() { + authentication = new UsernamePasswordAuthenticationToken(ADMIN_EMAIL, ADMIN_PASSWORD) + + IUser user = userService.findByEmail(USER_EMAIL, false) + Authority testAuthority = authorityService.getOrCreate("TEST_AUTHORITY") + + assert user.getAuthorities().size() == 3 + + def content = testAuthority.stringId + mvc.perform(MockMvcRequestBuilders.delete(AUTHORITY_REMOVE_API.replace("{id}", user.stringId)) + .accept(MediaTypes.HAL_JSON_VALUE) + .content(content) + .contentType(MediaType.TEXT_PLAIN_VALUE) + .with(SecurityMockMvcRequestPostProcessors.csrf().asHeader()) + .with(SecurityMockMvcRequestPostProcessors.authentication(authentication))) + .andExpect(MockMvcResultMatchers.status().isOk()) + .andReturn() + + user = userService.findByEmail(USER_EMAIL, false) + assert user.getAuthorities().size() == 2 + } } From dc062f7d0b86fb2c4b92d8f091672eccdb66088f Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Wed, 18 May 2022 09:37:21 +0200 Subject: [PATCH 38/68] [NAE-1617] Refactor authority - finished documentation --- docs/authorization/authority.md | 117 +++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 2 deletions(-) diff --git a/docs/authorization/authority.md b/docs/authorization/authority.md index fb47c9f9dd..4e00010925 100644 --- a/docs/authorization/authority.md +++ b/docs/authorization/authority.md @@ -8,7 +8,120 @@ resources. Authorizing objects are Java enum values, that represent authorities, that are needed to access a resource or use an action. E.g. to be able to import new process (Petri Net) into the application, the user must have authority -created from ``AuthorizingObject.PROCESS_UPLOAD`` authorizing object. +created from `AuthorizingObject.PROCESS_UPLOAD` authorizing object. These authorizing objects are predefined, and they are used to create the -``Authority`` objects/entities at application startup. \ No newline at end of file +`Authority` objects/entities at application startup. There followings are predefined: + +- `PROCESS_UPLOAD`- to import new process +- `PROCESS_VIEW_ALL`- to retrieve all the processes imported by any user +- `PROCESS_VIEW_MY`- to retrieve only processes imported by logged user +- `PROCESS_DELETE_ALL`- to delete processes imported by any user +- `PROCESS_DELETE_MY`- to delete processes imported by logged user +- `FILTER_UPLOAD`- to upload filter +- `FILTER_DELETE_MY`- to delete filter imported by logged user +- `FILTER_DELETE_ALL`- to delete filter imported by any user +- `USER_CREATE`- to invite or create user +- `USER_DELETE`- to remove user +- `USER_EDIT_ALL`- to edit any user +- `USER_EDIT_MY`- to edit only logged user +- `USER_VIEW_ALL`- to retrieve all users +- `USER_VIEW_MY`- to retrieve only logged user +- `GROUP_CREATE`- to create group +- `GROUP_DELETE_MY`- to delete group created by logged user +- `GROUP_DELETE_ALL`- to delete group create by any user +- `GROUP_ADD_USER`- to add any user to any group +- `GROUP_REMOVE_USER`- to remove any user from any group +- `GROUP_VIEW_ALL`- to retrieve any group +- `GROUP_VIEW_MY`- to retrieve group of logged user +- `ROLE_ASSIGN_TO_USER`- to assign role to user +- `ROLE_REMOVE_FROM_USER`- to remove role from user +- `AUTHORITY_CREATE`- to create authority +- `AUTHORITY_DELETE`- to delete authority +- `AUTHORITY_VIEW_ALL`- to retrieve any authority +- `CASE_VIEW_ALL`- to view all cases +- `CASE_VIEW_MY`- to view cases of logged user +- `CASE_CREATE`- to create case +- `CASE_DELETE`- to delete case +- `CASE_DATA_GET_ALL`- to get all data of case +- `TASK_RELOAD`- to reload tasks +- `TASK_ASSIGN`- to assign task +- `TASK_FINISH`- to finish task +- `TASK_CANCEL`- to cancel task +- `TASK_DELEGATE`- to delegate task +- `TASK_SAVE_DATA`- to save data on task + +However, it is possible to add custom authorizing objects using `nae.authority.authorizing-objects` +property in `application.properties` files as following: + +``` +# Authorities +nae.authority.authorizing-objects=EXAMPLE_AUTHORITY_1,EXAMPLE_AUTHORITY_2 +``` + +## Authorization definition + +You can define authorization for any method in the Netgrif Application Engine project. +You can use the new `@Authorizations` and `@Authorize` annotations over the method definitions, +which are strongly connected to each other: the value of `@Authorizations` is an array of `@Authorize` +objects: + +``` +@Authorizations(value = { + @Authorize(authority = "PROCESS_UPLOAD", expression = "#canUpload(#userId)" +}) +void importPetriNet(File petriNet) { + ... +} +``` + +The ``@Authorize`` annotation has two fields: +- `authority` - an authority, that the authenticated user is needed to be checked for +- `expression` - an expression that returns boolean and serves as additional authorization + +## Authorization check + +The statements are evaluated in `BaseAuthorizationServiceAspect` bean that is implemented using AOP. The user will have +valid authorization if it has the required `authority` AND fulfills additional authorization defined +in `expression` (authority check returns `true` AND expression check returns `true`). + + +If there is no `authority` defined, the authorization method returns `true` for authority check. +In the following example, user must fulfill addition authorization implemented in `canUpload(String userId)` +function: +``` +@Authorizations(value = { + @Authorize(expression = "#canUpload(#userId)) +}) +void importPetriNet(File petriNet) { + ... +} +``` + +If there is no `expression` defined, the authorization method always returns`true` for expression check. +In the following example, user must have `PROCESS_UPLOAD` authority: +``` +@Authorizations(value = { + @Authorize(authority = "PROCESS_UPLOAD") +}) +void importPetriNet(File petriNet) { + ... +} +``` + + +If there are more authorizations defined inside `@Authorizations` using `@Authorize`, then OR statement is valid +between the multiple `@Authorize` statements, so user must fulfill at least one `@Authorize` statement. +In the following example, the logged user must have `PROCESS_UPLOAD` authority AND must fulfill `canUpload(String userId)` +expression, OR must fulfill `isAdmin(String userId)` expression: +``` +@Authorizations(value = { + @Authorize(authority = "PROCESS_UPLOAD", expression = "#canUpload(#userId)", + @Authorize(expression = "isAdmin(#userId)") +}) +void importPetriNet(File petriNet) { + ... +} +``` + + From aa61971d423bf8243652f3c4843a3971ab057965 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 23 May 2022 08:40:28 +0200 Subject: [PATCH 39/68] [NAE-1617] Authority refactor - implemented changes according to PR --- .../engine/auth/domain/AuthorizingObject.java | 10 ++++++--- .../orgstructure/groups/NextGroupService.java | 6 ++++++ .../groups/interfaces/INextGroupService.java | 2 ++ .../orgstructure/web/GroupController.java | 21 +++++++++++++++++++ .../workflow/web/PublicTaskController.java | 3 +++ src/main/resources/application.properties | 2 +- .../ElasticSearchViewPermissionTest.groovy | 2 -- 7 files changed, 40 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java index 94d0cd2a40..026ff9dfcb 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java @@ -19,7 +19,8 @@ public enum AuthorizingObject { FILTER_DELETE_MY, FILTER_DELETE_ALL, USER_CREATE, - USER_DELETE, + USER_DELETE_ALL, + USER_DELETE_MY, USER_EDIT_ALL, USER_EDIT_MY, USER_VIEW_ALL, @@ -27,10 +28,13 @@ public enum AuthorizingObject { GROUP_CREATE, GROUP_DELETE_MY, GROUP_DELETE_ALL, - GROUP_ADD_USER, - GROUP_REMOVE_USER, + GROUP_ALL_ADD_USER, + GROUP_MY_ADD_USER, + GROUP_ALL_REMOVE_USER, + GROUP_MY_REMOVE_USER, GROUP_VIEW_ALL, GROUP_VIEW_MY, + GROUP_MEMBEROF_VIEW, ROLE_ASSIGN_TO_USER, ROLE_REMOVE_FROM_USER, AUTHORITY_CREATE, diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/groups/NextGroupService.java b/src/main/java/com/netgrif/application/engine/orgstructure/groups/NextGroupService.java index d10ca6c579..44fba5b296 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/groups/NextGroupService.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/groups/NextGroupService.java @@ -268,6 +268,12 @@ public Set getAllGroupsOfUser(IUser groupUser) { return new HashSet<>(groupList); } + @Override + public Set getGroupCasesOfUser(IUser groupUser) { + List groupList = workflowService.searchAll(groupCase().and(QCase.case$.dataSet.get(GROUP_MEMBERS_FIELD).options.containsKey(groupUser.getStringId()))).toList(); + return new HashSet<>(groupList); + } + @Override public String getGroupOwnerId(String groupId) { return this.getGroupOwnerId(this.findGroup(groupId)); diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/groups/interfaces/INextGroupService.java b/src/main/java/com/netgrif/application/engine/orgstructure/groups/interfaces/INextGroupService.java index d730db00ad..0b500063ef 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/groups/interfaces/INextGroupService.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/groups/interfaces/INextGroupService.java @@ -44,6 +44,8 @@ public interface INextGroupService { Set getAllGroupsOfUser(IUser groupUser); + Set getGroupCasesOfUser(IUser groupUser); + String getGroupOwnerId(String groupId); Collection getGroupsOwnerIds(Collection groupIds); diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java index 648f0ecb7d..45778bef3d 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java @@ -5,6 +5,7 @@ import com.netgrif.application.engine.orgstructure.web.responsebodies.Group; import com.netgrif.application.engine.orgstructure.web.responsebodies.GroupsResource; import com.netgrif.application.engine.workflow.domain.Case; +import com.netgrif.application.engine.workflow.domain.QCase; import io.swagger.annotations.*; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -72,6 +73,26 @@ public GroupsResource getMyGroups(Authentication auth) { return new GroupsResource(groupResponse); } + @Authorizations(value = { + @Authorize(authority = "GROUP_MEMBEROF_VIEW") + }) + @ApiOperation(value = "Get logged user's groups in the system", + notes = "Caller must have the GROUP_VIEW_MY authority", + authorizations = @Authorization("BasicAuth")) + @RequestMapping(value = "/my", method = RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK", response = GroupsResource.class), + @ApiResponse(code = 403, message = "Caller doesn't fulfill the authorisation requirements"), + }) + public GroupsResource getMembershipGroups(Authentication auth) { + Set groups = service.getGroupCasesOfUser(((LoggedUser)auth.getPrincipal()).transformToUser()); + Set groupResponse = groups.stream() + .map(aCase -> new Group(aCase.getStringId(), aCase.getTitle())) + .collect(Collectors.toCollection(HashSet::new)); + return new GroupsResource(groupResponse); + } + + // @ApiOperation(value = "Get all the user's groups", authorizations = @Authorization("BasicAuth")) // @GetMapping(value = "/my", produces = MediaTypes.HAL_JSON_VALUE) // public GroupsResource getGroupsOfUser(Authentication auth) { diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java b/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java index 96bd11b37a..052064cf80 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java @@ -176,6 +176,9 @@ public ResponseEntity getFilePreview(@PathVariable("id") String taskId return super.getFilePreview(taskId, fieldId); } + @Authorizations(value = { + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") + }) @ApiOperation(value = "Upload multiple files into the task", notes = "Caller must be assigned to the task, or must be an ADMIN") @RequestMapping(value = "/{id}/files/{field}", method = RequestMethod.POST, produces = MediaTypes.HAL_JSON_VALUE) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 16a8c59fe6..51938878c3 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -162,4 +162,4 @@ nae.filter.export.file-name=filters.xml #server.port=8080 # Authorities -nae.authority.authorizing-objects=EXAMPLE_AUTHORITY_1,EXAMPLE_AUTHORITY_2 \ No newline at end of file +nae.authority.authorizing-objects= \ No newline at end of file diff --git a/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy b/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy index 9f32992026..23247c0579 100644 --- a/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy @@ -31,8 +31,6 @@ import org.springframework.data.domain.PageRequest import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension -import java.lang.reflect.Array - @ExtendWith(SpringExtension.class) @ActiveProfiles(["test"]) @SpringBootTest From 601ef6b24452f810309e1bf93e2e83c8cd00a283 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 23 May 2022 08:47:28 +0200 Subject: [PATCH 40/68] [NAE-1617] Authority refactor - implemented deleteMyPetriNet --- .../petrinet/web/PetriNetController.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index b7231dd998..3171fc21bc 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -188,7 +188,7 @@ PagedModel searchPetriNets(@RequestBody Map Date: Mon, 23 May 2022 08:56:15 +0200 Subject: [PATCH 41/68] [NAE-1617] Authority refactor - implemented endpoint for viewing my petri nets --- .../petrinet/web/PetriNetController.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index 3171fc21bc..e4c252f6c2 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -42,6 +42,7 @@ import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.*; +import java.util.stream.Collectors; import static org.springframework.web.bind.annotation.RequestMethod.GET; import static org.springframework.web.bind.annotation.RequestMethod.POST; @@ -121,6 +122,32 @@ public PetriNetReferenceResources getAll(@RequestParam(value = "indentifier", re } } + @Authorizations(value = { + @Authorize(authority = "PROCESS_VIEW_MY") + }) + @ApiOperation(value = "Get all processes", authorizations = @Authorization("BasicAuth")) + @RequestMapping(value = "/my", method = GET, produces = MediaTypes.HAL_JSON_VALUE) + public PetriNetReferenceResources getMy(@RequestParam(value = "indentifier", required = false) String identifier, @RequestParam(value = "version", required = false) String version, Authentication auth, Locale locale) { + LoggedUser user = (LoggedUser) auth.getPrincipal(); + List references; + if (identifier != null && version == null) { + references = service.getReferencesByIdentifier(identifier, user, locale).stream().filter(ref -> ref.getAuthor().getId().equals(user.getId())).collect(Collectors.toList()); + return new PetriNetReferenceResources(references); + } else if (identifier == null && version != null) { + references = service.getReferencesByVersion(converter.convert(version), user, locale).stream().filter(ref -> ref.getAuthor().getId().equals(user.getId())).collect(Collectors.toList()); + return new PetriNetReferenceResources(references); + } else if (identifier != null && version != null) { + PetriNetReference reference = service.getReference(identifier, converter.convert(version), user, locale); + if (reference.getAuthor().getId().equals(user.getId())) + return new PetriNetReferenceResources(Collections.singletonList(reference)); + else + return new PetriNetReferenceResources(new ArrayList()); + } else { + references = service.getReferences(user, locale).stream().filter(ref -> ref.getAuthor().getId().equals(user.getId())).collect(Collectors.toList()); + return new PetriNetReferenceResources(references); + } + } + @ApiOperation(value = "Get process by id", authorizations = @Authorization("BasicAuth")) @RequestMapping(value = "/{id}", method = GET, produces = MediaTypes.HAL_JSON_VALUE) public PetriNetReferenceResource getOne(@PathVariable("id") String id, Authentication auth, Locale locale) { From 5575b9b32cf8dbcd593d5f8a2d92d10dfc7fc624 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Fri, 27 May 2022 12:57:43 +0200 Subject: [PATCH 42/68] [NAE-1567] Plugin management - corrected according to tests. --- .../application/engine/orgstructure/web/GroupController.java | 2 +- .../application/engine/petrinet/web/PetriNetController.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java index 45778bef3d..9168708aec 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java @@ -79,7 +79,7 @@ public GroupsResource getMyGroups(Authentication auth) { @ApiOperation(value = "Get logged user's groups in the system", notes = "Caller must have the GROUP_VIEW_MY authority", authorizations = @Authorization("BasicAuth")) - @RequestMapping(value = "/my", method = RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE) + @RequestMapping(value = "/membership", method = RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE) @ApiResponses(value = { @ApiResponse(code = 200, message = "OK", response = GroupsResource.class), @ApiResponse(code = 403, message = "Caller doesn't fulfill the authorisation requirements"), diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index e4c252f6c2..176ea1e8be 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -243,7 +243,7 @@ public MessageResource deletePetriNet(@PathVariable("id") String processId, Auth @ApiResponse(code = 200, message = "OK", response = MessageResource.class), @ApiResponse(code = 403, message = "Caller doesn't fulfill the authorisation requirements") }) - @RequestMapping(value = "/{id}", method = RequestMethod.DELETE, produces = MediaTypes.HAL_JSON_VALUE) + @RequestMapping(value = "/my/{id}", method = RequestMethod.DELETE, produces = MediaTypes.HAL_JSON_VALUE) public MessageResource deleteMyPetriNet(@PathVariable("id") String processId, Authentication auth) { String decodedProcessId = decodeUrl(processId); if (Objects.equals(decodedProcessId, "")) { From c9fdc43f3dde96da444ecd532f7efab452c29460 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 30 May 2022 09:27:34 +0200 Subject: [PATCH 43/68] [NAE-1617] Authority refactor - implemented additional tests. --- .../engine/auth/domain/AuthorizingObject.java | 2 +- .../orgstructure/web/GroupController.java | 2 +- .../groups/GroupControllerTest.groovy | 88 +++++++++++++++++++ .../web/PetriNetControllerTest.groovy | 53 +++++++---- 4 files changed, 127 insertions(+), 18 deletions(-) create mode 100644 src/test/groovy/com/netgrif/application/engine/orgstructure/groups/GroupControllerTest.groovy diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java index 026ff9dfcb..e3693ac933 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java @@ -34,7 +34,7 @@ public enum AuthorizingObject { GROUP_MY_REMOVE_USER, GROUP_VIEW_ALL, GROUP_VIEW_MY, - GROUP_MEMBEROF_VIEW, + GROUP_MEMBERSHIP_MY, ROLE_ASSIGN_TO_USER, ROLE_REMOVE_FROM_USER, AUTHORITY_CREATE, diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java index 9168708aec..10bc66ca49 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java @@ -74,7 +74,7 @@ public GroupsResource getMyGroups(Authentication auth) { } @Authorizations(value = { - @Authorize(authority = "GROUP_MEMBEROF_VIEW") + @Authorize(authority = "GROUP_MEMBERSHIP_MY") }) @ApiOperation(value = "Get logged user's groups in the system", notes = "Caller must have the GROUP_VIEW_MY authority", diff --git a/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/GroupControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/GroupControllerTest.groovy new file mode 100644 index 0000000000..c556f5de60 --- /dev/null +++ b/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/GroupControllerTest.groovy @@ -0,0 +1,88 @@ +package com.netgrif.application.engine.orgstructure.groups + +import com.netgrif.application.engine.TestHelper +import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorizingObject +import com.netgrif.application.engine.auth.domain.User +import com.netgrif.application.engine.auth.domain.UserState +import com.netgrif.application.engine.auth.service.interfaces.IUserService +import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole +import com.netgrif.application.engine.startup.ImportHelper +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken +import org.springframework.security.core.Authentication +import org.springframework.test.context.ActiveProfiles +import org.springframework.test.context.junit.jupiter.SpringExtension +import org.springframework.test.web.servlet.MockMvc +import org.springframework.test.web.servlet.setup.MockMvcBuilders +import org.springframework.web.context.WebApplicationContext + +import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication +import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status + +@ExtendWith(SpringExtension.class) +@ActiveProfiles(["test"]) +@SpringBootTest +class GroupControllerTest { + + private MockMvc mvc + + @Autowired + private WebApplicationContext wac + + @Autowired + private TestHelper testHelper + + @Autowired + private ImportHelper importHelper + + @Autowired + private IUserService userService + + Authentication userAuth + + private static final String USER_EMAIL = "test@nae.com" + + private static final String GROUP_VIEW_MY_URL = "/api/group/my" + private static final String MEMBERSHIPS_MY_URL = "/api/group/membership" + + + @BeforeEach + void init() { + testHelper.truncateDbs() + + mvc = MockMvcBuilders + .webAppContextSetup(wac) + .apply(springSecurity()) + .build() + + def auths = importHelper.createAuthorities(["user": [ + AuthorizingObject.GROUP_VIEW_MY.name(), + AuthorizingObject.GROUP_MEMBERSHIP_MY.name() + ]]) + + importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), + auths.get("user").toArray() as Authority[], [] as ProcessRole[]) + userAuth = new UsernamePasswordAuthenticationToken(userService.findByEmail(USER_EMAIL, false).transformToLoggedUser(), "password", auths.get("user")) + } + + @Test + void testViewMyGroups() { + mvc.perform(get(GROUP_VIEW_MY_URL) + .with(authentication(this.userAuth))) + .andExpect(status().isOk()) + } + + @Test + void testMyMemberships() { + mvc.perform(get(MEMBERSHIPS_MY_URL) + .with(authentication(this.userAuth))) + .andExpect(status().isOk()) + } +} diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy index f246731077..b79ffa5dc8 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy @@ -1,26 +1,21 @@ -package com.netgrif.application.engine.petrinet.webprocessRolesAndPermissionses +package com.netgrif.application.engine.petrinet.web import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.domain.Authority -import com.netgrif.application.engine.auth.domain.AuthorizingObject -import com.netgrif.application.engine.auth.domain.User -import com.netgrif.application.engine.auth.domain.UserState +import com.netgrif.application.engine.auth.domain.* import com.netgrif.application.engine.auth.service.interfaces.IUserService import com.netgrif.application.engine.ipc.TaskApiTest import com.netgrif.application.engine.petrinet.domain.PetriNet import com.netgrif.application.engine.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.startup.AuthorityRunner import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.startup.SuperCreator -import org.junit.Before import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith //import com.netgrif.application.engine.orgstructure.domain.Group -import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.security.authentication.UsernamePasswordAuthenticationToken @@ -34,6 +29,7 @@ import org.springframework.web.context.WebApplicationContext import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status @ExtendWith(SpringExtension.class) @@ -42,8 +38,12 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. class PetriNetControllerTest { public static final String NET_FILE = "process_delete_test.xml" + public static final String USER_NET_FILE = "all_data.xml" private static final String DELETE_PROCESS_URL = "/api/petrinet/" + private static final String DELETE_MY_PROCESS_URL = "/api/petrinet/my/" + + private static final String VIEW_MY_PROCESS_URL = "/api/petrinet/my" private static final String USER_EMAIL = "user@test.com" private static final String ADMIN_EMAIL = "admin@test.com" @@ -76,11 +76,6 @@ class PetriNetControllerTest { void before() { testHelper.truncateDbs() - def net = petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) - assert net.getNet() != null - - this.net = net.getNet() - mvc = MockMvcBuilders .webAppContextSetup(wac) .apply(springSecurity()) @@ -88,9 +83,10 @@ class PetriNetControllerTest { def auths = importHelper.createAuthorities(["user": [AuthorizingObject.FILTER_UPLOAD.name(), - AuthorizingObject.FILTER_DELETE_MY.name()], "admin": AuthorizingObject.stringValues()]) + AuthorizingObject.FILTER_DELETE_MY.name(), AuthorizingObject.PROCESS_DELETE_MY.name(), AuthorizingObject.PROCESS_VIEW_MY.name()], + "admin": AuthorizingObject.stringValues()]) - importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), + IUser basicUser = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], // [] as Group[], [] as ProcessRole[]) @@ -103,9 +99,19 @@ class PetriNetControllerTest { [] as ProcessRole[]) adminAuth = new UsernamePasswordAuthenticationToken(userService.findByEmail(ADMIN_EMAIL, false).transformToLoggedUser(), "password", auths.get("admin")) + + def net = petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) + assert net.getNet() != null + this.net = net.getNet() + + def userNet = petriNetService.importPetriNet(stream(USER_NET_FILE), VersionType.MAJOR, basicUser.transformToLoggedUser()) + assert userNet.getNet() != null + this.userNet = userNet.getNet() + + } - private PetriNet net + private PetriNet net, userNet private Authentication userAuth private Authentication adminAuth @@ -120,4 +126,19 @@ class PetriNetControllerTest { .with(authentication(this.adminAuth))) .andExpect(status().isOk()) } + + @Test + void testDeleteMyProcess() { + mvc.perform(delete(DELETE_MY_PROCESS_URL + userNet.stringId) + .with(authentication(this.userAuth))) + .andExpect(status().isOk()) + } + + @Test + void testViewMyProcess() { + mvc.perform(get(VIEW_MY_PROCESS_URL) + .param("identifier", userNet.stringId) + .with(authentication(this.userAuth))) + .andExpect(status().isOk()) + } } From f1a3d68a6e8b77c5b5705534f31b0a447b72b86d Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 2 Aug 2022 10:25:41 +0200 Subject: [PATCH 44/68] [NAE-1617] Refactor authority - corrected according to PR --- .../engine/petrinet/web/PetriNetControllerTest.groovy | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy index e69df1a04c..9163d0f890 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy @@ -106,9 +106,8 @@ class PetriNetControllerTest { // [] as Group[], [] as ProcessRole[]) - adminAuth = new UsernamePasswordAuthenticationToken(ADMIN_EMAIL, "password") - adminAuth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) adminAuth = new UsernamePasswordAuthenticationToken(userService.findByEmail(ADMIN_EMAIL, false).transformToLoggedUser(), "password", auths.get("admin")) + adminAuth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) def net = petriNetService.importPetriNet(stream(NET_FILE), VersionType.MAJOR, superCreator.getLoggedSuper()) assert net.getNet() != null From 378e10998f4d0dce4baa6425f5e23646ca52ce6b Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 2 Aug 2022 10:26:09 +0200 Subject: [PATCH 45/68] [NAE-1617] Refactor authority - merged 6.2.0 --- .../engine/petrinet/web/PetriNetControllerTest.groovy | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy index 9163d0f890..84176ac134 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy @@ -120,11 +120,6 @@ class PetriNetControllerTest { } - private PetriNet net, userNet - - private Authentication userAuth - private Authentication adminAuth - @Test void testDeleteProcess() { mvc.perform(delete(DELETE_PROCESS_URL + net.stringId) From 2203dee73866f5e9aebbccbc998b4971fb9b3418 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 2 Aug 2022 10:31:22 +0200 Subject: [PATCH 46/68] [NAE-1617] Refactor authority - merged 6.2.0 --- pom.xml | 22 +++++-------------- .../engine/auth/service/UserService.java | 1 - .../NaeSecurityConfiguration.java | 8 +------ 3 files changed, 6 insertions(+), 25 deletions(-) diff --git a/pom.xml b/pom.xml index 2d6dc31cb0..4e4fdf86b5 100644 --- a/pom.xml +++ b/pom.xml @@ -71,33 +71,21 @@ log4j-api 2.17.2 - - - org.springframework.data - spring-data-commons - 2.7.0-M4 - - - - org.springframework.data - spring-data-elasticsearch - 4.4.0-RC1 - org.apache.commons commons-compress 1.21 - - commons-beanutils - commons-beanutils - 1.9.4 - com.beust jcommander 1.75 + + commons-beanutils + commons-beanutils + 1.9.4 + diff --git a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java index efe2da62bc..f83219f4ee 100755 --- a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java @@ -2,7 +2,6 @@ import com.netgrif.application.engine.auth.domain.*; import com.netgrif.application.engine.auth.domain.repositories.UserRepository; -import com.netgrif.application.engine.auth.service.interfaces.IAfterRegistrationAuthService; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService; import com.netgrif.application.engine.auth.web.requestbodies.UpdateUserRequest; diff --git a/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java b/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java index dac771a145..1d5ce6d88a 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java +++ b/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java @@ -1,10 +1,6 @@ package com.netgrif.application.engine.configuration; import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.AuthorizingObject; -import com.netgrif.application.engine.auth.domain.UserProperties; -import com.netgrif.application.engine.auth.service.AfterRegistrationAuthService; -import com.netgrif.application.engine.auth.service.interfaces.IAfterRegistrationAuthService; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.configuration.authentication.providers.NaeAuthProperties; @@ -112,7 +108,7 @@ protected void configure(HttpSecurity http) throws Exception { .addFilterBefore(createPublicAuthenticationFilter(), BasicAuthenticationFilter.class) .addFilterAfter(createSecurityContextFilter(), BasicAuthenticationFilter.class) .authorizeRequests() - .antMatchers(getPatterns()).permitAll() + .antMatchers(naeAuthProperties.getServerPatterns()).permitAll() .antMatchers(OPTIONS).permitAll() .anyRequest().authenticated() .and() @@ -126,8 +122,6 @@ protected void configure(HttpSecurity http) throws Exception { .httpStrictTransportSecurity().includeSubDomains(true).maxAgeInSeconds(31536000) .and() .addHeaderWriter(new StaticHeadersWriter("X-Content-Security-Policy", "frame-src: 'none'")); - - setCsrf(http); } From 71f5e96e8e8df0031489ed97835ef9bde87701b5 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 2 Aug 2022 11:28:17 +0200 Subject: [PATCH 47/68] [NAE-1617] Refactor authority - updated authority documentation --- .../engine/auth/domain/AuthorizingObject.java | 4 +- .../engine/auth/service/AuthorityService.java | 48 ++++++++++++++++++- .../service/interfaces/IAuthorityService.java | 48 ++++++++++++++++++- .../NaeSecurityConfiguration.java | 1 + 4 files changed, 96 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java index e3693ac933..29c958de39 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java @@ -13,11 +13,11 @@ public enum AuthorizingObject { PROCESS_UPLOAD, PROCESS_VIEW_ALL, PROCESS_VIEW_MY, - PROCESS_DELETE_MY, PROCESS_DELETE_ALL, + PROCESS_DELETE_MY, FILTER_UPLOAD, - FILTER_DELETE_MY, FILTER_DELETE_ALL, + FILTER_DELETE_MY, USER_CREATE, USER_DELETE_ALL, USER_DELETE_MY, diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index 52553febf1..75767a4fcf 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -13,17 +13,31 @@ import java.util.List; import java.util.Optional; +/** + * Service to manage authorities in NAE + * */ @Service public class AuthorityService implements IAuthorityService { + /** + * Repository to communicate with database + * */ @Autowired private AuthorityRepository repository; + /** + * Retrieve all authorities from database + * */ @Override public List findAll() { return repository.findAll(); } + /** + * Returns or creates authority based on provided name from/into database + * @param name of searched authority + * @return Authority object + * */ @Override @Transactional public Authority getOrCreate(String name) { @@ -36,11 +50,21 @@ public Authority getOrCreate(String name) { return authority; } + /** + * Saves new or updated to database + * @param authority that will be saved + * @return saved authority object + * */ @Override public Authority save(Authority authority) { return repository.save(authority); } + /** + * Returns or creates authorities based on provided names from/into database + * @param authorities of searched authority + * @return list of authority objects + * */ @Override @Transactional public List getOrCreate(List authorities) { @@ -57,8 +81,12 @@ public List getOrCreate(List authorities) { return result; } + /** + * Removes authority from database based on provided name if exists + * @param name of authority to be deleted + * */ @Override - public Authority delete(String name) { + public void delete(String name) { if (isScope(name)) { throw new IllegalArgumentException("The authority name is not valid. Scope is suitable for this function."); } @@ -66,9 +94,14 @@ public Authority delete(String name) { if (authority == null) throw new IllegalArgumentException("Could not find authority with name [" + name + "]"); repository.delete(authority); - return authority; } + /** + * Returns authorities of provided scope. A scope contains authorities of the same name prefix, such as authorities + * of PROCESS scope: PROCESS_UPLOAD, PROCESS_DELETE etc. + * @param scope to be searched for + * @return list of authorities of given scope + * */ @Override public List findByScope(String scope) { List authorities; @@ -92,11 +125,22 @@ public Authority findByName(String name) { return authority; } + /** + * Returns authority from database based on provided ID + * @param id of authority to be retrieved + * @return optional of authority + * */ @Override public Optional findById(String id) { return Optional.of(repository.findBy_id(new ObjectId(id))); } + /** + * Returns authority from database based on provided ID if exists + * @param id of authority to be retrieved + * @return authority object + * */ + @Override public Authority getOne(String id) { Optional authority = repository.findById(id); if (authority.isEmpty()) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java index 0d8419b2c6..8eecf2654e 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java @@ -5,23 +5,69 @@ import java.util.List; import java.util.Optional; +/** + * Interface for managing authorities in NAE + * */ public interface IAuthorityService { + /** + * Finds all authorities in the system + * @return list of all authorities + * */ List findAll(); + /** + * Finds all authorities of given scope + * @param scope of authorities + * @return list of authorities of given scopr + * */ List findByScope(String scope); + /** + * Finds authority of given name + * @param name of authority to be searched + * @return authority object + * */ Authority findByName(String name); + /** + * Finds authority by ID + * @param id of authority + * @return optional of authority object + * */ Optional findById(String id); + /** + * Returns or creates authority of given name if it does not exist. + * @param name of the authority to be retrieved + * @return authority objects + * */ Authority getOrCreate(String name); + /** + * Saves authority object and retrieves it + * @param authority to be saved + * @return saved authority object + * */ Authority save(Authority authority); + /** + * Returns or creates authorities based on provided list of names + * @param authorities list of authority names + * @return list of authority objects + * */ List getOrCreate(List authorities); - Authority delete(String name); + /** + * Removes authority object based on name + * @param name of authority to be removed + * */ + void delete(String name); + /** + * Returns authority based on ID + * @param id of authority to be retrieved + * @return authority object + * */ Authority getOne(String id); } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java b/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java index 1d5ce6d88a..e88ed1674c 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java +++ b/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java @@ -122,6 +122,7 @@ protected void configure(HttpSecurity http) throws Exception { .httpStrictTransportSecurity().includeSubDomains(true).maxAgeInSeconds(31536000) .and() .addHeaderWriter(new StaticHeadersWriter("X-Content-Security-Policy", "frame-src: 'none'")); + setCsrf(http); } From f36bd15b459b812f33976a2e526bbe3c25fc7900 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 2 Aug 2022 11:29:24 +0200 Subject: [PATCH 48/68] [NAE-1617] Refactor authority - updated authority documentation --- .../application/engine/auth/service/AuthorityService.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index 75767a4fcf..c467448dbd 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -114,6 +114,12 @@ public List findByScope(String scope) { return authorities; } + /** + * Returns authority based on name, throws exception if authority name is not valid or authority with provided name + * cannot be found. + * @param name of authority + * @return authority object + * */ @Override public Authority findByName(String name) { if (isScope(name)) { From 2bec5ebd62ff6060f6af418c8dd34d79ce26118b Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 2 Aug 2022 11:32:59 +0200 Subject: [PATCH 49/68] [NAE-1617] Refactor authority - updated authority documentation --- .../application/engine/auth/service/AuthorityService.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index c467448dbd..f8b93f4463 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -154,6 +154,11 @@ public Authority getOne(String id) { return authority.get(); } + /** + * Checks for authorityName, if it is valid scope name + * @param authorityName of authority + * @return boolean whether the provided name is valid scope name + * */ private boolean isScope(String authorityName) { if (authorityName.endsWith("*")) return true; From 017db434b80fee319f21425b79fb56dadff7c6ca Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 2 Aug 2022 12:12:15 +0200 Subject: [PATCH 50/68] [NAE-1617] Refactor authority - updated authority documentation --- .../application/engine/auth/domain/AuthorizingObject.java | 1 + .../auth/service/AbstractBaseAuthorizationService.java | 4 +--- .../engine/auth/service/BaseAuthorizationServiceAspect.java | 6 +++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java index 29c958de39..34d66626be 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java @@ -10,6 +10,7 @@ * using given authorizing object. * */ public enum AuthorizingObject { + DEFAULT, PROCESS_UPLOAD, PROCESS_VIEW_ALL, PROCESS_VIEW_MY, diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java index 9e31c9fb7e..69c15886f2 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java @@ -8,11 +8,9 @@ public abstract class AbstractBaseAuthorizationService implements IBaseAuthorizationService { private final IUserService userService; - private final IAuthorityService authorityService; - public AbstractBaseAuthorizationService(IUserService userService, IAuthorityService authorityService) { + public AbstractBaseAuthorizationService(IUserService userService) { this.userService = userService; - this.authorityService = authorityService; } @Override diff --git a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java index 9ba41bbb33..eb081101f6 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java @@ -33,8 +33,8 @@ @Service public class BaseAuthorizationServiceAspect extends AbstractBaseAuthorizationService { - public BaseAuthorizationServiceAspect(@Autowired IUserService userService, @Autowired IAuthorityService authorityService) { - super(userService, authorityService); + public BaseAuthorizationServiceAspect(@Autowired IUserService userService) { + super(userService); } /** @@ -65,7 +65,7 @@ protected Object authorize(ProceedingJoinPoint joinPoint, Authorizations authori if (result) { return joinPoint.proceed(); } else { - throw new AccessDeniedException("Access Denied"); + throw new AccessDeniedException("Access Denied. User does not have required authorization level."); } } From a60bb47d454f4af848ed953cb8ca9f7d340a7132 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 12 Sep 2022 13:16:57 +0200 Subject: [PATCH 51/68] [NAE-1617] Authority refactor - corrected build error --- .../engine/auth/service/AuthorityService.java | 5 ++-- .../engine/auth/web/AuthorityController.java | 27 ++++++++++++++----- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index f8b93f4463..c9537ba0ff 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -5,6 +5,7 @@ import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import org.bson.types.ObjectId; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -42,7 +43,7 @@ public List findAll() { @Transactional public Authority getOrCreate(String name) { if (isScope(name)) { - throw new IllegalArgumentException("The authority name is not valid. Scope is suitable for this function."); + throw new IllegalArgumentException("The authority name is not valid. Scope is not suitable for this function."); } Authority authority = repository.findByName(name); if (authority == null) @@ -92,7 +93,7 @@ public void delete(String name) { } Authority authority = repository.findByName(name); if (authority == null) - throw new IllegalArgumentException("Could not find authority with name [" + name + "]"); + throw new ResourceNotFoundException("Could not find authority with name [" + name + "]"); repository.delete(authority); } diff --git a/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java index 0810351926..4ece6bc677 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java @@ -6,12 +6,15 @@ import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.auth.web.requestbodies.NewAuthorityRequest; import com.netgrif.application.engine.auth.web.responsebodies.AuthorityResource; +import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; +import com.netgrif.application.engine.workflow.web.responsebodies.ResponseMessage; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.Authorization; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; @@ -39,9 +42,15 @@ public class AuthorityController { }) @ApiOperation(value = "Delete authority", authorizations = @Authorization("BasicAuth")) @DeleteMapping(value = "/delete/{name}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public EntityModel delete(@PathVariable String name, Authentication auth, Locale locale) { - Authority deletedAuthority = authorityService.delete(name); - return AuthorityResource.of(deletedAuthority); + public MessageResource delete(@PathVariable String name) { + try { + authorityService.delete(name); + log.info("Authority [" + name + "] has been deleted successfully."); + return new MessageResource(ResponseMessage.createSuccessMessage("Authority [" + name + "] has been deleted successfully.")); + } catch (IllegalArgumentException | ResourceNotFoundException e) { + log.error("Failed to delete authority [" + name + "].", e); + return new MessageResource(ResponseMessage.createErrorMessage("Failed to delete authority.")); + } } @Authorizations(value = { @@ -49,8 +58,14 @@ public EntityModel delete(@PathVariable String name, Authentication a }) @ApiOperation(value = "Delete authority", authorizations = @Authorization("BasicAuth")) @PostMapping(value = "/create", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public EntityModel create(@RequestBody NewAuthorityRequest request, Authentication auth, Locale locale) { - Authority authority = authorityService.getOrCreate(request.name); - return AuthorityResource.of(authority); + public EntityModel create(@RequestBody NewAuthorityRequest request) { + try { + Authority authority = authorityService.getOrCreate(request.name); + log.info("Authority [" + authority + "] has been created successfully."); + return AuthorityResource.of(authority); + } catch (IllegalArgumentException | ResourceNotFoundException e) { + log.error("Failed to create authority [" + request.name + "].", e); + return null; + } } } From 7c919085c269f1db50a531683ecc8c43905446b2 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 13 Sep 2022 11:50:03 +0200 Subject: [PATCH 52/68] [NAE-1617] Authority refactor - corrected according to PR --- .../application/engine/auth/domain/Authorize.java | 1 + .../engine/auth/web/AuthorityController.java | 15 ++++++--------- .../engine/petrinet/web/PetriNetController.java | 9 +++------ 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java index 8098e78e11..1a5d619c9f 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java @@ -7,6 +7,7 @@ /** * This annotation serves as marking for functions that requires additional authorization over the basic authentication. * */ +@Repeatable(Authorizations.class) @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD, ElementType.TYPE }) @Inherited diff --git a/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java index 4ece6bc677..2e26fdd89d 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java @@ -8,9 +8,9 @@ import com.netgrif.application.engine.auth.web.responsebodies.AuthorityResource; import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; import com.netgrif.application.engine.workflow.web.responsebodies.ResponseMessage; -import io.swagger.annotations.Api; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.Authorization; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -18,11 +18,8 @@ import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; -import java.util.Locale; - @Slf4j @RestController @RequestMapping("/api/authority") @@ -31,7 +28,7 @@ havingValue = "true", matchIfMissing = true ) -@Api(tags = {"Authority"}) +@Tag(name = "Authority") public class AuthorityController { @Autowired @@ -40,7 +37,7 @@ public class AuthorityController { @Authorizations(value = { @Authorize(authority = "AUTHORITY_DELETE") }) - @ApiOperation(value = "Delete authority", authorizations = @Authorization("BasicAuth")) + @Operation(description = "Delete authority", security = {@SecurityRequirement(name = "BasicAuth")}) @DeleteMapping(value = "/delete/{name}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public MessageResource delete(@PathVariable String name) { try { @@ -56,7 +53,7 @@ public MessageResource delete(@PathVariable String name) { @Authorizations(value = { @Authorize(authority = "AUTHORITY_CREATE") }) - @ApiOperation(value = "Delete authority", authorizations = @Authorization("BasicAuth")) + @Operation(description = "Delete authority", security = {@SecurityRequirement(name = "BasicAuth")}) @PostMapping(value = "/create", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public EntityModel create(@RequestBody NewAuthorityRequest request) { try { diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index 92c9e241cb..37b0842867 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -18,8 +18,6 @@ import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessage; import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessageResource; import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.Authorization; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; @@ -131,7 +129,7 @@ public PetriNetReferenceResource getOne(@PathVariable("id") String id, Authentic @Authorizations(value = { @Authorize(authority = "PROCESS_VIEW_MY") }) - @Operation(value = "Get all processes", security = {@SecurityRequirement(name = "BasicAuth")}) + @Operation(description = "Get all processes", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/my", produces = MediaTypes.HAL_JSON_VALUE) public PetriNetReferenceResources getMy(@RequestParam(value = "indentifier", required = false) String identifier, @RequestParam(value = "version", required = false) String version, Authentication auth, Locale locale) { LoggedUser user = (LoggedUser) auth.getPrincipal(); @@ -215,7 +213,6 @@ PagedModel searchPetriNets(@RequestBody Map Date: Tue, 13 Sep 2022 12:21:52 +0200 Subject: [PATCH 53/68] [NAE-1617] Authority refactor - refactored old swagger annotations to new - changed private to protected at BaseAuthorizationServiceAspect.isAllowedByExpression --- .../BaseAuthorizationServiceAspect.java | 3 +-- .../auth/web/AuthenticationController.java | 8 ++---- .../engine/auth/web/UserController.java | 21 +++++---------- .../orgstructure/web/GroupController.java | 26 ++++++++----------- .../workflow/web/PublicTaskController.java | 8 +----- .../engine/workflow/web/TaskController.java | 3 --- .../auth/AuthenticationControllerTest.groovy | 2 +- 7 files changed, 23 insertions(+), 48 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java index eb081101f6..f4fd4f43d1 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java @@ -2,7 +2,6 @@ import com.netgrif.application.engine.auth.domain.Authorizations; import com.netgrif.application.engine.auth.domain.Authorize; -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.configuration.ApplicationContextProvider; import lombok.extern.slf4j.Slf4j; @@ -78,7 +77,7 @@ protected Object authorize(ProceedingJoinPoint joinPoint, Authorizations authori * @param expression the SpEL expression * @return the evaluated value, whether the SpEL expression returns true or not * */ - private boolean isAllowedByExpression(ProceedingJoinPoint joinPoint, String expression) { + protected boolean isAllowedByExpression(ProceedingJoinPoint joinPoint, String expression) { if (expression == null || expression.equals("")) { return true; } diff --git a/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java b/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java index a37e914c7b..7b9fe38505 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java @@ -51,9 +51,6 @@ public class AuthenticationController { @Autowired private IRegistrationService registrationService; - @Autowired - private UserDetailsServiceImpl userDetailsService; - @Autowired private IMailService mailService; @@ -96,15 +93,14 @@ public MessageResource signup(@RequestBody RegistrationRequest regRequest) { @Authorizations(value = { @Authorize(authority = "USER_CREATE") }) - @ApiOperation(value = "Send invitation to a new user", authorizations = @Authorization("BasicAuth")) @PostMapping(value = "/invite", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public MessageResource invite(@RequestBody NewUserRequest newUserRequest, Authentication auth) { + public MessageResource invite(@RequestBody NewUserRequest newUserRequest) { try { if (!serverAuthProperties.isOpenRegistration()) { return MessageResource.errorMessage("Registration is disabled."); } - newUserRequest.email = URLDecoder.decode(newUserRequest.email, StandardCharsets.UTF_8.name()); + newUserRequest.email = URLDecoder.decode(newUserRequest.email, StandardCharsets.UTF_8); if (mailAttemptService.isBlocked(newUserRequest.email)) { return MessageResource.successMessage("Done"); } diff --git a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java index 0e4a9a47d3..a193daf775 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java @@ -22,10 +22,6 @@ import com.netgrif.application.engine.settings.web.PreferencesResource; import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; import com.netgrif.application.engine.workflow.web.responsebodies.ResourceLinkAssembler; -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.Authorization; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; @@ -68,9 +64,6 @@ public class UserController { @Autowired private IUserService userService; - @Autowired - private UserDetailsServiceImpl userDetailsService; - @Autowired private IProcessRoleService processRoleService; @@ -162,7 +155,7 @@ public UserResource updateUser(@PathVariable("id") String userId, @RequestBody U LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); IUser user = userService.resolveById(userId, false); if (user == null || (!loggedUser.hasAuthority("USER_EDIT_ALL") && !Objects.equals(loggedUser.getId(), userId))) - throw new UnauthorisedRequestException("User " + loggedUser.getUsername() + " doesn't have permission to modify profile of " + user.transformToLoggedUser().getUsername()); + throw new UnauthorisedRequestException("User " + loggedUser.getUsername() + " doesn't have permission to modify profile of " + (user != null ? user.transformToLoggedUser().getUsername() : null)); user = userService.update(user, updates); securityContextService.saveToken(userId); @@ -217,7 +210,7 @@ public MessageResource assignRolesToUser(@PathVariable("id") String userId, @Req @ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), }) - public AuthoritiesResources getAllAuthorities(Authentication auth) { + public AuthoritiesResources getAllAuthorities() { return new AuthoritiesResources(authorityService.findAll()); } @@ -253,13 +246,13 @@ public PreferencesResource preferences(Authentication auth) { @Authorizations(value = { @Authorize(authority = "USER_EDIT_ALL") }) - @ApiOperation(value = "Assign authority to the user", - notes = "Caller must have the USER_EDIT authority", - authorizations = @Authorization("BasicAuth")) + @Operation(summary = "Assign authority to the user", + description = "Caller must have the USER_EDIT authority", + security = {@SecurityRequirement(name = "BasicAuth")}) @DeleteMapping(value = "/{id}/authority/remove", consumes = MediaType.TEXT_PLAIN_VALUE, produces = MediaTypes.HAL_JSON_VALUE) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = MessageResource.class), - @ApiResponse(code = 403, message = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), }) public MessageResource removeAuthorityFromUser(@PathVariable("id") String userId, @RequestBody String authorityId) { userService.removeAuthority(userId, authorityId); diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java index 3e2d314c59..5e7bd1dabd 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java @@ -5,9 +5,6 @@ import com.netgrif.application.engine.orgstructure.web.responsebodies.Group; import com.netgrif.application.engine.orgstructure.web.responsebodies.GroupsResource; import com.netgrif.application.engine.workflow.domain.Case; -import com.netgrif.application.engine.workflow.domain.QCase; -import io.swagger.annotations.*; -import org.springframework.beans.factory.annotation.Autowired; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; @@ -16,7 +13,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.hateoas.MediaTypes; import org.springframework.security.core.Authentication; -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; @@ -64,13 +60,13 @@ public GroupsResource getAllGroups() { @Authorizations(value = { @Authorize(authority = "GROUP_VIEW_MY") }) - @Operation(value = "Get logged user's groups in the system", - notes = "Caller must have the GROUP_VIEW_MY authority", - authorizations = @Authorization("BasicAuth")) + @Operation(summary = "Get logged user's groups in the system", + description = "Caller must have the GROUP_VIEW_MY authority", + security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/my", produces = MediaTypes.HAL_JSON_VALUE) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = GroupsResource.class), - @ApiResponse(code = 403, message = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), }) public GroupsResource getMyGroups(Authentication auth) { String loggedUserId = ((LoggedUser)auth.getPrincipal()).getId(); @@ -85,13 +81,13 @@ public GroupsResource getMyGroups(Authentication auth) { @Authorizations(value = { @Authorize(authority = "GROUP_MEMBERSHIP_MY") }) - @Operation(value = "Get logged user's groups in the system", - notes = "Caller must have the GROUP_VIEW_MY authority", - authorizations = @Authorization("BasicAuth")) - @RequestMapping(value = "/membership", method = RequestMethod.GET, produces = MediaTypes.HAL_JSON_VALUE) + @Operation(summary = "Get logged user's groups in the system", + description = "Caller must have the GROUP_VIEW_MY authority", + security = {@SecurityRequirement(name = "BasicAuth")}) + @GetMapping(value = "/membership", produces = MediaTypes.HAL_JSON_VALUE) @ApiResponses(value = { - @ApiResponse(code = 200, message = "OK", response = GroupsResource.class), - @ApiResponse(code = 403, message = "Caller doesn't fulfill the authorisation requirements"), + @ApiResponse(responseCode = "200", description = "OK"), + @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), }) public GroupsResource getMembershipGroups(Authentication auth) { Set groups = service.getGroupCasesOfUser(((LoggedUser)auth.getPrincipal()).transformToUser()); diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java b/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java index 7abc073548..62ce393fab 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java @@ -3,7 +3,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.netgrif.application.engine.auth.domain.Authorizations; import com.netgrif.application.engine.auth.domain.Authorize; -import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.workflow.domain.MergeFilterOperation; @@ -12,7 +11,6 @@ import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; import com.netgrif.application.engine.workflow.web.requestbodies.singleaslist.SingleTaskSearchRequestAsList; import com.netgrif.application.engine.workflow.web.responsebodies.LocalisedTaskResource; -import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; import com.netgrif.application.engine.workflow.web.responsebodies.TaskReference; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; @@ -50,14 +48,11 @@ public class PublicTaskController extends AbstractTaskController { private final ITaskService taskService; - private final IDataService dataService; - final IUserService userService; public PublicTaskController(ITaskService taskService, IDataService dataService, IUserService userService) { super(taskService, dataService, null); this.taskService = taskService; - this.dataService = dataService; this.userService = userService; } @@ -70,7 +65,6 @@ public List getTasksOfCase(@PathVariable("id") String caseId, Loc @Authorizations(value = { @Authorize(expression = "@taskAuthorizationService.canCallAssign(@userService.getAnonymousLogged(), #taskId)") }) - @PreAuthorize("@taskAuthorizationService.canCallAssign(@userService.getAnonymousLogged(), #taskId)") @GetMapping(value = "/assign/{id}", produces = MediaTypes.HAL_JSON_VALUE) @Operation(summary = "Assign task", description = "Caller must be able to perform the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -175,7 +169,7 @@ public EntityModel deleteFile(@PathVariable("id") Strin @Operation(summary = "Download preview for file field value") @GetMapping(value = "/{id}/file_preview/{field}", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE) - public ResponseEntity getFilePreview(@PathVariable("id") String taskId, @PathVariable("field") String fieldId, HttpServletResponse response) throws FileNotFoundException { + public ResponseEntity getFilePreview(@PathVariable("id") String taskId, @PathVariable("field") String fieldId) throws FileNotFoundException { return super.getFilePreview(taskId, fieldId); } diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java b/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java index 5a21a6a9f9..4b631c586c 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/TaskController.java @@ -14,10 +14,7 @@ import com.netgrif.application.engine.workflow.web.requestbodies.singleaslist.SingleTaskSearchRequestAsList; import com.netgrif.application.engine.workflow.web.responsebodies.CountResponse; import com.netgrif.application.engine.workflow.web.responsebodies.LocalisedTaskResource; -import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; import com.netgrif.application.engine.workflow.web.responsebodies.TaskReference; -import io.swagger.annotations.*; -import org.checkerframework.checker.units.qual.A; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; diff --git a/src/test/groovy/com/netgrif/application/engine/auth/AuthenticationControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/AuthenticationControllerTest.groovy index 412ebed381..2f3620c342 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/AuthenticationControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/auth/AuthenticationControllerTest.groovy @@ -93,7 +93,7 @@ class AuthenticationControllerTest { @Test @WithMockUser(roles = "ADMIN") void inviteTest() { - controller.invite(new NewUserRequest(email: EMAIL, groups: [], processRoles: []), null) + controller.invite(new NewUserRequest(email: EMAIL, groups: [], processRoles: [])) MimeMessage[] messages = smtpServer.getReceivedMessages() assertMessageReceived(messages) From b573dfa1528af9fc92af7084d232099ef045753d Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 13 Sep 2022 12:22:01 +0200 Subject: [PATCH 54/68] [NAE-1617] Authority refactor - refactored old swagger annotations to new - changed private to protected at BaseAuthorizationServiceAspect.isAllowedByExpression --- .../engine/auth/web/responsebodies/AuthoritiesResources.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthoritiesResources.java b/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthoritiesResources.java index 6f3e5b3df5..6053fd61be 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthoritiesResources.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthoritiesResources.java @@ -6,8 +6,6 @@ import org.springframework.hateoas.CollectionModel; import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; -import java.util.ArrayList; - public class AuthoritiesResources extends CollectionModel { public AuthoritiesResources(Iterable content) { super(content); @@ -19,6 +17,6 @@ public AuthoritiesResources() { public void buildLinks() { add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(UserController.class) - .getAllAuthorities(null)).withSelfRel()); + .getAllAuthorities()).withSelfRel()); } } From 8b6bd3f3c14339c85db594cd1080529b17f7bc2b Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 13 Sep 2022 12:32:21 +0200 Subject: [PATCH 55/68] [NAE-1617] Authority refactor - refactored @Authorize annotation to handle authority list --- .../application/engine/auth/domain/Authorize.java | 2 +- .../service/AbstractBaseAuthorizationService.java | 14 +++++++++----- .../service/BaseAuthorizationServiceAspect.java | 2 +- .../interfaces/IBaseAuthorizationService.java | 4 +--- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java index 1a5d619c9f..38a0f91f10 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java @@ -17,7 +17,7 @@ /** * The authorizing object to be checked, whether the user has it assigned. * */ - String authority() default ""; + String[] authority() default ""; /** * The Spring-EL expression to be evaluated before invoking the protected method. diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java index 69c15886f2..c1c53049f7 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java @@ -1,9 +1,12 @@ package com.netgrif.application.engine.auth.service; -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.auth.service.interfaces.IBaseAuthorizationService; import com.netgrif.application.engine.auth.service.interfaces.IUserService; +import org.springframework.security.core.GrantedAuthority; + +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; public abstract class AbstractBaseAuthorizationService implements IBaseAuthorizationService { @@ -14,9 +17,10 @@ public AbstractBaseAuthorizationService(IUserService userService) { } @Override - public final boolean hasAuthority(String authorizingObject) { - if (authorizingObject == null || authorizingObject.length() == 0) + public final boolean hasAnyAuthority(String[] authorizingObject) { + if (authorizingObject == null || authorizingObject.length == 0) return true; - return this.userService.getLoggedUser().getAuthorities().stream().anyMatch(a -> a.getName().equals(authorizingObject)); + Set loggedUserAuthorities = this.userService.getLoggedUser().getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet()); + return loggedUserAuthorities.containsAll(Arrays.asList(authorizingObject)); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java index f4fd4f43d1..73157a36f8 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java @@ -57,7 +57,7 @@ protected Object authorize(ProceedingJoinPoint joinPoint, Authorizations authori if (authorizations.value() != null && authorizations.value().length > 0) { for (Authorize authorize : authorizations.value()) { - result = result || (isAllowedByExpression(joinPoint, authorize.expression()) && hasAuthority(authorize.authority())); + result = result || (isAllowedByExpression(joinPoint, authorize.expression()) && hasAnyAuthority(authorize.authority())); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java index 85808a1c71..30a128978b 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IBaseAuthorizationService.java @@ -1,8 +1,6 @@ package com.netgrif.application.engine.auth.service.interfaces; -import com.netgrif.application.engine.auth.domain.AuthorizingObject; - public interface IBaseAuthorizationService { - boolean hasAuthority(String authorityName); + boolean hasAnyAuthority(String[] authorizingObject); } From f89384c2918d1be1daf51e379c353ecd3fc85e03 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 13 Sep 2022 12:32:43 +0200 Subject: [PATCH 56/68] [NAE-1617] Authority refactor - added ELASTIC_REINDEX authority --- .../application/engine/auth/domain/AuthorizingObject.java | 3 ++- .../application/engine/elastic/web/ElasticController.java | 4 +--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java index 34d66626be..d47dc3397f 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java @@ -51,7 +51,8 @@ public enum AuthorizingObject { TASK_FINISH, TASK_CANCEL, TASK_DELEGATE, - TASK_SAVE_DATA; + TASK_SAVE_DATA, + ELASTIC_REINDEX; public static List stringValues() { return Arrays.stream(AuthorizingObject.values()).map(Enum::name).collect(Collectors.toList()); diff --git a/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java b/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java index 68bf887911..665964e834 100644 --- a/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java +++ b/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java @@ -52,9 +52,7 @@ public class ElasticController { description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) @PostMapping(value = "/reindex", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - @Authorizations({ - @Authorize(authority = Authority.defaultAdminAuthority) - }) + @Authorize(authority = {"ELASTIC_REINDEX"}) @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), From 6419576e12b7e47f18eded8522bf048dc9ba40f8 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 13 Sep 2022 12:44:41 +0200 Subject: [PATCH 57/68] [NAE-1617] Authority refactor - removed Authorization annotation from method and enabled multiple Authorize annotation on methods --- .../engine/auth/domain/AuthorizingObject.java | 4 +- .../auth/web/AuthenticationController.java | 6 +- .../engine/auth/web/AuthorityController.java | 9 +-- .../orgstructure/web/GroupController.java | 12 +--- .../orgstructure/web/LdapController.java | 8 +-- .../responsebodies/LdapGroupsResource.java | 2 +- .../petrinet/web/PetriNetController.java | 48 +++++----------- .../PetriNetReferenceResource.java | 2 +- .../engine/workflow/web/FilterController.java | 10 +--- .../engine/workflow/web/TaskController.java | 55 ++++++------------ .../workflow/web/WorkflowController.java | 56 ++++++------------- 11 files changed, 68 insertions(+), 144 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java index d47dc3397f..fe863b768f 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java @@ -52,7 +52,9 @@ public enum AuthorizingObject { TASK_CANCEL, TASK_DELEGATE, TASK_SAVE_DATA, - ELASTIC_REINDEX; + ELASTIC_REINDEX, + LDAP_GROUP_GET_ALL, + LDAP_GROUP_ASSIGN_ROLES; public static List stringValues() { return Arrays.stream(AuthorizingObject.values()).map(Enum::name).collect(Collectors.toList()); diff --git a/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java b/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java index 7b9fe38505..0b39c5f7d9 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java @@ -1,11 +1,9 @@ package com.netgrif.application.engine.auth.web; -import com.netgrif.application.engine.auth.domain.Authorizations; import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.domain.RegisteredUser; import com.netgrif.application.engine.auth.service.InvalidUserTokenException; -import com.netgrif.application.engine.auth.service.UserDetailsServiceImpl; import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService; import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.auth.web.requestbodies.ChangePasswordRequest; @@ -90,9 +88,7 @@ public MessageResource signup(@RequestBody RegistrationRequest regRequest) { } @Operation(summary = "Send invitation to a new user", security = {@SecurityRequirement(name = "BasicAuth")}) - @Authorizations(value = { - @Authorize(authority = "USER_CREATE") - }) + @Authorize(authority = "USER_CREATE") @PostMapping(value = "/invite", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public MessageResource invite(@RequestBody NewUserRequest newUserRequest) { try { diff --git a/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java index 2e26fdd89d..6e4be3e095 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java @@ -1,7 +1,6 @@ package com.netgrif.application.engine.auth.web; import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.Authorizations; import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.auth.web.requestbodies.NewAuthorityRequest; @@ -34,9 +33,7 @@ public class AuthorityController { @Autowired private IAuthorityService authorityService; - @Authorizations(value = { - @Authorize(authority = "AUTHORITY_DELETE") - }) + @Authorize(authority = "AUTHORITY_DELETE") @Operation(description = "Delete authority", security = {@SecurityRequirement(name = "BasicAuth")}) @DeleteMapping(value = "/delete/{name}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public MessageResource delete(@PathVariable String name) { @@ -50,9 +47,7 @@ public MessageResource delete(@PathVariable String name) { } } - @Authorizations(value = { - @Authorize(authority = "AUTHORITY_CREATE") - }) + @Authorize(authority = "AUTHORITY_CREATE") @Operation(description = "Delete authority", security = {@SecurityRequirement(name = "BasicAuth")}) @PostMapping(value = "/create", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public EntityModel create(@RequestBody NewAuthorityRequest request) { diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java index 5e7bd1dabd..75ae5ecc1c 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java @@ -38,9 +38,7 @@ public GroupController(INextGroupService service) { this.service = service; } - @Authorizations(value = { - @Authorize(authority = "GROUP_VIEW_ALL") - }) + @Authorize(authority = "GROUP_VIEW_ALL") @Operation(summary = "Get all groups in the system", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -57,9 +55,7 @@ public GroupsResource getAllGroups() { return new GroupsResource(groupResponse); } - @Authorizations(value = { - @Authorize(authority = "GROUP_VIEW_MY") - }) + @Authorize(authority = "GROUP_VIEW_MY") @Operation(summary = "Get logged user's groups in the system", description = "Caller must have the GROUP_VIEW_MY authority", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -78,9 +74,7 @@ public GroupsResource getMyGroups(Authentication auth) { return new GroupsResource(groupResponse); } - @Authorizations(value = { - @Authorize(authority = "GROUP_MEMBERSHIP_MY") - }) + @Authorize(authority = "GROUP_MEMBERSHIP_MY") @Operation(summary = "Get logged user's groups in the system", description = "Caller must have the GROUP_VIEW_MY authority", security = {@SecurityRequirement(name = "BasicAuth")}) diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/LdapController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/LdapController.java index 9ce263ae73..8d0ff55e82 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/LdapController.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/LdapController.java @@ -1,5 +1,6 @@ package com.netgrif.application.engine.orgstructure.web; +import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.ldap.domain.LdapGroup; import com.netgrif.application.engine.ldap.domain.LdapGroupRef; @@ -20,7 +21,6 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; -import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -43,7 +43,7 @@ public class LdapController { @Autowired protected ILdapGroupRefService service; - @PreAuthorize("hasRole('ADMIN')") + @Authorize(authority = "LDAP_GROUP_GET_ALL") @Operation(summary = "Get all ldap groups", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -52,7 +52,7 @@ public class LdapController { @ApiResponse(responseCode = "200", description = "OK"), @ApiResponse(responseCode = "403", description = "Caller doesn't fulfill the authorisation requirements"), }) - public LdapGroupsResource getAllLdapGroups(@RequestBody LdapGroupSearchBody body, Authentication auth) { + public LdapGroupsResource getAllLdapGroups(@RequestBody LdapGroupSearchBody body) { List groups; if (body == null || body.getFulltext().equals("")) { groups = service.findAllGroups(); @@ -69,7 +69,7 @@ public LdapGroupsResource getAllLdapGroups(@RequestBody LdapGroupSearchBody body return new LdapGroupsResource(ldapGroupResponse); } - @PreAuthorize("hasRole('ADMIN')") + @Authorize(authority = "LDAP_GROUP_ASSIGN_ROLES") @Operation(summary = "Assign role to the ldap group", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/LdapGroupsResource.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/LdapGroupsResource.java index da60ad545d..81dfc508f1 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/LdapGroupsResource.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/responsebodies/LdapGroupsResource.java @@ -15,7 +15,7 @@ public LdapGroupsResource(Iterable content) { private void buildLinks() { add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(LdapController.class) - .getAllLdapGroups(null,null)).withSelfRel()) + .getAllLdapGroups(null)).withSelfRel()) .add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(LdapController.class) .assignRolesToLdapGroup(null, null)).withRel("roleAssign")); } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index 37b0842867..d323c6181f 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -1,6 +1,5 @@ package com.netgrif.application.engine.petrinet.web; -import com.netgrif.application.engine.auth.domain.Authorizations; import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.eventoutcomes.LocalisedEventOutcomeFactory; @@ -43,14 +42,13 @@ import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; -import java.io.*; +import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.*; import java.util.stream.Collectors; -import static org.springframework.web.bind.annotation.RequestMethod.GET; - @RestController @RequestMapping("/api/petrinet") @ConditionalOnProperty( @@ -63,9 +61,6 @@ public class PetriNetController { private static final Logger log = LoggerFactory.getLogger(PetriNetController.class); - @Autowired - private FileStorageConfiguration fileStorageConfiguration; - @Autowired private IPetriNetService service; @@ -75,9 +70,7 @@ public class PetriNetController { @Autowired private StringToVersionConverter converter; - @Authorizations(value = { - @Authorize(authority = "PROCESS_UPLOAD") - }) + @Authorize(authority = "PROCESS_UPLOAD") @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")}) @@ -102,9 +95,7 @@ public EntityModel importPetriNet( } } - @Authorizations(value = { - @Authorize(authority = "PROCESS_VIEW_ALL") - }) + @Authorize(authority = "PROCESS_VIEW_ALL") @Operation(summary = "Get all processes", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(produces = MediaTypes.HAL_JSON_VALUE) public PetriNetReferenceResources getAll(@RequestParam(value = "indentifier", required = false) String identifier, @RequestParam(value = "version", required = false) String version, Authentication auth, Locale locale) { @@ -113,7 +104,7 @@ public PetriNetReferenceResources getAll(@RequestParam(value = "indentifier", re return new PetriNetReferenceResources(service.getReferencesByIdentifier(identifier, user, locale)); } else if (identifier == null && version != null) { return new PetriNetReferenceResources(service.getReferencesByVersion(converter.convert(version), user, locale)); - } else if (identifier != null && version != null) { + } else if (identifier != null) { return new PetriNetReferenceResources(Collections.singletonList(service.getReference(identifier, converter.convert(version), user, locale))); } else { return new PetriNetReferenceResources(service.getReferences(user, locale)); @@ -126,9 +117,7 @@ public PetriNetReferenceResource getOne(@PathVariable("id") String id, Authentic return new PetriNetReferenceResource(IPetriNetService.transformToReference(service.getPetriNet(decodeUrl(id)), locale)); } - @Authorizations(value = { - @Authorize(authority = "PROCESS_VIEW_MY") - }) + @Authorize(authority = "PROCESS_VIEW_MY") @Operation(description = "Get all processes", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/my", produces = MediaTypes.HAL_JSON_VALUE) public PetriNetReferenceResources getMy(@RequestParam(value = "indentifier", required = false) String identifier, @RequestParam(value = "version", required = false) String version, Authentication auth, Locale locale) { @@ -140,7 +129,7 @@ public PetriNetReferenceResources getMy(@RequestParam(value = "indentifier", req } else if (identifier == null && version != null) { references = service.getReferencesByVersion(converter.convert(version), user, locale).stream().filter(ref -> ref.getAuthor().getId().equals(user.getId())).collect(Collectors.toList()); return new PetriNetReferenceResources(references); - } else if (identifier != null && version != null) { + } else if (identifier != null) { PetriNetReference reference = service.getReference(identifier, converter.convert(version), user, locale); if (reference.getAuthor().getId().equals(user.getId())) return new PetriNetReferenceResources(Collections.singletonList(reference)); @@ -162,7 +151,7 @@ public PetriNetReferenceResource getOne(@PathVariable("identifier") String ident @Operation(summary = "Get transitions of processes", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/transitions", produces = MediaTypes.HAL_JSON_VALUE) public TransitionReferencesResource getTransitionReferences(@RequestParam List ids, Authentication auth, Locale locale) { - ids.forEach(id -> id = decodeUrl(id)); + ids.forEach(PetriNetController::decodeUrl); return new TransitionReferencesResource(service.getTransitionReferences(ids, (LoggedUser) auth.getPrincipal(), locale)); } @@ -188,7 +177,7 @@ public TransactionsResource getTransactions(@PathVariable("netId") String netId, @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) { + public FileSystemResource getNetFile(@PathVariable("netId") String netId, @RequestParam(value = "title", required = false) String title, HttpServletResponse response) { FileSystemResource fileResource = service.getFile(decodeUrl(netId), decodeUrl(title)); response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE); response.setHeader("Content-Disposition", "attachment; filename=\"" + fileResource.getFilename() + Importer.FILE_EXTENSION + "\""); @@ -210,9 +199,7 @@ PagedModel searchPetriNets(@RequestBody Map assign(Authentication auth, @PathVar return super.assign(loggedUser, taskId, locale); } - @Authorizations(value = { - @Authorize(authority = "TASK_DELEGATE"), - @Authorize(expression = "@taskAuthorizationService.canCallDelegate(#auth.getPrincipal(), #taskId)") - }) + @Authorize(authority = "TASK_DELEGATE") + @Authorize(expression = "@taskAuthorizationService.canCallDelegate(#auth.getPrincipal(), #taskId)") @Operation(summary = "Delegate task", description = "Caller must be able to delegate the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -119,10 +114,8 @@ public EntityModel delegate(Authentication auth, @PathV return super.delegate(loggedUser, taskId, delegatedId, locale); } - @Authorizations(value = { - @Authorize(authority = "TASK_FINISH"), - @Authorize(expression = "@taskAuthorizationService.canCallFinish(#auth.getPrincipal(), #taskId)") - }) + @Authorize(authority = "TASK_FINISH") + @Authorize(expression = "@taskAuthorizationService.canCallFinish(#auth.getPrincipal(), #taskId)") @Operation(summary = "Finish task", description = "Caller must be assigned to the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -136,10 +129,8 @@ public EntityModel finish(Authentication auth, @PathVar return super.finish(loggedUser, taskId, locale); } - @Authorizations(value = { - @Authorize(authority = "TASK_CANCEL"), - @Authorize(expression = "@taskAuthorizationService.canCallCancel(#auth.getPrincipal(), #taskId)") - }) + @Authorize(authority = "TASK_CANCEL") + @Authorize(expression = "@taskAuthorizationService.canCallCancel(#auth.getPrincipal(), #taskId)") @Operation(summary = "Cancel task", description = "Caller must be assigned to the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -195,10 +186,8 @@ public EntityModel getData(@PathVariable("id") String t return super.getData(taskId, locale); } - @Authorizations(value = { - @Authorize(authority = "TASK_SAVE_DATA"), - @Authorize(expression = "@taskAuthorizationService.canCallSaveData(#auth.getPrincipal(), #taskId)") - }) + @Authorize(authority = "TASK_SAVE_DATA") + @Authorize(expression = "@taskAuthorizationService.canCallSaveData(#auth.getPrincipal(), #taskId)") @Operation(summary = "Set task data", description = "Caller must be assigned to the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -212,10 +201,8 @@ public EntityModel setData(Authentication auth, @PathVa return super.setData(taskId, dataBody, locale); } - @Authorizations(value = { - @Authorize(authority = "TASK_SAVE_DATA"), - @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") - }) + @Authorize(authority = "TASK_SAVE_DATA") + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") @Operation(summary = "Upload file into the task", description = "Caller must be assigned to the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -235,10 +222,8 @@ public ResponseEntity getFile(@PathVariable("id") String taskId, @Path return super.getFile(taskId, fieldId); } - @Authorizations(value = { - @Authorize(authority = "TASK_SAVE_DATA"), - @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") - }) + @Authorize(authority = "TASK_SAVE_DATA") + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") @Operation(summary = "Remove file from the task", description = "Caller must be assigned to the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -251,10 +236,8 @@ public EntityModel deleteFile(Authentication auth, @Pat return super.deleteFile(taskId, fieldId); } - @Authorizations(value = { - @Authorize(authority = "TASK_SAVE_DATA"), - @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") - }) + @Authorize(authority = "TASK_SAVE_DATA") + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") @Operation(summary = "Upload multiple files into the task", description = "Caller must be assigned to the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -275,10 +258,8 @@ public ResponseEntity getNamedFile(@PathVariable("id") String taskId, return super.getNamedFile(taskId, fieldId, name); } - @Authorizations(value = { - @Authorize(authority = "TASK_SAVE_DATA"), - @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") - }) + @Authorize(authority = "TASK_SAVE_DATA") + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(#auth.getPrincipal(), #taskId)") @Operation(summary = "Remove file from tasks file list field value", description = "Caller must be assigned to the task, or must be an ADMIN", security = {@SecurityRequirement(name = "BasicAuth")}) diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java index 9ee2be40c8..3709c8fc11 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java @@ -78,10 +78,8 @@ public class WorkflowController { private IDataService dataService; - @Authorizations(value = { - @Authorize(authority = "CASE_CREATE"), - @Authorize(expression = "@workflowAuthorizationService.canCallCreate(#auth.getPrincipal(), #body.netId)") - }) + @Authorize(authority = "CASE_CREATE") + @Authorize(expression = "@workflowAuthorizationService.canCallCreate(#auth.getPrincipal(), #body.netId)") @Operation(summary = "Create new case", security = {@SecurityRequirement(name = "BasicAuth")}) @PostMapping(value = "/case", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public EntityModel createCase(@RequestBody CreateCaseBody body, Authentication auth, Locale locale) { @@ -96,9 +94,7 @@ public EntityModel createCase(@RequestBody CreateCaseBo } } - @Authorizations(value = { - @Authorize(authority = "CASE_VIEW_ALL") - }) + @Authorize(authority = "CASE_VIEW_ALL") @Operation(summary = "Get all cases of the system", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/all", produces = MediaTypes.HAL_JSON_VALUE) public PagedModel getAll(Pageable pageable, PagedResourcesAssembler assembler) { @@ -174,9 +170,7 @@ public PagedModel findAllByAuthor(@PathVariable("id") String autho return resources; } - @Authorizations(value = { - @Authorize(authority = "TASK_RELOAD") - }) + @Authorize(authority = "TASK_RELOAD") @Operation(summary = "Reload tasks of case", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -187,7 +181,7 @@ public PagedModel findAllByAuthor(@PathVariable("id") String autho }) public MessageResource reloadTasks(@PathVariable("id") String caseId) { try { - caseId = URLDecoder.decode(caseId, StandardCharsets.UTF_8.name()); + caseId = URLDecoder.decode(caseId, StandardCharsets.UTF_8); Case aCase = workflowService.findOne(caseId); taskService.reloadTasks(aCase); @@ -199,42 +193,28 @@ public MessageResource reloadTasks(@PathVariable("id") String caseId) { } @Deprecated - @Authorizations(value = { - @Authorize(authority = "CASE_DATA_GET_ALL") - }) + @Authorize(authority = "CASE_DATA_GET_ALL") @Operation(summary = "Get all case data", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/case/{id}/data", produces = MediaTypes.HAL_JSON_VALUE) public DataFieldsResource getAllCaseData(@PathVariable("id") String caseId, Locale locale) { - try { - caseId = URLDecoder.decode(caseId, StandardCharsets.UTF_8.name()); - return new DataFieldsResource(workflowService.getData(caseId), locale); - } catch (UnsupportedEncodingException e) { - log.error("Getting all case data of [" + caseId + "] failed:", e); - return new DataFieldsResource(new ArrayList<>(), locale); - } + caseId = URLDecoder.decode(caseId, StandardCharsets.UTF_8); + return new DataFieldsResource(workflowService.getData(caseId), locale); } - @Authorizations(value = { - @Authorize(authority = "CASE_DELETE"), - @Authorize(expression = "@workflowAuthorizationService.canCallDelete(#auth.getPrincipal(), #caseId)") - }) + @Authorize(authority = "CASE_DELETE") + @Authorize(expression = "@workflowAuthorizationService.canCallDelete(#auth.getPrincipal(), #caseId)") @Operation(summary = "Delete case", security = {@SecurityRequirement(name = "BasicAuth")}) @DeleteMapping(value = "/case/{id}", produces = MediaTypes.HAL_JSON_VALUE) public EntityModel deleteCase(Authentication auth, @PathVariable("id") String caseId, @RequestParam(defaultValue = "false") boolean deleteSubtree) { - try { - caseId = URLDecoder.decode(caseId, StandardCharsets.UTF_8.name()); - DeleteCaseEventOutcome outcome; - if (deleteSubtree) { - outcome = workflowService.deleteSubtreeRootedAt(caseId); - } else { - outcome = workflowService.deleteCase(caseId); - } - return EventOutcomeWithMessageResource.successMessage("Case " + caseId + " was deleted", - LocalisedEventOutcomeFactory.from(outcome, LocaleContextHolder.getLocale())); - } catch (UnsupportedEncodingException e) { - log.error("Deleting case [" + caseId + "] failed:", e); - return EventOutcomeWithMessageResource.errorMessage("Deleting case " + caseId + " has failed!"); + caseId = URLDecoder.decode(caseId, StandardCharsets.UTF_8); + DeleteCaseEventOutcome outcome; + if (deleteSubtree) { + outcome = workflowService.deleteSubtreeRootedAt(caseId); + } else { + outcome = workflowService.deleteCase(caseId); } + return EventOutcomeWithMessageResource.successMessage("Case " + caseId + " was deleted", + LocalisedEventOutcomeFactory.from(outcome, LocaleContextHolder.getLocale())); } @Operation(summary = "Download case file field value", security = {@SecurityRequirement(name = "BasicAuth")}) From fc5349797533e9486bf9b2ec925dca909b847318 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 13 Sep 2022 12:52:50 +0200 Subject: [PATCH 58/68] [NAE-1617] Authority refactor - added cache for anonymous user authorities --- .../application/engine/auth/domain/AnonymousUser.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AnonymousUser.java b/src/main/java/com/netgrif/application/engine/auth/domain/AnonymousUser.java index e7f3c8db16..2c90a93038 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AnonymousUser.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AnonymousUser.java @@ -2,8 +2,11 @@ import lombok.Data; import org.bson.types.ObjectId; +import org.springframework.cache.annotation.Cacheable; import org.springframework.data.mongodb.core.mapping.Document; +import java.util.Set; + @Document @Data public class AnonymousUser extends User { @@ -20,6 +23,12 @@ public AnonymousUser(String email, String password, String name, String surname) super(email, password, name, surname); } + @Override + @Cacheable("authorities") + public Set getAuthorities() { + return super.getAuthorities(); + } + @Override public LoggedUser transformToLoggedUser() { LoggedUser loggedUser = new LoggedUser(this.get_id().toString(), this.getEmail(), this.getPassword(), this.getAuthorities()); From 7d779288040b7b984941a1612be4c077364485cd Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 13 Sep 2022 12:53:20 +0200 Subject: [PATCH 59/68] [NAE-1617] Authority refactor - removed AbstractBaseAuthorizationService --- .../AbstractBaseAuthorizationService.java | 26 ------------------- .../BaseAuthorizationServiceAspect.java | 23 ++++++++++++++-- 2 files changed, 21 insertions(+), 28 deletions(-) delete mode 100644 src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java deleted file mode 100644 index c1c53049f7..0000000000 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractBaseAuthorizationService.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.netgrif.application.engine.auth.service; - -import com.netgrif.application.engine.auth.service.interfaces.IBaseAuthorizationService; -import com.netgrif.application.engine.auth.service.interfaces.IUserService; -import org.springframework.security.core.GrantedAuthority; - -import java.util.Arrays; -import java.util.Set; -import java.util.stream.Collectors; - -public abstract class AbstractBaseAuthorizationService implements IBaseAuthorizationService { - - private final IUserService userService; - - public AbstractBaseAuthorizationService(IUserService userService) { - this.userService = userService; - } - - @Override - public final boolean hasAnyAuthority(String[] authorizingObject) { - if (authorizingObject == null || authorizingObject.length == 0) - return true; - Set loggedUserAuthorities = this.userService.getLoggedUser().getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet()); - return loggedUserAuthorities.containsAll(Arrays.asList(authorizingObject)); - } -} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java index 73157a36f8..83f29a978c 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java @@ -2,6 +2,7 @@ import com.netgrif.application.engine.auth.domain.Authorizations; import com.netgrif.application.engine.auth.domain.Authorize; +import com.netgrif.application.engine.auth.service.interfaces.IBaseAuthorizationService; import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.configuration.ApplicationContextProvider; import lombok.extern.slf4j.Slf4j; @@ -18,10 +19,13 @@ import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.expression.ExpressionUtils; +import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Service; import java.util.Arrays; import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; /** @@ -30,10 +34,12 @@ @Slf4j @Aspect @Service -public class BaseAuthorizationServiceAspect extends AbstractBaseAuthorizationService { +public class BaseAuthorizationServiceAspect implements IBaseAuthorizationService { + + private final IUserService userService; public BaseAuthorizationServiceAspect(@Autowired IUserService userService) { - super(userService); + this.userService = userService; } /** @@ -68,6 +74,19 @@ protected Object authorize(ProceedingJoinPoint joinPoint, Authorizations authori } } + /** + * Checks whether the currently logged user has all the input authorizing objects. + * @param authorizingObject to be checked for user + * @return boolean if user has all the authorizing objects. + * */ + @Override + public final boolean hasAnyAuthority(String[] authorizingObject) { + if (authorizingObject == null || authorizingObject.length == 0) + return true; + Set loggedUserAuthorities = this.userService.getLoggedUser().getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet()); + return loggedUserAuthorities.containsAll(Arrays.asList(authorizingObject)); + } + /** * Parser and evaluator function for Spring-EL expression. It creates parser for SpEL expression, context for it, * and evaluates the authorization SpEL expression. It resolves the arguments of invoked method and sets as From 6ad92168fde0ef3fc63b8d8468cb8581433b5bd2 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 13 Sep 2022 12:54:15 +0200 Subject: [PATCH 60/68] [NAE-1617] Authority refactor - added final keywords to BaseAuthorizationServiceAspect --- .../engine/auth/service/BaseAuthorizationServiceAspect.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java index 83f29a978c..40c8fe07e6 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java @@ -48,7 +48,7 @@ public BaseAuthorizationServiceAspect(@Autowired IUserService userService) { * @param authorizations the annotation with authorization requirements * */ @Pointcut(value = "@annotation(authorizations))") - protected void authorizingMethod(Authorizations authorizations) {} + protected final void authorizingMethod(Authorizations authorizations) {} /** @@ -58,7 +58,7 @@ protected void authorizingMethod(Authorizations authorizations) {} * @param authorizations the incoming annotation with authorization parameters * */ @Around(value = "authorizingMethod(authorizations)", argNames = "joinPoint,authorizations") - protected Object authorize(ProceedingJoinPoint joinPoint, Authorizations authorizations) throws Throwable { + protected final Object authorize(ProceedingJoinPoint joinPoint, Authorizations authorizations) throws Throwable { boolean result = false; if (authorizations.value() != null && authorizations.value().length > 0) { From 0420715f1b4cebc04a7d15e53f874e0d4a6659f8 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 13 Sep 2022 13:23:41 +0200 Subject: [PATCH 61/68] [NAE-1617] Authority refactor - created additional endpoints for AuthorityController - modified controllers according to IDEA suggestion --- .../engine/auth/web/AuthorityController.java | 31 +++++++++++++++++++ .../web/responsebodies/AuthorityResource.java | 8 +++++ .../petrinet/web/PetriNetController.java | 4 +-- .../PetriNetReferenceResource.java | 2 +- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java index 6e4be3e095..f0a299ba25 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java @@ -4,6 +4,7 @@ import com.netgrif.application.engine.auth.domain.Authorize; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.auth.web.requestbodies.NewAuthorityRequest; +import com.netgrif.application.engine.auth.web.responsebodies.AuthoritiesResources; import com.netgrif.application.engine.auth.web.responsebodies.AuthorityResource; import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; import com.netgrif.application.engine.workflow.web.responsebodies.ResponseMessage; @@ -14,11 +15,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.data.rest.webmvc.ResourceNotFoundException; +import org.springframework.hateoas.CollectionModel; import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; +import java.util.Optional; + @Slf4j @RestController @RequestMapping("/api/authority") @@ -60,4 +64,31 @@ public EntityModel create(@RequestBody NewAuthorityRequest request) { return null; } } + + @Authorize(authority = "AUTHORITY_GET_ALL") + @Operation(description = "Delete authority", security = {@SecurityRequirement(name = "BasicAuth")}) + @GetMapping(value = "/all", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) + public CollectionModel getAll() { + return new AuthoritiesResources(authorityService.findAll()); + } + + @Authorize(authority = "AUTHORITY_CREATE") + @Operation(description = "Delete authority", security = {@SecurityRequirement(name = "BasicAuth")}) + @GetMapping(value = "/{name}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) + public EntityModel getOne(@PathVariable("name") String name) { + Optional authority = authorityService.findById(name); + if (authority.isPresent()) { + return AuthorityResource.of(authority.get()); + } else { + log.error("Cannot find authority with name [" + name + "]."); + return null; + } + } + + @Authorize(authority = "AUTHORITY_CREATE") + @Operation(description = "Delete authority", security = {@SecurityRequirement(name = "BasicAuth")}) + @GetMapping(value = "/scope/{scope}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) + public CollectionModel getAllByScope(@PathVariable("scope") String scope) { + return new AuthoritiesResources(authorityService.findByScope(scope)); + } } diff --git a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthorityResource.java b/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthorityResource.java index 5e81f69ee4..ecffe233da 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthorityResource.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthorityResource.java @@ -1,7 +1,9 @@ package com.netgrif.application.engine.auth.web.responsebodies; import com.netgrif.application.engine.auth.domain.Authority; +import com.netgrif.application.engine.auth.web.AuthorityController; import org.springframework.hateoas.EntityModel; +import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; import java.util.ArrayList; @@ -9,5 +11,11 @@ public class AuthorityResource extends EntityModel { public AuthorityResource(Authority content) { super(content, new ArrayList<>()); + buildLinks(); + } + + private void buildLinks() { + add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder + .methodOn(AuthorityController.class).getAll()).withRel("getAll")); } } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index d323c6181f..fd98539196 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -12,7 +12,6 @@ import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.petrinet.service.interfaces.IProcessRoleService; import com.netgrif.application.engine.petrinet.web.responsebodies.*; -import com.netgrif.application.engine.workflow.domain.FileStorageConfiguration; import com.netgrif.application.engine.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessage; import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessageResource; @@ -43,7 +42,6 @@ import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.*; @@ -113,7 +111,7 @@ public PetriNetReferenceResources getAll(@RequestParam(value = "indentifier", re @Operation(summary = "Get process by id", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/{id}", produces = MediaTypes.HAL_JSON_VALUE) - public PetriNetReferenceResource getOne(@PathVariable("id") String id, Authentication auth, Locale locale) { + public PetriNetReferenceResource getOne(@PathVariable("id") String id, Locale locale) { return new PetriNetReferenceResource(IPetriNetService.transformToReference(service.getPetriNet(decodeUrl(id)), locale)); } diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceResource.java b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceResource.java index 830a85c538..315e222f83 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceResource.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/responsebodies/PetriNetReferenceResource.java @@ -13,7 +13,7 @@ public PetriNetReferenceResource(PetriNetReference content) { private void buildLinks() { add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder - .methodOn(PetriNetController.class).getOne(getContent().getStringId(), null, null)) + .methodOn(PetriNetController.class).getOne(getContent().getStringId(), null)) .withSelfRel()); add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder From 62a86001951032b711f30bd58c9822354e604313 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 13 Sep 2022 13:24:59 +0200 Subject: [PATCH 62/68] [NAE-1617] Authority refactor - modified authority id --- .../application/engine/auth/domain/Authority.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java index 5d048abbc6..13769c6bea 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java @@ -3,7 +3,6 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import lombok.Getter; import lombok.Setter; -import org.bson.types.ObjectId; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.security.core.GrantedAuthority; @@ -21,13 +20,9 @@ public class Authority implements GrantedAuthority { public static final List defaultAnonymousAuthorities = Collections.emptyList(); @Id - @Getter - private ObjectId _id; - @NotNull @JsonIgnore @Getter - @Setter private String name; @JsonIgnore @@ -57,7 +52,7 @@ public void removeUser(IUser user) { } public String getStringId() { - return _id.toString(); + return name; } @Override @@ -82,7 +77,7 @@ public boolean equals(Object o) { @Override public String toString() { return "Authority{" + - "id=" + _id + + "id=" + name + ", name='" + name + '\'' + '}'; } From 74e35cf50aa0d68907340e0bb5f138e24fa03438 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 13 Sep 2022 13:39:45 +0200 Subject: [PATCH 63/68] [NAE-1617] Authority refactor - refactored MY keyword in AuthorizingObject to SELF and OWN --- .../engine/auth/domain/AuthorizingObject.java | 24 +++++++++---------- .../engine/action/AssignActionTest.groovy | 3 +-- .../FilterAuthorizationServiceTest.groovy | 2 +- .../groups/GroupControllerTest.groovy | 4 ++-- .../web/PetriNetControllerTest.groovy | 2 +- 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java index fe863b768f..f4a8bb089e 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java @@ -13,36 +13,36 @@ public enum AuthorizingObject { DEFAULT, PROCESS_UPLOAD, PROCESS_VIEW_ALL, - PROCESS_VIEW_MY, + PROCESS_VIEW_OWN, PROCESS_DELETE_ALL, - PROCESS_DELETE_MY, + PROCESS_DELETE_OWN, FILTER_UPLOAD, FILTER_DELETE_ALL, - FILTER_DELETE_MY, + FILTER_DELETE_OWN, USER_CREATE, USER_DELETE_ALL, - USER_DELETE_MY, + USER_DELETE_SELF, USER_EDIT_ALL, - USER_EDIT_MY, + USER_EDIT_SELF, USER_VIEW_ALL, - USER_VIEW_MY, + USER_VIEW_SELF, GROUP_CREATE, - GROUP_DELETE_MY, + GROUP_DELETE_SELF, GROUP_DELETE_ALL, GROUP_ALL_ADD_USER, - GROUP_MY_ADD_USER, + GROUP_OWN_ADD_USER, GROUP_ALL_REMOVE_USER, - GROUP_MY_REMOVE_USER, + GROUP_OWN_REMOVE_USER, GROUP_VIEW_ALL, - GROUP_VIEW_MY, - GROUP_MEMBERSHIP_MY, + GROUP_VIEW_OWN, + GROUP_MEMBERSHIP_SELF, ROLE_ASSIGN_TO_USER, ROLE_REMOVE_FROM_USER, AUTHORITY_CREATE, AUTHORITY_DELETE, AUTHORITY_VIEW_ALL, CASE_VIEW_ALL, - CASE_VIEW_MY, + CASE_VIEW_OWN, CASE_CREATE, CASE_DELETE, CASE_DATA_GET_ALL, diff --git a/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy index afea3a11f9..311dc185be 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/AssignActionTest.groovy @@ -39,7 +39,6 @@ import org.springframework.web.context.WebApplicationContext import java.util.stream.Collectors import java.util.stream.Stream -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication import static org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity @ExtendWith(SpringExtension.class) @@ -98,7 +97,7 @@ class AssignActionTest { createMainAndSecondaryNet() def auths = importHelper.createAuthorities(["user": [AuthorizingObject.FILTER_UPLOAD.name(), - AuthorizingObject.FILTER_DELETE_MY.name()], "admin": AuthorizingObject.stringValues()]) + AuthorizingObject.FILTER_DELETE_OWN.name()], "admin": AuthorizingObject.stringValues()]) def authorityList = Stream.concat(auths.get("user").stream(), auths.get("admin").stream()).collect(Collectors.toList()).toArray() importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), diff --git a/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy index c43bb0b75c..1b9079f039 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/auth/FilterAuthorizationServiceTest.groovy @@ -74,7 +74,7 @@ class FilterAuthorizationServiceTest { .build() def auths = importHelper.createAuthorities(["user": [AuthorizingObject.FILTER_UPLOAD.name(), - AuthorizingObject.FILTER_DELETE_MY.name()], "admin": AuthorizingObject.stringValues()]) + AuthorizingObject.FILTER_DELETE_OWN.name()], "admin": AuthorizingObject.stringValues()]) importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/GroupControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/GroupControllerTest.groovy index c556f5de60..3dfa3e5f86 100644 --- a/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/GroupControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/GroupControllerTest.groovy @@ -63,8 +63,8 @@ class GroupControllerTest { .build() def auths = importHelper.createAuthorities(["user": [ - AuthorizingObject.GROUP_VIEW_MY.name(), - AuthorizingObject.GROUP_MEMBERSHIP_MY.name() + AuthorizingObject.GROUP_VIEW_OWN.name(), + AuthorizingObject.GROUP_MEMBERSHIP_SELF.name() ]]) importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy index 84176ac134..c37dde3e4a 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy @@ -90,7 +90,7 @@ class PetriNetControllerTest { def auths = importHelper.createAuthorities(["user": [AuthorizingObject.FILTER_UPLOAD.name(), - AuthorizingObject.FILTER_DELETE_MY.name(), AuthorizingObject.PROCESS_DELETE_MY.name(), AuthorizingObject.PROCESS_VIEW_MY.name()], + AuthorizingObject.FILTER_DELETE_OWN.name(), AuthorizingObject.PROCESS_DELETE_OWN.name(), AuthorizingObject.PROCESS_VIEW_OWN.name()], "admin": AuthorizingObject.stringValues()]) IUser basicUser = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), From 5f26dc4d9d77c3146ae9c1ef8d1f514cd433cd4a Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Wed, 14 Sep 2022 09:59:59 +0200 Subject: [PATCH 64/68] [NAE-1617] Authority refactor - corrected code according to tests - updated naming convention in tests - updated Aspect according to tests --- .../logic/action/ActionDelegate.groovy | 4 +-- .../engine/auth/domain/AbstractUser.java | 4 +-- .../engine/auth/domain/Authority.java | 3 +- .../engine/auth/domain/Authorizations.java | 2 -- .../engine/auth/domain/Authorize.java | 2 -- .../engine/auth/domain/AuthorizingObject.java | 2 +- .../repositories/AuthorityRepository.java | 3 -- .../engine/auth/service/AuthorityService.java | 2 +- .../BaseAuthorizationServiceAspect.java | 34 +++++++++++-------- .../engine/auth/web/AuthorityController.java | 15 ++++---- .../engine/auth/web/UserController.java | 20 +++-------- .../web/responsebodies/AuthorityResource.java | 2 +- .../orgstructure/web/GroupController.java | 4 +-- .../petrinet/web/PetriNetController.java | 4 +-- .../engine/workflow/web/FilterController.java | 2 +- .../workflow/web/PublicTaskController.java | 24 ++++--------- .../engine/action/ActionDelegateTest.groovy | 30 ++++++++++++++++ .../engine/auth/AuthorityTest.groovy | 6 ++++ .../service/CachePetriNetServiceTest.groovy | 4 +-- .../web/PetriNetControllerTest.groovy | 3 +- 20 files changed, 93 insertions(+), 77 deletions(-) diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy index 0986466416..ede8d39852 100644 --- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy @@ -1256,7 +1256,7 @@ class ActionDelegate { } @Authorizations(value = [ - @Authorize(authority = "USER_DELETE") + @Authorize(authority = "USER_DELETE_ALL") ]) void deleteUser(String email) { IUser user = userService.findByEmail(email, false) @@ -1266,7 +1266,7 @@ class ActionDelegate { } @Authorizations(value = [ - @Authorize(authority = "USER_DELETE") + @Authorize(authority = "USER_DELETE_ALL") ]) void deleteUser(IUser user) { List tasks = taskService.findByUser(new FullPageRequest(), user).toList() diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AbstractUser.java b/src/main/java/com/netgrif/application/engine/auth/domain/AbstractUser.java index 1e29a9fbe1..c9b1242e5e 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AbstractUser.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AbstractUser.java @@ -34,13 +34,13 @@ public AbstractUser() { } public void addAuthority(Authority authority) { - if (authorities.stream().anyMatch(it -> it.get_id().equals(authority.get_id()))) + if (authorities.stream().anyMatch(it -> it.getName().equals(authority.getName()))) return; authorities.add(authority); } public void removeAuthority(Authority authority) { - if (authorities.stream().noneMatch(it -> it.get_id().equals(authority.get_id()))) + if (authorities.stream().noneMatch(it -> it.getName().equals(authority.getName()))) return; authorities.remove(authority); } diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java index 13769c6bea..0ecdf1d2e8 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java @@ -16,7 +16,8 @@ public class Authority implements GrantedAuthority { public static final long serialVersionUID = 2839744057647464485L; public static final String defaultAdminAuthority = "*"; - public static final List defaultUserAuthorities = Arrays.asList("FILTER_*", "GROUP_VIEW_MY"); + public static final List defaultUserAuthorities = Arrays.asList("FILTER_*", + AuthorizingObject.GROUP_VIEW_OWN.name()); public static final List defaultAnonymousAuthorities = Collections.emptyList(); @Id diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authorizations.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authorizations.java index 7fb58a2771..2574b40a17 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authorizations.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authorizations.java @@ -7,8 +7,6 @@ * */ @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD, ElementType.TYPE }) -@Inherited -@Documented public @interface Authorizations { /** diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java index 38a0f91f10..cb5fe090f8 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authorize.java @@ -10,8 +10,6 @@ @Repeatable(Authorizations.class) @Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.METHOD, ElementType.TYPE }) -@Inherited -@Documented public @interface Authorize { /** diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java index f4a8bb089e..e2609a7fb9 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java @@ -40,7 +40,7 @@ public enum AuthorizingObject { ROLE_REMOVE_FROM_USER, AUTHORITY_CREATE, AUTHORITY_DELETE, - AUTHORITY_VIEW_ALL, + AUTHORITY_VIEW, CASE_VIEW_ALL, CASE_VIEW_OWN, CASE_CREATE, diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/repositories/AuthorityRepository.java b/src/main/java/com/netgrif/application/engine/auth/domain/repositories/AuthorityRepository.java index 3482dc3ea3..86dfd45a37 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/repositories/AuthorityRepository.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/repositories/AuthorityRepository.java @@ -12,8 +12,5 @@ public interface AuthorityRepository extends MongoRepository, QuerydslPredicateExecutor { Authority findByName(String name); - - Authority findBy_id(ObjectId id); - List findAllByNameStartsWith(String prefix); } diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index c9537ba0ff..81ad550b04 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -139,7 +139,7 @@ public Authority findByName(String name) { * */ @Override public Optional findById(String id) { - return Optional.of(repository.findBy_id(new ObjectId(id))); + return Optional.of(repository.findByName(id)); } /** diff --git a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java index 40c8fe07e6..72feb203a0 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/BaseAuthorizationServiceAspect.java @@ -43,30 +43,36 @@ public BaseAuthorizationServiceAspect(@Autowired IUserService userService) { } /** - * Pointcut definition for {@link Authorizations} annotation to connect authorization requests from join points to the - * {@link #authorize(ProceedingJoinPoint, Authorizations)} advice. - * @param authorizations the annotation with authorization requirements - * */ - @Pointcut(value = "@annotation(authorizations))") - protected final void authorizingMethod(Authorizations authorizations) {} - - - /** - * The advice that handles incoming authorization requests from join points from - * {@link #authorizingMethod(Authorizations)} pointcuts + * The advice that handles incoming authorization requests from join points defined with @annotation(authorization) * @param joinPoint the incoming method invocation join point * @param authorizations the incoming annotation with authorization parameters * */ - @Around(value = "authorizingMethod(authorizations)", argNames = "joinPoint,authorizations") + @Around(value = "@annotation(authorizations)", argNames = "joinPoint,authorizations") protected final Object authorize(ProceedingJoinPoint joinPoint, Authorizations authorizations) throws Throwable { boolean result = false; - if (authorizations.value() != null && authorizations.value().length > 0) { for (Authorize authorize : authorizations.value()) { result = result || (isAllowedByExpression(joinPoint, authorize.expression()) && hasAnyAuthority(authorize.authority())); } } + if (result) { + return joinPoint.proceed(); + } else { + throw new AccessDeniedException("Access Denied. User does not have required authorization level."); + } + } + /** + * The advice that handles incoming authorization requests from join points defined with @annotation(authorization) + * @param joinPoint the incoming method invocation join point + * @param authorize the incoming annotation with authorization parameter + * */ + @Around(value = "@annotation(authorize)", argNames = "joinPoint,authorize") + protected final Object authorize(ProceedingJoinPoint joinPoint, Authorize authorize) throws Throwable { + boolean result = false; + if (authorize != null) { + result = isAllowedByExpression(joinPoint, authorize.expression()) && hasAnyAuthority(authorize.authority()); + } if (result) { return joinPoint.proceed(); } else { @@ -81,7 +87,7 @@ protected final Object authorize(ProceedingJoinPoint joinPoint, Authorizations a * */ @Override public final boolean hasAnyAuthority(String[] authorizingObject) { - if (authorizingObject == null || authorizingObject.length == 0) + if (authorizingObject == null || authorizingObject.length == 0 || Arrays.stream(authorizingObject).allMatch(s -> s.length() == 0)) return true; Set loggedUserAuthorities = this.userService.getLoggedUser().getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet()); return loggedUserAuthorities.containsAll(Arrays.asList(authorizingObject)); diff --git a/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java index f0a299ba25..aed211bcf7 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java @@ -19,6 +19,7 @@ import org.springframework.hateoas.EntityModel; import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; +import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; import java.util.Optional; @@ -40,7 +41,7 @@ public class AuthorityController { @Authorize(authority = "AUTHORITY_DELETE") @Operation(description = "Delete authority", security = {@SecurityRequirement(name = "BasicAuth")}) @DeleteMapping(value = "/delete/{name}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public MessageResource delete(@PathVariable String name) { + public MessageResource delete(@PathVariable String name, Authentication auth) { try { authorityService.delete(name); log.info("Authority [" + name + "] has been deleted successfully."); @@ -54,7 +55,7 @@ public MessageResource delete(@PathVariable String name) { @Authorize(authority = "AUTHORITY_CREATE") @Operation(description = "Delete authority", security = {@SecurityRequirement(name = "BasicAuth")}) @PostMapping(value = "/create", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public EntityModel create(@RequestBody NewAuthorityRequest request) { + public EntityModel create(@RequestBody NewAuthorityRequest request, Authentication auth) { try { Authority authority = authorityService.getOrCreate(request.name); log.info("Authority [" + authority + "] has been created successfully."); @@ -68,14 +69,14 @@ public EntityModel create(@RequestBody NewAuthorityRequest request) { @Authorize(authority = "AUTHORITY_GET_ALL") @Operation(description = "Delete authority", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/all", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public CollectionModel getAll() { + public CollectionModel getAll(Authentication auth) { return new AuthoritiesResources(authorityService.findAll()); } - @Authorize(authority = "AUTHORITY_CREATE") + @Authorize(authority = "AUTHORITY_VIEW") @Operation(description = "Delete authority", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/{name}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public EntityModel getOne(@PathVariable("name") String name) { + public EntityModel getOne(@PathVariable("name") String name, Authentication auth) { Optional authority = authorityService.findById(name); if (authority.isPresent()) { return AuthorityResource.of(authority.get()); @@ -85,10 +86,10 @@ public EntityModel getOne(@PathVariable("name") String name) { } } - @Authorize(authority = "AUTHORITY_CREATE") + @Authorize(authority = "AUTHORITY_VIEW") @Operation(description = "Delete authority", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/scope/{scope}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public CollectionModel getAllByScope(@PathVariable("scope") String scope) { + public CollectionModel getAllByScope(@PathVariable("scope") String scope, Authentication auth) { return new AuthoritiesResources(authorityService.findByScope(scope)); } } diff --git a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java index a193daf775..597246b354 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java @@ -91,9 +91,7 @@ protected UserResourceAssembler getUserResourceAssembler(Locale locale, boolean return result; } - @Authorizations(value = { - @Authorize(authority = "USER_VIEW_ALL") - }) + @Authorize(authority = "USER_VIEW_ALL") @Operation(summary = "Get all users", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(produces = MediaTypes.HAL_JSON_VALUE) public PagedModel getAll(@RequestParam(value = "small", required = false) Boolean small, Pageable pageable, PagedResourcesAssembler assembler, Authentication auth, Locale locale) { @@ -179,9 +177,7 @@ public PagedModel getAllWithRole(@RequestBody Set roleIds, return resources; } - @Authorizations(value = { - @Authorize(authority = "USER_EDIT_ALL", expression = "@userService.isLogged(#userId)") - }) + @Authorize(authority = "USER_EDIT_ALL", expression = "@userService.isLogged(#userId)") @Operation(summary = "Assign role to the user", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) @PostMapping(value = "/{id}/role/assign", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) @ApiResponses(value = { @@ -199,9 +195,7 @@ public MessageResource assignRolesToUser(@PathVariable("id") String userId, @Req } } - @Authorizations(value = { - @Authorize(authority = "AUTHORITY_VIEW_ALL") - }) + @Authorize(authority = "AUTHORITY_VIEW_ALL") @Operation(summary = "Get all authorities of the system", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -214,9 +208,7 @@ public AuthoritiesResources getAllAuthorities() { return new AuthoritiesResources(authorityService.findAll()); } - @Authorizations(value = { - @Authorize(authority = "USER_EDIT_ALL") - }) + @Authorize(authority = "USER_EDIT_ALL") @Operation(summary = "Assign authority to the user", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -243,9 +235,7 @@ public PreferencesResource preferences(Authentication auth) { return new PreferencesResource(preferences); } - @Authorizations(value = { - @Authorize(authority = "USER_EDIT_ALL") - }) + @Authorize(authority = "USER_EDIT_ALL") @Operation(summary = "Assign authority to the user", description = "Caller must have the USER_EDIT authority", security = {@SecurityRequirement(name = "BasicAuth")}) diff --git a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthorityResource.java b/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthorityResource.java index ecffe233da..a8263f7ea7 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthorityResource.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/responsebodies/AuthorityResource.java @@ -16,6 +16,6 @@ public AuthorityResource(Authority content) { private void buildLinks() { add(WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder - .methodOn(AuthorityController.class).getAll()).withRel("getAll")); + .methodOn(AuthorityController.class).getAll(null)).withRel("getAll")); } } diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java index 75ae5ecc1c..10225f0d02 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java @@ -55,7 +55,7 @@ public GroupsResource getAllGroups() { return new GroupsResource(groupResponse); } - @Authorize(authority = "GROUP_VIEW_MY") + @Authorize(authority = "GROUP_VIEW_OWN") @Operation(summary = "Get logged user's groups in the system", description = "Caller must have the GROUP_VIEW_MY authority", security = {@SecurityRequirement(name = "BasicAuth")}) @@ -74,7 +74,7 @@ public GroupsResource getMyGroups(Authentication auth) { return new GroupsResource(groupResponse); } - @Authorize(authority = "GROUP_MEMBERSHIP_MY") + @Authorize(authority = "GROUP_MEMBERSHIP_SELF") @Operation(summary = "Get logged user's groups in the system", description = "Caller must have the GROUP_VIEW_MY authority", security = {@SecurityRequirement(name = "BasicAuth")}) diff --git a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index fd98539196..06c5d0bbc6 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -115,7 +115,7 @@ public PetriNetReferenceResource getOne(@PathVariable("id") String id, Locale lo return new PetriNetReferenceResource(IPetriNetService.transformToReference(service.getPetriNet(decodeUrl(id)), locale)); } - @Authorize(authority = "PROCESS_VIEW_MY") + @Authorize(authority = "PROCESS_VIEW_OWN") @Operation(description = "Get all processes", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/my", produces = MediaTypes.HAL_JSON_VALUE) public PetriNetReferenceResources getMy(@RequestParam(value = "indentifier", required = false) String identifier, @RequestParam(value = "version", required = false) String version, Authentication auth, Locale locale) { @@ -217,7 +217,7 @@ public MessageResource deletePetriNet(@PathVariable("id") String processId, Auth return MessageResource.successMessage("Petri net " + decodedProcessId + " was deleted"); } - @Authorize(authority = "PROCESS_DELETE_MY") + @Authorize(authority = "PROCESS_DELETE_OWN") @Operation(summary = "Delete process", description = "Caller must have the ADMIN role. Removes the specified process, along with it's cases, tasks and process roles.", security = {@SecurityRequirement(name = "BasicAuth")}) diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/FilterController.java b/src/main/java/com/netgrif/application/engine/workflow/web/FilterController.java index 633cc5f481..12da4ca0b5 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/FilterController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/FilterController.java @@ -58,7 +58,7 @@ public MessageResource createFilter(@RequestBody CreateFilterBody newFilter, @Re @Operation(summary = "Delete filter specified by id", security = {@SecurityRequirement(name = "BasicAuth")}) @DeleteMapping(value = "/{id}", produces = MediaTypes.HAL_JSON_VALUE) @Authorize(authority = "FILTER_DELETE_ALL") - @Authorize(authority = "FILTER_DELETE_MY") + @Authorize(authority = "FILTER_DELETE_OWN") public MessageResource deleteFilter(@PathVariable("id") String filterId, Authentication auth) throws UnauthorisedRequestException { LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); boolean success = filterService.deleteFilter(filterId, loggedUser); diff --git a/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java b/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java index 62ce393fab..604fb34fe7 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java +++ b/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java @@ -62,9 +62,7 @@ public List getTasksOfCase(@PathVariable("id") String caseId, Loc return this.taskService.findAllByCase(caseId, locale); } - @Authorizations(value = { - @Authorize(expression = "@taskAuthorizationService.canCallAssign(@userService.getAnonymousLogged(), #taskId)") - }) + @Authorize(expression = "@taskAuthorizationService.canCallAssign(@userService.getAnonymousLogged(), #taskId)") @GetMapping(value = "/assign/{id}", produces = MediaTypes.HAL_JSON_VALUE) @Operation(summary = "Assign task", description = "Caller must be able to perform the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -79,9 +77,7 @@ public EntityModel assign(@PathVariable("id") String ta return super.assign(loggedUser, taskId, locale); } - @Authorizations(value = { - @Authorize(expression = "@taskAuthorizationService.canCallFinish(@userService.getAnonymousLogged(), #taskId)") - }) + @Authorize(expression = "@taskAuthorizationService.canCallFinish(@userService.getAnonymousLogged(), #taskId)") @GetMapping(value = "/finish/{id}", produces = MediaTypes.HAL_JSON_VALUE) @Operation(summary = "Finish task", description = "Caller must be assigned to the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -96,9 +92,7 @@ public EntityModel finish(@PathVariable("id") String ta return super.finish(loggedUser, taskId, locale); } - @Authorizations(value = { - @Authorize(expression = "@taskAuthorizationService.canCallCancel(@userService.getAnonymousLogged(), #taskId)") - }) + @Authorize(expression = "@taskAuthorizationService.canCallCancel(@userService.getAnonymousLogged(), #taskId)") @GetMapping(value = "/cancel/{id}", produces = MediaTypes.HAL_JSON_VALUE) @Operation(summary = "Cancel task", description = "Caller must be assigned to the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -119,9 +113,7 @@ public EntityModel getData(@PathVariable("id") String t return super.getData(taskId, locale); } - @Authorizations(value = { - @Authorize(expression = "@taskAuthorizationService.canCallSaveData(@userService.getAnonymousLogged(), #taskId)") - }) + @Authorize(expression = "@taskAuthorizationService.canCallSaveData(@userService.getAnonymousLogged(), #taskId)") @PostMapping(value = "/{id}/data", consumes = "application/json;charset=UTF-8", produces = "application/json;charset=UTF-8") @Operation(summary = "Set task data", description = "Caller must be assigned to the task, or must be an ADMIN") @ApiResponses({@ApiResponse( @@ -135,9 +127,7 @@ public EntityModel setData(@PathVariable("id") String t return super.setData(taskId, dataBody, locale); } - @Authorizations(value = { - @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") - }) + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") @Operation(summary = "Upload file into the task", description = "Caller must be assigned to the task, or must be an ADMIN") @PostMapping(value = "/{id}/file/{field}", produces = MediaTypes.HAL_JSON_VALUE) @@ -173,9 +163,7 @@ public ResponseEntity getFilePreview(@PathVariable("id") String taskId return super.getFilePreview(taskId, fieldId); } - @Authorizations(value = { - @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") - }) + @Authorize(expression = "@taskAuthorizationService.canCallSaveFile(@userService.getAnonymousLogged(), #taskId)") @Operation(summary = "Upload multiple files into the task", description = "Caller must be assigned to the task, or must be an ADMIN") @PostMapping(value = "/{id}/files/{field}", produces = MediaTypes.HAL_JSON_VALUE) diff --git a/src/test/groovy/com/netgrif/application/engine/action/ActionDelegateTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/ActionDelegateTest.groovy index 4a8b5f61a1..eb87dbe709 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/ActionDelegateTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/ActionDelegateTest.groovy @@ -3,10 +3,18 @@ package com.netgrif.application.engine.action import com.icegreen.greenmail.util.GreenMail import com.icegreen.greenmail.util.ServerSetup import com.netgrif.application.engine.TestHelper +import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.IUser +import com.netgrif.application.engine.auth.domain.LoggedUser +import com.netgrif.application.engine.auth.domain.User +import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.auth.service.interfaces.IUserService import com.netgrif.application.engine.auth.web.requestbodies.NewUserRequest import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.ActionDelegate +import com.netgrif.application.engine.petrinet.domain.roles.ProcessRole +import com.netgrif.application.engine.security.service.SecurityContextService +import com.netgrif.application.engine.startup.ImportHelper import com.netgrif.application.engine.workflow.service.interfaces.IFilterImportExportService import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource import org.junit.jupiter.api.BeforeEach @@ -15,6 +23,11 @@ import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest +import org.springframework.mock.web.MockHttpServletRequest +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken +import org.springframework.security.core.Authentication +import org.springframework.security.core.context.SecurityContextHolder +import org.springframework.security.web.authentication.WebAuthenticationDetails import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension @@ -37,9 +50,26 @@ class ActionDelegateTest { @Autowired private IUserService userService + @Autowired + private ImportHelper importHelper + + Authentication authentication + + private static final String ADMIN_EMAIL = "super@netgrif.com" + private static final String ADMIN_PASSWORD = "password" + @BeforeEach void before() { testHelper.truncateDbs() + Map> auths = importHelper.createAuthorities(["admin": AuthorizingObject.stringValues()]) + List adminAuths = auths.get("admin") + IUser user = userService.findByEmail(ADMIN_EMAIL, false) + user.setAuthorities(adminAuths.toSet()) + user = userService.save(user) + authentication = new UsernamePasswordAuthenticationToken(user.transformToLoggedUser(), ADMIN_PASSWORD, + adminAuths) + authentication.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) + SecurityContextHolder.getContext().setAuthentication(authentication) } @Test diff --git a/src/test/groovy/com/netgrif/application/engine/auth/AuthorityTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/AuthorityTest.groovy index b0ef284444..246b6325a8 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/AuthorityTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/auth/AuthorityTest.groovy @@ -18,9 +18,11 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.context.SpringBootTest import org.springframework.hateoas.MediaTypes import org.springframework.http.MediaType +import org.springframework.mock.web.MockHttpServletRequest import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.core.Authentication import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors +import org.springframework.security.web.authentication.WebAuthenticationDetails import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension import org.springframework.test.web.servlet.MockMvc @@ -90,6 +92,7 @@ class AuthorityTest { @Test void testCreateAuthority() { authentication = new UsernamePasswordAuthenticationToken(USER_EMAIL, USER_PASSWORD) + authentication.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) def content = JsonOutput.toJson(["name": "TEST_AUTHORITY"]) @@ -114,6 +117,7 @@ class AuthorityTest { assert a != null authentication = new UsernamePasswordAuthenticationToken(USER_EMAIL, USER_PASSWORD) + authentication.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) mvc.perform(MockMvcRequestBuilders.delete(AUTHORITY_DELETE_API.replace("{name}", "TEST_AUTHORITY")) .accept(MediaTypes.HAL_JSON_VALUE) @@ -133,6 +137,7 @@ class AuthorityTest { @Test void testAssignAuthorityToUser() { authentication = new UsernamePasswordAuthenticationToken(ADMIN_EMAIL, ADMIN_PASSWORD) + authentication.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) IUser user = userService.findByEmail(USER_EMAIL, false) Authority testAuthority = authorityService.getOrCreate("CREATED_AUTHORITY") @@ -156,6 +161,7 @@ class AuthorityTest { @Test void testRemoveAuthorityFromUser() { authentication = new UsernamePasswordAuthenticationToken(ADMIN_EMAIL, ADMIN_PASSWORD) + authentication.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) IUser user = userService.findByEmail(USER_EMAIL, false) Authority testAuthority = authorityService.getOrCreate("TEST_AUTHORITY") diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy index 9c41466129..5de7cb9fa9 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy @@ -59,9 +59,9 @@ class CachePetriNetServiceTest { @BeforeEach void setup() { testHelper.truncateDbs() - def auths = importHelper.createAuthorities(["user": Authority.user, "admin": Authority.admin]) + def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) importHelper.createUser(new User(name: "Customer", surname: "User", email: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), - [auths.get("user")] as Authority[], + auths.get("user").toArray() as Authority[], [] as ProcessRole[]) } diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy index c37dde3e4a..35a5c2e91e 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/web/PetriNetControllerTest.groovy @@ -21,6 +21,7 @@ import org.springframework.boot.test.context.SpringBootTest import org.springframework.mock.web.MockHttpServletRequest import org.springframework.security.authentication.UsernamePasswordAuthenticationToken import org.springframework.security.core.Authentication +import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors import org.springframework.security.web.authentication.WebAuthenticationDetails import org.springframework.test.context.ActiveProfiles import org.springframework.test.context.junit.jupiter.SpringExtension @@ -70,7 +71,7 @@ class PetriNetControllerTest { @Autowired private IUserService userService - private PetriNet net + private PetriNet net, userNet private Authentication userAuth private Authentication adminAuth From f41976f05e3d9f77d43ea6cd80d10d5491b68675 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Wed, 14 Sep 2022 10:53:01 +0200 Subject: [PATCH 65/68] [NAE-1617] Authority refactor - corrected according to tests - updated documentation --- docs/authorization/authority.md | 43 ++++++++--------- .../logic/action/ActionDelegate.groovy | 46 +++++++------------ .../engine/auth/domain/AuthorizingObject.java | 7 +-- .../engine/auth/web/UserController.java | 2 +- 4 files changed, 37 insertions(+), 61 deletions(-) diff --git a/docs/authorization/authority.md b/docs/authorization/authority.md index 4e00010925..6567b14274 100644 --- a/docs/authorization/authority.md +++ b/docs/authorization/authority.md @@ -15,32 +15,31 @@ These authorizing objects are predefined, and they are used to create the - `PROCESS_UPLOAD`- to import new process - `PROCESS_VIEW_ALL`- to retrieve all the processes imported by any user -- `PROCESS_VIEW_MY`- to retrieve only processes imported by logged user +- `PROCESS_VIEW_OWN`- to retrieve only processes imported by logged user - `PROCESS_DELETE_ALL`- to delete processes imported by any user -- `PROCESS_DELETE_MY`- to delete processes imported by logged user +- `PROCESS_DELETE_OWN`- to delete processes imported by logged user - `FILTER_UPLOAD`- to upload filter -- `FILTER_DELETE_MY`- to delete filter imported by logged user +- `FILTER_DELETE_OWN`- to delete filter imported by logged user - `FILTER_DELETE_ALL`- to delete filter imported by any user - `USER_CREATE`- to invite or create user - `USER_DELETE`- to remove user - `USER_EDIT_ALL`- to edit any user -- `USER_EDIT_MY`- to edit only logged user +- `USER_EDIT_SELF`- to edit only logged user - `USER_VIEW_ALL`- to retrieve all users -- `USER_VIEW_MY`- to retrieve only logged user +- `USER_VIEW_SELF`- to retrieve only logged user - `GROUP_CREATE`- to create group -- `GROUP_DELETE_MY`- to delete group created by logged user +- `GROUP_DELETE_OWN`- to delete group created by logged user - `GROUP_DELETE_ALL`- to delete group create by any user - `GROUP_ADD_USER`- to add any user to any group - `GROUP_REMOVE_USER`- to remove any user from any group - `GROUP_VIEW_ALL`- to retrieve any group -- `GROUP_VIEW_MY`- to retrieve group of logged user +- `GROUP_VIEW_OWN`- to retrieve group of logged user - `ROLE_ASSIGN_TO_USER`- to assign role to user - `ROLE_REMOVE_FROM_USER`- to remove role from user - `AUTHORITY_CREATE`- to create authority - `AUTHORITY_DELETE`- to delete authority - `AUTHORITY_VIEW_ALL`- to retrieve any authority - `CASE_VIEW_ALL`- to view all cases -- `CASE_VIEW_MY`- to view cases of logged user - `CASE_CREATE`- to create case - `CASE_DELETE`- to delete case - `CASE_DATA_GET_ALL`- to get all data of case @@ -50,6 +49,9 @@ These authorizing objects are predefined, and they are used to create the - `TASK_CANCEL`- to cancel task - `TASK_DELEGATE`- to delegate task - `TASK_SAVE_DATA`- to save data on task +- `ELASTIC_REINDEX` - to reindex Elasticsearch database +- `LDAP_GROUP_GET_ALL` - to get all LDAP groups +- `LDAP_GROUP_ASSIGN_ROLES` - to assign roles to LDAP groups However, it is possible to add custom authorizing objects using `nae.authority.authorizing-objects` property in `application.properties` files as following: @@ -62,14 +64,11 @@ nae.authority.authorizing-objects=EXAMPLE_AUTHORITY_1,EXAMPLE_AUTHORITY_2 ## Authorization definition You can define authorization for any method in the Netgrif Application Engine project. -You can use the new `@Authorizations` and `@Authorize` annotations over the method definitions, -which are strongly connected to each other: the value of `@Authorizations` is an array of `@Authorize` -objects: +You can use the new `@Authorize` annotation over the method definitions. This annotation can +be defined once or multiple times over a method: ``` -@Authorizations(value = { - @Authorize(authority = "PROCESS_UPLOAD", expression = "#canUpload(#userId)" -}) +@Authorize(authority = "PROCESS_UPLOAD", expression = "#canUpload(#userId)" void importPetriNet(File petriNet) { ... } @@ -90,9 +89,7 @@ If there is no `authority` defined, the authorization method returns `true` for In the following example, user must fulfill addition authorization implemented in `canUpload(String userId)` function: ``` -@Authorizations(value = { - @Authorize(expression = "#canUpload(#userId)) -}) +@Authorize(expression = "#canUpload(#userId)) void importPetriNet(File petriNet) { ... } @@ -101,24 +98,20 @@ void importPetriNet(File petriNet) { If there is no `expression` defined, the authorization method always returns`true` for expression check. In the following example, user must have `PROCESS_UPLOAD` authority: ``` -@Authorizations(value = { - @Authorize(authority = "PROCESS_UPLOAD") -}) +@Authorize(authority = "PROCESS_UPLOAD") void importPetriNet(File petriNet) { ... } ``` -If there are more authorizations defined inside `@Authorizations` using `@Authorize`, then OR statement is valid +If there are more authorizations defined using `@Authorize`, then OR statement is valid between the multiple `@Authorize` statements, so user must fulfill at least one `@Authorize` statement. In the following example, the logged user must have `PROCESS_UPLOAD` authority AND must fulfill `canUpload(String userId)` expression, OR must fulfill `isAdmin(String userId)` expression: ``` -@Authorizations(value = { - @Authorize(authority = "PROCESS_UPLOAD", expression = "#canUpload(#userId)", - @Authorize(expression = "isAdmin(#userId)") -}) +@Authorize(authority = "PROCESS_UPLOAD", expression = "#canUpload(#userId)", +@Authorize(expression = "isAdmin(#userId)") void importPetriNet(File petriNet) { ... } diff --git a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy index ede8d39852..dd9db1bab6 100644 --- a/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy +++ b/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy @@ -1140,9 +1140,8 @@ class ActionDelegate { mailService.sendMail(mailDraft) } - @Authorizations(value = [ - @Authorize(authority = "USER_EDIT") - ]) + @Authorize(authority = "USER_EDIT_ALL") + @Authorize(authority = "USER_EDIT_OWN", expression = "@userService.getLoggedUser().email.equals(#email)") def changeUserByEmail(String email) { [email : { cl -> changeUserByEmail(email, "email", cl) @@ -1159,9 +1158,8 @@ class ActionDelegate { ] } - @Authorizations(value = [ - @Authorize(authority = "USER_EDIT") - ]) + @Authorize(authority = "USER_EDIT_ALL") + @Authorize(authority = "USER_EDIT_OWN", expression = "@userService.getLoggedUser().stringId.equals(#id)") def changeUser(String id) { [email : { cl -> changeUser(id, "email", cl) @@ -1178,9 +1176,8 @@ class ActionDelegate { ] } - @Authorizations(value = [ - @Authorize(authority = "USER_EDIT") - ]) + @Authorize(authority = "USER_EDIT_ALL") + @Authorize(authority = "USER_EDIT_OWN", expression = "@userService.getLoggedUser().stringId.equals(#user.getStringId())") def changeUser(IUser user) { [email : { cl -> changeUser(user, "email", cl) @@ -1197,25 +1194,22 @@ class ActionDelegate { ] } - @Authorizations(value = [ - @Authorize(authority = "USER_EDIT") - ]) + @Authorize(authority = "USER_EDIT_ALL") + @Authorize(authority = "USER_EDIT_SELF", expression = "@userService.getLoggedUser().email.equals(#email)") def changeUserByEmail(String email, String attribute, def cl) { IUser user = userService.findByEmail(email, false) changeUser(user, attribute, cl) } - @Authorizations(value = [ - @Authorize(authority = "USER_EDIT") - ]) + @Authorize(authority = "USER_EDIT_ALL") + @Authorize(authority = "USER_EDIT_SELF", expression = "@userService.getLoggedUser().stringId.equals(#id)") def changeUser(String id, String attribute, def cl) { IUser user = userService.findById(id, false) changeUser(user, attribute, cl) } - @Authorizations(value = [ - @Authorize(authority = "USER_EDIT") - ]) + @Authorize(authority = "USER_EDIT_ALL") + @Authorize(authority = "USER_EDIT_SELF", expression = "@userService.getLoggedUser().stringId.equals(#user.getStringId())") def changeUser(IUser user, String attribute, def cl) { if (user == null) { log.error("Cannot find user.") @@ -1231,9 +1225,7 @@ class ActionDelegate { userService.save(user) } - @Authorizations(value = [ - @Authorize(authority = "USER_CREATE") - ]) + @Authorize(authority = "USER_CREATE") MessageResource inviteUser(String email) { NewUserRequest newUserRequest = new NewUserRequest() newUserRequest.email = email @@ -1242,9 +1234,7 @@ class ActionDelegate { return inviteUser(newUserRequest) } - @Authorizations(value = [ - @Authorize(authority = "USER_CREATE") - ]) + @Authorize(authority = "USER_CREATE") MessageResource inviteUser(NewUserRequest newUserRequest) { IUser user = registrationService.createNewUser(newUserRequest); if (user == null) @@ -1255,9 +1245,7 @@ class ActionDelegate { return MessageResource.successMessage("Done"); } - @Authorizations(value = [ - @Authorize(authority = "USER_DELETE_ALL") - ]) + @Authorize(authority = "USER_DELETE") void deleteUser(String email) { IUser user = userService.findByEmail(email, false) if (user == null) @@ -1265,9 +1253,7 @@ class ActionDelegate { deleteUser(user) } - @Authorizations(value = [ - @Authorize(authority = "USER_DELETE_ALL") - ]) + @Authorize(authority = "USER_DELETE") void deleteUser(IUser user) { List tasks = taskService.findByUser(new FullPageRequest(), user).toList() if (tasks != null && tasks.size() > 0) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java index e2609a7fb9..ebb468b11d 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java @@ -20,14 +20,13 @@ public enum AuthorizingObject { FILTER_DELETE_ALL, FILTER_DELETE_OWN, USER_CREATE, - USER_DELETE_ALL, - USER_DELETE_SELF, + USER_DELETE, USER_EDIT_ALL, USER_EDIT_SELF, USER_VIEW_ALL, USER_VIEW_SELF, GROUP_CREATE, - GROUP_DELETE_SELF, + GROUP_DELETE_OWN, GROUP_DELETE_ALL, GROUP_ALL_ADD_USER, GROUP_OWN_ADD_USER, @@ -37,12 +36,10 @@ public enum AuthorizingObject { GROUP_VIEW_OWN, GROUP_MEMBERSHIP_SELF, ROLE_ASSIGN_TO_USER, - ROLE_REMOVE_FROM_USER, AUTHORITY_CREATE, AUTHORITY_DELETE, AUTHORITY_VIEW, CASE_VIEW_ALL, - CASE_VIEW_OWN, CASE_CREATE, CASE_DELETE, CASE_DATA_GET_ALL, diff --git a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java index 597246b354..6541ce9fa3 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java @@ -177,7 +177,7 @@ public PagedModel getAllWithRole(@RequestBody Set roleIds, return resources; } - @Authorize(authority = "USER_EDIT_ALL", expression = "@userService.isLogged(#userId)") + @Authorize(authority = "ROLE_ASSIGN_TO_USER") @Operation(summary = "Assign role to the user", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "BasicAuth")}) @PostMapping(value = "/{id}/role/assign", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) @ApiResponses(value = { From 9209a5e986f928601a930e69563285298352bcf4 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Wed, 14 Sep 2022 14:21:57 +0200 Subject: [PATCH 66/68] [NAE-1617] Authority refactor - corrected according to tests - added properties - corrected according to PR --- .../engine/startup/SuperCreator.groovy | 2 +- .../engine/auth/domain/AnonymousUser.java | 6 -- .../engine/auth/domain/Authority.java | 1 + .../auth/domain/AuthorityProperties.java | 19 ++++++ .../auth/service/AbstractUserService.java | 12 ++-- .../engine/auth/service/AuthorityService.java | 68 +++++++++++++------ .../engine/auth/service/UserService.java | 12 ++-- .../IAuthorityAuthorizationService.java | 4 -- .../service/interfaces/IAuthorityService.java | 15 ++-- .../engine/auth/web/AuthorityController.java | 2 +- .../engine/auth/web/UserController.java | 9 +-- .../NaeSecurityConfiguration.java | 6 +- .../properties/CacheProperties.java | 9 ++- .../orgstructure/groups/NextGroupService.java | 10 +++ .../groups/interfaces/INextGroupService.java | 2 + .../orgstructure/web/GroupController.java | 7 +- .../petrinet/service/PetriNetService.java | 3 +- .../service/FilterAuthorizationService.java | 3 +- src/main/resources/application.properties | 6 +- .../engine/action/RemoveActionTest.groovy | 6 +- .../auth/TaskAuthorizationServiceTest.groovy | 6 +- .../WorkflowAuthorizationServiceTest.groovy | 6 +- .../engine/elastic/ElasticSearchTest.groovy | 6 +- .../event/GroovyShellFactoryTest.groovy | 6 +- .../filters/FilterImportExportTest.groovy | 6 +- .../engine/insurance/EncryptionTest.groovy | 6 +- .../engine/insurance/mvc/InsuranceTest.groovy | 6 +- .../engine/menu/MenuImportExportTest.groovy | 6 +- .../groups/NextGroupServiceTest.groovy | 6 +- .../ElasticSearchViewPermissionTest.groovy | 6 +- .../QueryDSLViewPermissionTest.groovy | 6 +- .../domain/roles/ProcessRoleTest.groovy | 6 +- .../service/CachePetriNetServiceTest.groovy | 8 ++- .../service/PetriNetServiceTest.groovy | 6 +- .../engine/workflow/TaskControllerTest.groovy | 6 +- .../application/engine/MockService.java | 6 +- .../workflow/service/TaskServiceTest.java | 5 +- .../engine/workflow/web/VariableArcsTest.java | 10 +-- 38 files changed, 218 insertions(+), 97 deletions(-) create mode 100644 src/main/java/com/netgrif/application/engine/auth/domain/AuthorityProperties.java delete mode 100644 src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityAuthorizationService.java diff --git a/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy b/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy index aa7058a0a4..6be6a0521c 100644 --- a/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy +++ b/src/main/groovy/com/netgrif/application/engine/startup/SuperCreator.groovy @@ -43,7 +43,7 @@ class SuperCreator extends AbstractOrderedCommandLineRunner { } private IUser createSuperUser() { - List adminAuthorities = authorityService.findByScope(Authority.defaultAdminAuthority) + Set adminAuthorities = authorityService.getDefaultAdminAuthorities() IUser superUser = userService.findByEmail("super@netgrif.com", false) if (superUser == null) { this.superUser = userService.saveNew(new User( diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AnonymousUser.java b/src/main/java/com/netgrif/application/engine/auth/domain/AnonymousUser.java index 2c90a93038..521ed03218 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AnonymousUser.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AnonymousUser.java @@ -23,12 +23,6 @@ public AnonymousUser(String email, String password, String name, String surname) super(email, password, name, surname); } - @Override - @Cacheable("authorities") - public Set getAuthorities() { - return super.getAuthorities(); - } - @Override public LoggedUser transformToLoggedUser() { LoggedUser loggedUser = new LoggedUser(this.get_id().toString(), this.getEmail(), this.getPassword(), this.getAuthorities()); diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java index 0ecdf1d2e8..6f2b7e1674 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/Authority.java @@ -16,6 +16,7 @@ public class Authority implements GrantedAuthority { public static final long serialVersionUID = 2839744057647464485L; public static final String defaultAdminAuthority = "*"; + public static final List defaultUserAuthorities = Arrays.asList("FILTER_*", AuthorizingObject.GROUP_VIEW_OWN.name()); public static final List defaultAnonymousAuthorities = Collections.emptyList(); diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityProperties.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityProperties.java new file mode 100644 index 0000000000..d5bf50ad65 --- /dev/null +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorityProperties.java @@ -0,0 +1,19 @@ +package com.netgrif.application.engine.auth.domain; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Data +@Component +@ConfigurationProperties(prefix = "nae.authority") +public class AuthorityProperties { + + private List defaultUserAuthorities; + + private List defaultAnonymousAuthorities; + + private List defaultAdminAuthorities; +} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java b/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java index 2318b1c4ff..8ef9dbdce8 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AbstractUserService.java @@ -47,16 +47,14 @@ public void addDefaultRole(IUser user) { @Override public void addDefaultAuthorities(IUser user) { if (user.getAuthorities().isEmpty()) { - HashSet authorities = new HashSet<>(); - Authority.defaultUserAuthorities.forEach(a -> authorities.addAll(authorityService.findByScope(a))); - user.setAuthorities(authorities); + user.setAuthorities(authorityService.getDefaultUserAuthorities()); } } @Override - public void assignAuthority(String userId, String authorityId) { + public void assignAuthority(String userId, String authorityName) { IUser user = resolveById(userId, true); - Authority authority = authorityService.getOne(authorityId); + Authority authority = authorityService.findByName(authorityName); user.addAuthority(authority); authority.addUser(user); @@ -64,9 +62,9 @@ public void assignAuthority(String userId, String authorityId) { } @Override - public void removeAuthority(String userId, String authorityId) { + public void removeAuthority(String userId, String authorityName) { IUser user = resolveById(userId, true); - Authority authority = authorityService.getOne(authorityId); + Authority authority = authorityService.findByName(authorityName); user.removeAuthority(authority); authority.removeUser(user); diff --git a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java index 81ad550b04..60a83c3837 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/AuthorityService.java @@ -1,18 +1,18 @@ package com.netgrif.application.engine.auth.service; import com.netgrif.application.engine.auth.domain.Authority; +import com.netgrif.application.engine.auth.domain.AuthorityProperties; import com.netgrif.application.engine.auth.domain.repositories.AuthorityRepository; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; -import org.bson.types.ObjectId; +import org.apache.logging.log4j.util.Strings; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; import org.springframework.data.rest.webmvc.ResourceNotFoundException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Optional; +import java.util.*; +import java.util.stream.Collectors; /** * Service to manage authorities in NAE @@ -26,6 +26,14 @@ public class AuthorityService implements IAuthorityService { @Autowired private AuthorityRepository repository; + /** + * Property class for authorities + * */ + @Autowired + private AuthorityProperties authorityProperties; + + private static final String SCOPE_SUFFIX = "*"; + /** * Retrieve all authorities from database * */ @@ -106,11 +114,13 @@ public void delete(String name) { @Override public List findByScope(String scope) { List authorities; - if (scope.equals("*")) + if (scope.equals(SCOPE_SUFFIX)) authorities = repository.findAll(); - else { - String prefix = scope.replace("*", ""); + else if (isScope(scope)) { + String prefix = scope.replace(SCOPE_SUFFIX, Strings.EMPTY); authorities = repository.findAllByNameStartsWith(prefix); + } else { + authorities = Collections.singletonList(repository.findByName(scope)); } return authorities; } @@ -138,21 +148,38 @@ public Authority findByName(String name) { * @return optional of authority * */ @Override - public Optional findById(String id) { + public Optional findOptionalByName(String id) { return Optional.of(repository.findByName(id)); } /** - * Returns authority from database based on provided ID if exists - * @param id of authority to be retrieved - * @return authority object + * Returns the default authorities for simple user + * @return list of authorities + * */ + @Override + @Cacheable("defaultUserAuthoritiesCache") + public Set getDefaultUserAuthorities() { + return authorityProperties.getDefaultUserAuthorities().stream().map(this::findByScope).flatMap(Collection::stream).collect(Collectors.toSet()); + } + + /** + * Returns the default authorities for anonymous user + * @return list of authorities + * */ + @Override + @Cacheable("defaultAnonymousAuthoritiesCache") + public Set getDefaultAnonymousAuthorities() { + return authorityProperties.getDefaultAnonymousAuthorities().stream().map(this::findByScope).flatMap(Collection::stream).collect(Collectors.toSet()); + } + + /** + * Returns the default authorities for admin user + * @return list of authorities * */ @Override - public Authority getOne(String id) { - Optional authority = repository.findById(id); - if (authority.isEmpty()) - throw new IllegalArgumentException("Could not find authority with id [" + id + "]"); - return authority.get(); + @Cacheable("defaultAdminAuthoritiesCache") + public Set getDefaultAdminAuthorities() { + return authorityProperties.getDefaultAdminAuthorities().stream().map(this::findByScope).flatMap(Collection::stream).collect(Collectors.toSet()); } /** @@ -161,11 +188,8 @@ public Authority getOne(String id) { * @return boolean whether the provided name is valid scope name * */ private boolean isScope(String authorityName) { - if (authorityName.endsWith("*")) - return true; - else if (authorityName.contains("*")) + if (authorityName.contains(SCOPE_SUFFIX) && authorityName.indexOf(SCOPE_SUFFIX) != authorityName.length() - 1) throw new IllegalArgumentException("The authority name or scope is not valid."); - else - return false; + else return authorityName.endsWith(SCOPE_SUFFIX); } } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java index f83219f4ee..aba9e26ea1 100755 --- a/src/main/java/com/netgrif/application/engine/auth/service/UserService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/UserService.java @@ -121,17 +121,13 @@ public void addAnonymousRole(User user) { public void addDefaultAuthorities(User user) { if (user.getAuthorities().isEmpty()) { - HashSet authorities = new HashSet<>(); - Authority.defaultUserAuthorities.forEach(a -> authorities.addAll(authorityService.findByScope(a))); - user.setAuthorities(authorities); + user.setAuthorities(authorityService.getDefaultUserAuthorities()); } } public void addAnonymousAuthorities(User user) { if (user.getAuthorities().isEmpty()) { - HashSet authorities = new HashSet<>(); - Authority.defaultAnonymousAuthorities.forEach(a -> authorities.add(authorityService.findByName(a))); - user.setAuthorities(authorities); + user.setAuthorities(authorityService.getDefaultAnonymousAuthorities()); } } @@ -264,7 +260,7 @@ public IUser getLoggedOrSystem() { @Override public void assignAuthority(String userId, String authorityId) { Optional user = userRepository.findById(userId); - Optional authority = authorityService.findById(authorityId); + Optional authority = authorityService.findOptionalByName(authorityId); if (user.isEmpty()) throw new IllegalArgumentException("Could not find user with id [" + userId + "]"); @@ -280,7 +276,7 @@ public void assignAuthority(String userId, String authorityId) { @Override public void removeAuthority(String userId, String authorityId) { Optional user = userRepository.findById(userId); - Optional authority = authorityService.findById(authorityId); + Optional authority = authorityService.findOptionalByName(authorityId); if (user.isEmpty()) throw new IllegalArgumentException("Could not find user with id [" + userId + "]"); diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityAuthorizationService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityAuthorizationService.java deleted file mode 100644 index 2b2dbb329c..0000000000 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityAuthorizationService.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.netgrif.application.engine.auth.service.interfaces; - -public interface IAuthorityAuthorizationService { -} diff --git a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java index 8eecf2654e..c92cbb2b9b 100644 --- a/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java +++ b/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IAuthorityService.java @@ -1,9 +1,11 @@ package com.netgrif.application.engine.auth.service.interfaces; import com.netgrif.application.engine.auth.domain.Authority; +import org.springframework.cache.annotation.Cacheable; import java.util.List; import java.util.Optional; +import java.util.Set; /** * Interface for managing authorities in NAE @@ -35,7 +37,7 @@ public interface IAuthorityService { * @param id of authority * @return optional of authority object * */ - Optional findById(String id); + Optional findOptionalByName(String name); /** * Returns or creates authority of given name if it does not exist. @@ -64,10 +66,9 @@ public interface IAuthorityService { * */ void delete(String name); - /** - * Returns authority based on ID - * @param id of authority to be retrieved - * @return authority object - * */ - Authority getOne(String id); + Set getDefaultUserAuthorities(); + + Set getDefaultAnonymousAuthorities(); + + Set getDefaultAdminAuthorities(); } \ No newline at end of file diff --git a/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java index aed211bcf7..7b11f0bf5b 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/AuthorityController.java @@ -77,7 +77,7 @@ public CollectionModel getAll(Authentication auth) { @Operation(description = "Delete authority", security = {@SecurityRequirement(name = "BasicAuth")}) @GetMapping(value = "/{name}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public EntityModel getOne(@PathVariable("name") String name, Authentication auth) { - Optional authority = authorityService.findById(name); + Optional authority = authorityService.findOptionalByName(name); if (authority.isPresent()) { return AuthorityResource.of(authority.get()); } else { diff --git a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java index 6541ce9fa3..4e3d164813 100644 --- a/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ b/src/main/java/com/netgrif/application/engine/auth/web/UserController.java @@ -1,9 +1,6 @@ package com.netgrif.application.engine.auth.web; -import com.netgrif.application.engine.auth.domain.Authorizations; -import com.netgrif.application.engine.auth.domain.Authorize; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.LoggedUser; +import com.netgrif.application.engine.auth.domain.*; import com.netgrif.application.engine.auth.domain.throwable.UnauthorisedRequestException; import com.netgrif.application.engine.auth.service.UserDetailsServiceImpl; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; @@ -127,7 +124,7 @@ public PagedModel search(@RequestParam(value = "small", required = public UserResource getUser(@PathVariable("id") String userId, @RequestParam(value = "small", required = false) Boolean small, Locale locale) { small = small != null && small; LoggedUser loggedUser = (LoggedUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); - if (!loggedUser.hasAuthority("USER_VIEW_ALL") && !Objects.equals(loggedUser.getId(), userId)) { + if (!loggedUser.hasAuthority(AuthorizingObject.USER_VIEW_ALL.name()) && !Objects.equals(loggedUser.getId(), userId)) { log.info("User " + loggedUser.getUsername() + " trying to get another user with ID " + userId); throw new IllegalArgumentException("Could not find user with id [" + userId + "]"); } @@ -152,7 +149,7 @@ public UserResource updateUser(@PathVariable("id") String userId, @RequestBody U LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); IUser user = userService.resolveById(userId, false); - if (user == null || (!loggedUser.hasAuthority("USER_EDIT_ALL") && !Objects.equals(loggedUser.getId(), userId))) + if (user == null || (!loggedUser.hasAuthority(AuthorizingObject.USER_EDIT_SELF.name()) && !Objects.equals(loggedUser.getId(), userId))) throw new UnauthorisedRequestException("User " + loggedUser.getUsername() + " doesn't have permission to modify profile of " + (user != null ? user.transformToLoggedUser().getUsername() : null)); user = userService.update(user, updates); diff --git a/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java b/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java index e88ed1674c..521b776706 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java +++ b/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.configuration; import com.netgrif.application.engine.auth.domain.Authority; +import com.netgrif.application.engine.auth.domain.AuthorityProperties; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.configuration.authentication.providers.NaeAuthProperties; @@ -73,6 +74,9 @@ public class NaeSecurityConfiguration extends AbstractSecurityConfiguration { @Autowired protected NaeLdapProperties ldapProperties; + @Autowired + private AuthorityProperties authorityProperties; + private static final String ANONYMOUS_USER = "anonymousUser"; @Bean @@ -157,7 +161,7 @@ protected Environment getEnvironment() { } private PublicAuthenticationFilter createPublicAuthenticationFilter() throws Exception { - List authorities = authorityService.getOrCreate(Authority.defaultAnonymousAuthorities); + List authorities = authorityService.getOrCreate(authorityProperties.getDefaultAnonymousAuthorities()); authorities.forEach(a -> a.setUsers(new HashSet<>())); return new PublicAuthenticationFilter( authenticationManager(), diff --git a/src/main/java/com/netgrif/application/engine/configuration/properties/CacheProperties.java b/src/main/java/com/netgrif/application/engine/configuration/properties/CacheProperties.java index d62b67be4d..3fc9ca6871 100644 --- a/src/main/java/com/netgrif/application/engine/configuration/properties/CacheProperties.java +++ b/src/main/java/com/netgrif/application/engine/configuration/properties/CacheProperties.java @@ -19,10 +19,17 @@ public class CacheProperties { private String petriNetCache = "petriNetCache"; + private String defaultAdminAuthoritiesCache = "defaultAdminAuthoritiesCache"; + + private String defaultUserAuthoritiesCache = "defaultUserAuthoritiesCache"; + + private String defaultAnonymousAuthoritiesCache = "defaultAnonymousAuthoritiesCache"; + private List additional = new ArrayList<>(); public Set getAllCaches() { - Set caches = new LinkedHashSet<>(Arrays.asList(petriNetById, petriNetByIdentifier, petriNetNewest, petriNetCache)); + Set caches = new LinkedHashSet<>(Arrays.asList(petriNetById, petriNetByIdentifier, petriNetNewest, petriNetCache, + defaultAdminAuthoritiesCache, defaultUserAuthoritiesCache, defaultAnonymousAuthoritiesCache)); caches.addAll(additional); return caches; } diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/groups/NextGroupService.java b/src/main/java/com/netgrif/application/engine/orgstructure/groups/NextGroupService.java index f9625d4d57..3b8c1da382 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/groups/NextGroupService.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/groups/NextGroupService.java @@ -10,6 +10,7 @@ import com.netgrif.application.engine.mail.interfaces.IMailAttemptService; import com.netgrif.application.engine.mail.interfaces.IMailService; import com.netgrif.application.engine.orgstructure.groups.interfaces.INextGroupService; +import com.netgrif.application.engine.orgstructure.web.responsebodies.Group; import com.netgrif.application.engine.petrinet.domain.I18nString; import com.netgrif.application.engine.petrinet.domain.throwable.TransitionNotExecutableException; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; @@ -308,6 +309,15 @@ public Collection getGroupsOwnerEmails(Collection groupIds) { return this.findByIds(groupIds).stream().map(this::getGroupOwnerEmail).collect(Collectors.toList()); } + @Override + public Set getGroupsOfUser(String userId) { + List groups = this.findAllGroups(); + return groups.stream() + .filter(aCase -> aCase.getAuthor().getId().equals(userId)) + .map(aCase -> new Group(aCase.getStringId(), aCase.getTitle())) + .collect(Collectors.toCollection(HashSet::new)); + } + protected static BooleanExpression groupCase() { return QCase.case$.processIdentifier.eq(GROUP_CASE_IDENTIFIER); } diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/groups/interfaces/INextGroupService.java b/src/main/java/com/netgrif/application/engine/orgstructure/groups/interfaces/INextGroupService.java index 735cdaf128..602040c7f8 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/groups/interfaces/INextGroupService.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/groups/interfaces/INextGroupService.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.orgstructure.groups.interfaces; import com.netgrif.application.engine.auth.domain.IUser; +import com.netgrif.application.engine.orgstructure.web.responsebodies.Group; import com.netgrif.application.engine.petrinet.domain.I18nString; import com.netgrif.application.engine.workflow.domain.Case; import com.netgrif.application.engine.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; @@ -58,4 +59,5 @@ public interface INextGroupService { Set getAllCoMembers(IUser user); + Set getGroupsOfUser(String userId); } diff --git a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java index 10225f0d02..191873c0af 100644 --- a/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java +++ b/src/main/java/com/netgrif/application/engine/orgstructure/web/GroupController.java @@ -66,12 +66,7 @@ public GroupsResource getAllGroups() { }) public GroupsResource getMyGroups(Authentication auth) { String loggedUserId = ((LoggedUser)auth.getPrincipal()).getId(); - List groups = service.findAllGroups(); - Set groupResponse = groups.stream() - .filter(aCase -> aCase.getAuthor().getId().equals(loggedUserId)) - .map(aCase -> new Group(aCase.getStringId(), aCase.getTitle())) - .collect(Collectors.toCollection(HashSet::new)); - return new GroupsResource(groupResponse); + return new GroupsResource(service.getGroupsOfUser(loggedUserId)); } @Authorize(authority = "GROUP_MEMBERSHIP_SELF") diff --git a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index c711fbc71c..c289002f13 100644 --- a/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.type.TypeFactory; +import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.service.interfaces.IUserService; import com.netgrif.application.engine.configuration.properties.CacheProperties; @@ -412,7 +413,7 @@ public Page search(Map criteria, LoggedUser u Query query = new Query(); Query query_total = new Query(); - if (user.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("PROCESS_VIEW_ALL"))) + if (user.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals(AuthorizingObject.PROCESS_VIEW_ALL.name()))) query.addCriteria(getProcessRolesCriteria(user)); criteria.forEach((key, value) -> { diff --git a/src/main/java/com/netgrif/application/engine/workflow/service/FilterAuthorizationService.java b/src/main/java/com/netgrif/application/engine/workflow/service/FilterAuthorizationService.java index e19929eac8..1fb3f57ba6 100644 --- a/src/main/java/com/netgrif/application/engine/workflow/service/FilterAuthorizationService.java +++ b/src/main/java/com/netgrif/application/engine/workflow/service/FilterAuthorizationService.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.workflow.service; import com.netgrif.application.engine.auth.domain.Authority; +import com.netgrif.application.engine.auth.domain.AuthorizingObject; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.workflow.domain.Filter; import com.netgrif.application.engine.workflow.service.interfaces.IFilterAuthorizationService; @@ -17,6 +18,6 @@ public class FilterAuthorizationService implements IFilterAuthorizationService { @Override public boolean canCallDelete(LoggedUser user, Filter filter) { - return user.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals("FILTER_DELETE_ALL")) || user.getId().equals(filter.getAuthor().getId()); + return user.getAuthorities().stream().anyMatch(a -> a.getAuthority().equals(AuthorizingObject.FILTER_DELETE_ALL.name())) || user.getId().equals(filter.getAuthor().getId()); } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index b8a647ca7d..6f410c273f 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -168,4 +168,8 @@ nae.filter.export.file-name=filters.xml #server.port=8080 # Authorities -nae.authority.authorizing-objects= \ No newline at end of file +nae.authority.authorizing-objects= +nae.authority.defaultUserAuthorities=FILTER_UPLOAD,FILTER_DELETE_OWN,USER_EDIT_SELF,GROUP_OWN_ADD_USER,\ + GROUP_OWN_REMOVE_USER,GROUP_DELETE_OWN,GROUP_VIEW_OWN,GROUP_MEMBERSHIP_SELF +nae.authority.defaultAnonymousAuthorities= +nae.authority.defaultAdminAuthorities=* diff --git a/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy b/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy index ccb04de945..1143bcd0f7 100644 --- a/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/action/RemoveActionTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.action import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState @@ -79,6 +80,9 @@ class RemoveActionTest { @Autowired private TestHelper testHelper + @Autowired + private AuthorityProperties authorityProperties + private MockMvc mvc private PetriNet petriNet private Authentication auth @@ -97,7 +101,7 @@ class RemoveActionTest { this.petriNet = net.getNet() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) + def auths = importHelper.createAuthorities(["user": authorityProperties.defaultUserAuthorities, "admin": authorityProperties.defaultAdminAuthorities]) importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSWORD, state: UserState.ACTIVE), [auths.get("user")] as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy index 364adf8c64..865b57fabd 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/auth/TaskAuthorizationServiceTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.auth import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.IUser import com.netgrif.application.engine.auth.domain.User @@ -104,6 +105,9 @@ class TaskAuthorizationServiceTest { @Autowired private IDataService dataService + @Autowired + private AuthorityProperties authorityProperties + private String taskId private String taskId2 @@ -167,7 +171,7 @@ class TaskAuthorizationServiceTest { assert netWithUserRefs.getNet() != null this.netWithUserRefs = netWithUserRefs.getNet() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities]) + def auths = importHelper.createAuthorities(["user": authorityProperties.defaultUserAuthorities]) testUser = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], [] as ProcessRole[]) } diff --git a/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy index 9c0cb30165..482538afe4 100644 --- a/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/auth/WorkflowAuthorizationServiceTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.auth import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.IUser import com.netgrif.application.engine.auth.domain.User @@ -80,6 +81,9 @@ class WorkflowAuthorizationServiceTest { @Autowired private IUserService userService + @Autowired + private AuthorityProperties authorityProperties + private PetriNet net private PetriNet netWithUserRefs @@ -127,7 +131,7 @@ class WorkflowAuthorizationServiceTest { assert netWithUserRefs.getNet() != null this.netWithUserRefs = netWithUserRefs.getNet() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities]) + def auths = importHelper.createAuthorities(["user": authorityProperties.defaultUserAuthorities]) testUser = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], [] as ProcessRole[]) } diff --git a/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy b/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy index 9003da5163..bdcf95809c 100644 --- a/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/elastic/ElasticSearchTest.groovy @@ -3,6 +3,7 @@ package com.netgrif.application.engine.elastic import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.ApplicationEngine import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.elastic.domain.ElasticCaseRepository @@ -86,6 +87,9 @@ class ElasticSearchTest { @Autowired private TestHelper testHelper + @Autowired + private AuthorityProperties authorityProperties + private Authentication auth private MockMvc mvc private String netId, netId2 @@ -109,7 +113,7 @@ class ElasticSearchTest { netId2 = net2.getStringId() // def org = importHelper.createGroup("Test") - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) + def auths = importHelper.createAuthorities(["user": authorityProperties.defaultUserAuthorities, "admin": authorityProperties.defaultAdminAuthorities]) // def processRoles = importHelper.getProcessRoles(net.get()) def testUser = importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: USER_PASSW, state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy b/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy index 50c91fe03d..f03ba528c7 100644 --- a/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/event/GroovyShellFactoryTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.event import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.LoggedUser import com.netgrif.application.engine.auth.domain.User @@ -62,6 +63,9 @@ class GroovyShellFactoryTest { @Autowired private IUserService userService + @Autowired + private AuthorityProperties authorityProperties + private PetriNet net @@ -81,7 +85,7 @@ class GroovyShellFactoryTest { .apply(springSecurity()) .build() - def auths = importHelper.createAuthorities(["systemAdmin": [Authority.defaultAdminAuthority]]) + def auths = importHelper.createAuthorities(["systemAdmin": authorityProperties.defaultAdminAuthorities]) importHelper.createUser(new User(name: "Admin", surname: "User", email: USER_EMAIL, password: USER_PASSW, state: UserState.ACTIVE), auths.get("systemAdmin").toArray() as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy b/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy index 9c46911782..523497c4f6 100644 --- a/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/filters/FilterImportExportTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.filters import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState @@ -92,6 +93,9 @@ class FilterImportExportTest { @Autowired private IDataService dataService + @Autowired + private AuthorityProperties authorityProperties + private Authentication userAuth private User dummyUser private Case importCase @@ -300,7 +304,7 @@ class FilterImportExportTest { } private User createDummyUser() { - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) + def auths = importHelper.createAuthorities(["user": authorityProperties.defaultUserAuthorities, "admin": authorityProperties.defaultAdminAuthorities]) return importHelper.createUser(new User(name: "Dummy", surname: "User", email: DUMMY_USER_MAIL, password: DUMMY_USER_PASSWORD, state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/insurance/EncryptionTest.groovy b/src/test/groovy/com/netgrif/application/engine/insurance/EncryptionTest.groovy index 1cec68988e..7cfb997107 100644 --- a/src/test/groovy/com/netgrif/application/engine/insurance/EncryptionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/insurance/EncryptionTest.groovy @@ -1,6 +1,7 @@ package com.netgrif.application.engine.insurance import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.LoggedUser import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService import com.netgrif.application.engine.importer.service.Importer @@ -46,6 +47,9 @@ class EncryptionTest { @Autowired private SuperCreator superCreator + @Autowired + private AuthorityProperties authorityProperties + private final String FIELD_NAME = "City" private final String FIELD_VALUE = "Bratislava" @@ -87,7 +91,7 @@ class EncryptionTest { } LoggedUser mockLoggedUser() { - def authorityUser = authorityService.getOrCreate(Authority.defaultUserAuthorities) + def authorityUser = authorityService.getOrCreate(authorityProperties.defaultUserAuthorities) return new LoggedUser(superCreator.getSuperUser().getStringId(), "super@netgrif.com", "password", authorityUser) } } \ No newline at end of file diff --git a/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy b/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy index 748cbfcbef..9ff937ef50 100644 --- a/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/insurance/mvc/InsuranceTest.groovy @@ -3,6 +3,7 @@ package com.netgrif.application.engine.insurance.mvc import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.ApplicationEngine import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState @@ -123,6 +124,9 @@ class InsuranceTest { @Autowired private TestHelper testHelper + @Autowired + private AuthorityProperties authorityProperties + @BeforeEach void before() { @@ -138,7 +142,7 @@ class InsuranceTest { netId = net.getNet().getStringId() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) + def auths = importHelper.createAuthorities(["user": authorityProperties.defaultUserAuthorities, "admin": authorityProperties.defaultAdminAuthorities]) def authorityArray = Stream.concat(auths.get("user").stream(), auths.get("admin").stream()).toArray() def processRoles = importHelper.getProcessRolesByImportId(net.getNet(), ["agent": "1", "company": "2"]) importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), diff --git a/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy b/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy index 8888ced299..b345f73b52 100644 --- a/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/menu/MenuImportExportTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.menu import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.auth.service.UserService @@ -116,6 +117,9 @@ class MenuImportExportTest { @Autowired private SuperCreator superCreator + @Autowired + private AuthorityProperties authorityProperties + private User dummyUser; private Authentication userAuth @@ -199,7 +203,7 @@ class MenuImportExportTest { } private User createDummyUser() { - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) + def auths = importHelper.createAuthorities(["user": authorityProperties.defaultUserAuthorities, "admin": authorityProperties.defaultAdminAuthorities]) return importHelper.createUser(new User(name: "Dummy", surname: "User", email: DUMMY_USER_MAIL, password: DUMMY_USER_PASSWORD, state: UserState.ACTIVE), [auths.get("user")] as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy index a30903dbcb..82a526d3cb 100644 --- a/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/orgstructure/groups/NextGroupServiceTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.orgstructure.groups import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState @@ -43,10 +44,13 @@ class NextGroupServiceTest { @Autowired TestHelper testHelper + @Autowired + private AuthorityProperties authorityProperties + @Test void groupTest() { testHelper.truncateDbs() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) + def auths = importHelper.createAuthorities(["user": authorityProperties.defaultUserAuthorities, "admin": authorityProperties.defaultAdminAuthorities]) importHelper.createUser(new User(name: "Dummy", surname: "User", email: DUMMY_USER_MAIL, password: "password", state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy b/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy index a5c39c8587..e65344e6f4 100644 --- a/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/permissions/ElasticSearchViewPermissionTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.permissions import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.IUser import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState @@ -71,6 +72,9 @@ class ElasticSearchViewPermissionTest { @Autowired private TestHelper testHelper + @Autowired + private AuthorityProperties authorityProperties + private static final String USER_EMAIL = "user123987645@test.com" private PetriNet net @@ -89,7 +93,7 @@ class ElasticSearchViewPermissionTest { assert netWithUserRefs.getNet() != null this.netWithUserRefs = netWithUserRefs.getNet() - userAuthority = authorityService.getOrCreate(Authority.defaultUserAuthorities) + userAuthority = authorityService.getOrCreate(authorityProperties.defaultUserAuthorities) testUser = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), userAuthority.toArray() as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/permissions/QueryDSLViewPermissionTest.groovy b/src/test/groovy/com/netgrif/application/engine/permissions/QueryDSLViewPermissionTest.groovy index fc37c12fed..af798b62f4 100644 --- a/src/test/groovy/com/netgrif/application/engine/permissions/QueryDSLViewPermissionTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/permissions/QueryDSLViewPermissionTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.permissions import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.IUser import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState @@ -64,6 +65,9 @@ class QueryDSLViewPermissionTest { @Autowired private TestHelper testHelper + @Autowired + private AuthorityProperties authorityProperties + private static final String USER_EMAIL = "user123987645@test.com" private PetriNet net @@ -82,7 +86,7 @@ class QueryDSLViewPermissionTest { assert netWithUserRefs.getNet() != null this.netWithUserRefs = netWithUserRefs.getNet() - userAuthority = authorityService.getOrCreate(Authority.defaultUserAuthorities) + userAuthority = authorityService.getOrCreate(authorityProperties.defaultUserAuthorities) testUser = importHelper.createUser(new User(name: "Role", surname: "User", email: USER_EMAIL, password: "password", state: UserState.ACTIVE), userAuthority.toArray() as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy index 53a98d1152..d2ba5fb229 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/domain/roles/ProcessRoleTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.petrinet.domain.roles import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.importer.service.Importer @@ -77,6 +78,9 @@ class ProcessRoleTest { @Autowired TestHelper testHelper + @Autowired + private AuthorityProperties authorityProperties + @BeforeEach void before() { testHelper.truncateDbs() @@ -91,7 +95,7 @@ class ProcessRoleTest { String netId = net.getNet().getStringId() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) + def auths = importHelper.createAuthorities(["user": authorityProperties.defaultUserAuthorities, "admin": authorityProperties.defaultAdminAuthorities]) def processRoles = userProcessRoleRepository.findAllByNetId(netId) importHelper.createUser(new User(name: "Test", surname: "Integration", email: USER_EMAIL_VIEW, password: "password", state: UserState.ACTIVE), [auths.get("user")] as Authority[], diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy index 5de7cb9fa9..879da1f267 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/service/CachePetriNetServiceTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.petrinet.service import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState import com.netgrif.application.engine.auth.service.interfaces.IUserService @@ -50,7 +51,10 @@ class CachePetriNetServiceTest { private CacheManager cacheManager @Autowired - private CacheProperties cacheProperties; + private CacheProperties cacheProperties + + @Autowired + private AuthorityProperties authorityProperties private def stream = { String name -> return TaskApiTest.getClassLoader().getResourceAsStream(name) @@ -59,7 +63,7 @@ class CachePetriNetServiceTest { @BeforeEach void setup() { testHelper.truncateDbs() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) + def auths = importHelper.createAuthorities(["user": authorityProperties.defaultUserAuthorities, "admin": authorityProperties.defaultAdminAuthorities]) importHelper.createUser(new User(name: "Customer", surname: "User", email: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy b/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy index 06d3ae57a9..f1d9836173 100644 --- a/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/petrinet/service/PetriNetServiceTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.petrinet.service import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState @@ -67,6 +68,9 @@ class PetriNetServiceTest { @Autowired private ProcessRoleRepository processRoleRepository + @Autowired + private AuthorityProperties authorityProperties + private def stream = { String name -> return TaskApiTest.getClassLoader().getResourceAsStream(name) } @@ -74,7 +78,7 @@ class PetriNetServiceTest { @BeforeEach void setup() { testHelper.truncateDbs() - def auths = importHelper.createAuthorities(["user": Authority.defaultUserAuthorities, "admin": [Authority.defaultAdminAuthority]]) + def auths = importHelper.createAuthorities(["user": authorityProperties.defaultUserAuthorities, "admin": authorityProperties.defaultAdminAuthorities]) importHelper.createUser(new User(name: "Customer", surname: "User", email: CUSTOMER_USER_MAIL, password: "password", state: UserState.ACTIVE), auths.get("user").toArray() as Authority[], [] as ProcessRole[]) diff --git a/src/test/groovy/com/netgrif/application/engine/workflow/TaskControllerTest.groovy b/src/test/groovy/com/netgrif/application/engine/workflow/TaskControllerTest.groovy index d6f8e20e64..c508e49e93 100644 --- a/src/test/groovy/com/netgrif/application/engine/workflow/TaskControllerTest.groovy +++ b/src/test/groovy/com/netgrif/application/engine/workflow/TaskControllerTest.groovy @@ -2,6 +2,7 @@ package com.netgrif.application.engine.workflow import com.netgrif.application.engine.TestHelper import com.netgrif.application.engine.auth.domain.Authority +import com.netgrif.application.engine.auth.domain.AuthorityProperties import com.netgrif.application.engine.auth.domain.AuthorizingObject import com.netgrif.application.engine.auth.domain.User import com.netgrif.application.engine.auth.domain.UserState @@ -88,6 +89,9 @@ class TaskControllerTest { @Autowired private TaskController taskController + @Autowired + private AuthorityProperties authorityProperties + private PetriNet net private Case useCase @@ -105,7 +109,7 @@ class TaskControllerTest { email: DUMMY_USER_MAIL, password: "superAdminPassword", state: UserState.ACTIVE, - authorities: authorityService.getOrCreate(Authority.defaultUserAuthorities).toSet() as Set, + authorities: authorityService.getOrCreate(authorityProperties.defaultUserAuthorities).toSet() as Set, processRoles: [] as Set)) importNet() } diff --git a/src/test/java/com/netgrif/application/engine/MockService.java b/src/test/java/com/netgrif/application/engine/MockService.java index 741b39181b..8d4b2fbbb5 100644 --- a/src/test/java/com/netgrif/application/engine/MockService.java +++ b/src/test/java/com/netgrif/application/engine/MockService.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine; import com.netgrif.application.engine.auth.domain.Authority; +import com.netgrif.application.engine.auth.domain.AuthorityProperties; import com.netgrif.application.engine.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import org.bson.types.ObjectId; @@ -18,8 +19,11 @@ public class MockService { @Autowired private IAuthorityService authorityService; + @Autowired + private AuthorityProperties authorityProperties; + public LoggedUser mockLoggedUser() { - List authorityUser = authorityService.getOrCreate(Authority.defaultUserAuthorities); + List authorityUser = authorityService.getOrCreate(authorityProperties.getDefaultUserAuthorities()); return new LoggedUser(new ObjectId().toString(), "super@netgrif.com", "password", authorityUser); } } diff --git a/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java b/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java index 3f206b153d..f47053ff15 100644 --- a/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java +++ b/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java @@ -73,6 +73,9 @@ public class TaskServiceTest { @Autowired private SuperCreator superCreator; + @Autowired + private AuthorityProperties authorityProperties; + @BeforeEach public void setUp() throws Exception { mongoTemplate.getDb().drop(); @@ -130,7 +133,7 @@ public void resetArcTest() throws TransitionNotExecutableException, MissingPetri } public LoggedUser mockLoggedUser() { - List authorityUser = authorityService.getOrCreate(Authority.defaultUserAuthorities); + List authorityUser = authorityService.getOrCreate(authorityProperties.getDefaultUserAuthorities()); return new LoggedUser(new ObjectId().toString(), "super@netgrif.com", "password", authorityUser); } } \ No newline at end of file diff --git a/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java b/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java index 2eb3b862bf..3cbcb20cc8 100644 --- a/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java +++ b/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java @@ -2,10 +2,7 @@ import com.netgrif.application.engine.MockService; import com.netgrif.application.engine.TestHelper; -import com.netgrif.application.engine.auth.domain.Authority; -import com.netgrif.application.engine.auth.domain.IUser; -import com.netgrif.application.engine.auth.domain.User; -import com.netgrif.application.engine.auth.domain.UserState; +import com.netgrif.application.engine.auth.domain.*; import com.netgrif.application.engine.auth.service.interfaces.IAuthorityService; import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; import com.netgrif.application.engine.petrinet.domain.PetriNet; @@ -88,6 +85,9 @@ public class VariableArcsTest { @Autowired private TestHelper testHelper; + @Autowired + private AuthorityProperties authorityProperties; + private PetriNet loaded; private IUser testUser; @@ -115,7 +115,7 @@ public void before() throws Exception { user.setState(UserState.ACTIVE); user.setEmail("VariableArcsTest@test.com"); testUser = importHelper.createUser(user, - authorityService.getOrCreate(Authority.defaultUserAuthorities).toArray(new Authority[]{}), + authorityService.getOrCreate(authorityProperties.getDefaultUserAuthorities()).toArray(new Authority[]{}), new ProcessRole[]{}); finishCase = importHelper.createCase("finish case", loaded); From 1d9c3bf69563959b82b5cb984ab80a7e093960ea Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Mon, 30 Jan 2023 14:28:46 +0100 Subject: [PATCH 67/68] [NAE-1617] Refactor authority - added old authorities to provide backward compatibility --- .../engine/auth/domain/AuthorizingObject.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java index ebb468b11d..ffddaa0219 100644 --- a/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java +++ b/src/main/java/com/netgrif/application/engine/auth/domain/AuthorizingObject.java @@ -11,6 +11,16 @@ * */ public enum AuthorizingObject { DEFAULT, + /** + * Deprecated as of version 6.3.0 + * */ + @Deprecated + ADMIN, + /** + * Deprecated as of version 6.3.0 + * */ + @Deprecated + USER, PROCESS_UPLOAD, PROCESS_VIEW_ALL, PROCESS_VIEW_OWN, From c945539e79ded144312d26821a011d0bc0a30e59 Mon Sep 17 00:00:00 2001 From: Stefan Renczes Date: Tue, 31 Jan 2023 10:57:27 +0100 Subject: [PATCH 68/68] [NAE-1617] Refactor authority - added old authorities to provide backward compatibility --- src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 6f410c273f..b65964304b 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -170,6 +170,6 @@ nae.filter.export.file-name=filters.xml # Authorities nae.authority.authorizing-objects= nae.authority.defaultUserAuthorities=FILTER_UPLOAD,FILTER_DELETE_OWN,USER_EDIT_SELF,GROUP_OWN_ADD_USER,\ - GROUP_OWN_REMOVE_USER,GROUP_DELETE_OWN,GROUP_VIEW_OWN,GROUP_MEMBERSHIP_SELF + GROUP_OWN_REMOVE_USER,GROUP_DELETE_OWN,GROUP_VIEW_OWN,GROUP_MEMBERSHIP_SELF,USER nae.authority.defaultAnonymousAuthorities= nae.authority.defaultAdminAuthorities=*