diff --git a/application-engine/src/main/groovy/com/netgrif/application/engine/migration/ActionMigration.groovy b/application-engine/src/main/groovy/com/netgrif/application/engine/migration/ActionMigration.groovy index b688a28eaf4..00a08b8e9cc 100644 --- a/application-engine/src/main/groovy/com/netgrif/application/engine/migration/ActionMigration.groovy +++ b/application-engine/src/main/groovy/com/netgrif/application/engine/migration/ActionMigration.groovy @@ -1,12 +1,11 @@ package com.netgrif.application.engine.migration import com.netgrif.application.engine.auth.service.UserService -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer import com.netgrif.application.engine.objects.petrinet.domain.PetriNet import com.netgrif.application.engine.objects.petrinet.domain.VersionType import com.netgrif.application.engine.petrinet.params.ImportPetriNetParams -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import groovy.util.logging.Slf4j import org.springframework.beans.factory.annotation.Autowired import org.springframework.core.io.ClassPathResource @@ -30,7 +29,7 @@ class ActionMigration { ImportPetriNetEventOutcome newPetriNet = petriNetService.importPetriNet(ImportPetriNetParams.with() .xmlFile(netStream) .releaseType(VersionType.MAJOR) - .author(ActorTransformer.toLoggedUser(userService.getLoggedOrSystem())) + .author(userService.getLoggedOrSystem()) .build()) List oldPetriNets @@ -44,7 +43,7 @@ class ActionMigration { .collect(Collectors.toList()) } - if (oldPetriNets.size() == 0){ + if (oldPetriNets.size() == 0) { String message = "Older version of Petri net with ID [" + newPetriNet.getNet().importId + "] is not present in MongoDB." log.error(message) throw new IllegalArgumentException(message) diff --git a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy index 1e686358e8a..5606de8465b 100644 --- a/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy +++ b/application-engine/src/main/groovy/com/netgrif/application/engine/petrinet/domain/dataset/logic/action/ActionDelegate.groovy @@ -5,6 +5,7 @@ import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRol import com.netgrif.application.engine.adapter.spring.workflow.domain.QCase import com.netgrif.application.engine.adapter.spring.workflow.domain.QTask import com.netgrif.application.engine.auth.service.GroupService +import com.netgrif.application.engine.auth.service.ImpersonationService import com.netgrif.application.engine.auth.service.UserDetailsServiceImpl import com.netgrif.application.engine.auth.service.UserService import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService @@ -22,17 +23,16 @@ import com.netgrif.application.engine.export.domain.ExportDataConfig import com.netgrif.application.engine.export.service.interfaces.IExportService import com.netgrif.application.engine.files.IStorageResolverService import com.netgrif.application.engine.files.interfaces.IStorageService -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService import com.netgrif.application.engine.importer.service.FieldFactory import com.netgrif.application.engine.integration.modules.ModuleHolder import com.netgrif.application.engine.mail.domain.MailDraft import com.netgrif.application.engine.mail.interfaces.IMailAttemptService import com.netgrif.application.engine.mail.interfaces.IMailService -import com.netgrif.application.engine.objects.auth.domain.AbstractUser -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer import com.netgrif.application.engine.menu.services.interfaces.DashboardItemService import com.netgrif.application.engine.menu.services.interfaces.DashboardManagementService import com.netgrif.application.engine.menu.services.interfaces.IMenuItemService +import com.netgrif.application.engine.objects.auth.domain.AbstractUser +import com.netgrif.application.engine.objects.auth.domain.ActorTransformer import com.netgrif.application.engine.objects.auth.domain.Group import com.netgrif.application.engine.objects.auth.domain.LoggedUser import com.netgrif.application.engine.objects.petrinet.domain.I18nString @@ -47,6 +47,7 @@ import com.netgrif.application.engine.objects.petrinet.domain.dataset.logic.vali import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole import com.netgrif.application.engine.objects.petrinet.domain.version.Version import com.netgrif.application.engine.objects.utils.MenuItemUtils +import com.netgrif.application.engine.objects.utils.Nullable import com.netgrif.application.engine.objects.workflow.domain.Case import com.netgrif.application.engine.objects.workflow.domain.Task import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.EventOutcome @@ -98,7 +99,6 @@ import org.springframework.core.io.FileSystemResource import org.springframework.data.domain.Page import org.springframework.data.domain.PageRequest import org.springframework.data.domain.Pageable -import com.netgrif.application.engine.objects.utils.Nullable import java.time.ZoneId import java.util.stream.Collectors @@ -140,6 +140,9 @@ class ActionDelegate { @Autowired UserService userService + @Autowired + ImpersonationService impersonationService + @Autowired IPetriNetService petriNetService @@ -200,9 +203,6 @@ class ActionDelegate { @Autowired ExportConfiguration exportConfiguration - @Autowired - IImpersonationService impersonationService - @Autowired SecurityConfigurationProperties.WebProperties webProperties @@ -969,11 +969,12 @@ class ActionDelegate { Case createCase(String identifier, String title = null, String color = "", AbstractUser author = userService.loggedOrSystem, Locale locale = LocaleContextHolder.getLocale(), Map params = [:]) { + LoggedUser loggedUser = author instanceof LoggedUser ? (LoggedUser) author : ActorTransformer.toLoggedUser(author) CreateCaseEventOutcome outcome = workflowService.createCase(CreateCaseParams.with() .processIdentifier(identifier) .title(title) .color(color) - .author(ActorTransformer.toLoggedUser(author)) + .author(loggedUser) .locale(locale) .params(params) .build()) @@ -983,11 +984,12 @@ class ActionDelegate { Case createCase(PetriNet net, String title = net.defaultCaseName.getTranslation(locale), String color = "", AbstractUser author = userService.loggedOrSystem, Locale locale = LocaleContextHolder.getLocale(), Map params = [:]) { + LoggedUser loggedUser = author instanceof LoggedUser ? (LoggedUser) author : ActorTransformer.toLoggedUser(author) CreateCaseEventOutcome outcome = workflowService.createCase(CreateCaseParams.with() .process(net) .title(title) .color(color) - .author(ActorTransformer.toLoggedUser(author)) + .author(loggedUser) .locale(locale) .params(params) .build()) @@ -1009,9 +1011,10 @@ class ActionDelegate { Task assignTask(String transitionId, Case aCase = useCase, AbstractUser user = userService.loggedOrSystem, Map params = [:]) { String taskId = getTaskId(transitionId, aCase) + LoggedUser loggedUser = user instanceof LoggedUser ? (LoggedUser) user : ActorTransformer.toLoggedUser(user) AssignTaskEventOutcome outcome = taskService.assignTask(TaskParams.with() .taskId(taskId) - .user(user) + .user(loggedUser) .params(params) .build()) this.outcomes.add(outcome) @@ -1019,9 +1022,10 @@ class ActionDelegate { } Task assignTask(Task task, AbstractUser user = userService.loggedOrSystem, Map params = [:]) { + LoggedUser loggedUser = user instanceof LoggedUser ? (LoggedUser) user : ActorTransformer.toLoggedUser(user) return addTaskOutcomeAndReturnTask(taskService.assignTask(TaskParams.with() .task(task) - .user(user) + .user(loggedUser) .params(params) .build())) } @@ -1032,17 +1036,19 @@ class ActionDelegate { Task cancelTask(String transitionId, Case aCase = useCase, AbstractUser user = userService.loggedOrSystem, Map params = [:]) { String taskId = getTaskId(transitionId, aCase) + LoggedUser loggedUser = user instanceof LoggedUser ? (LoggedUser) user : ActorTransformer.toLoggedUser(user) return addTaskOutcomeAndReturnTask(taskService.cancelTask(TaskParams.with() .taskId(taskId) - .user(user) + .user(loggedUser) .params(params) .build())) } Task cancelTask(Task task, AbstractUser user = userService.loggedOrSystem, Map params = [:]) { + LoggedUser loggedUser = user instanceof LoggedUser ? (LoggedUser) user : ActorTransformer.toLoggedUser(user) return addTaskOutcomeAndReturnTask(taskService.cancelTask(TaskParams.with() .task(task) - .user(user) + .user(loggedUser) .params(params) .build())) } @@ -1058,17 +1064,19 @@ class ActionDelegate { void finishTask(String transitionId, Case aCase = useCase, AbstractUser user = userService.loggedOrSystem, Map params = [:]) { String taskId = getTaskId(transitionId, aCase) + LoggedUser loggedUser = user instanceof LoggedUser ? (LoggedUser) user : ActorTransformer.toLoggedUser(user) addTaskOutcomeAndReturnTask(taskService.finishTask(TaskParams.with() .taskId(taskId) - .user(user) + .user(loggedUser) .params(params) .build())) } void finishTask(Task task, AbstractUser user = userService.loggedOrSystem, Map params = [:]) { + LoggedUser loggedUser = user instanceof LoggedUser ? (LoggedUser) user : ActorTransformer.toLoggedUser(user) addTaskOutcomeAndReturnTask(taskService.finishTask(TaskParams.with() .task(task) - .user(user) + .user(loggedUser) .params(params) .build())) } @@ -1103,44 +1111,44 @@ class ActionDelegate { refs.find { it.transitionId == transitionId }.stringId } - AbstractUser assignRole(String roleMongoId, AbstractUser user = userService.loggedUser) { + AbstractUser assignRole(String roleMongoId, AbstractUser user = userService.loggedUserFromContext) { AbstractUser actualUser = userService.addRole(user, roleMongoId) return actualUser } - AbstractUser assignRole(String roleId, String netId, AbstractUser user = userService.loggedUser, Pageable pageable = Pageable.unpaged()) { + AbstractUser assignRole(String roleId, String netId, AbstractUser user = userService.loggedUserFromContext, Pageable pageable = Pageable.unpaged()) { List nets = petriNetService.getByIdentifier(netId, pageable).content nets.forEach({ net -> user = assignRole(roleId, net, user) }) return user } - AbstractUser assignRole(String roleId, PetriNet net, AbstractUser user = userService.loggedUser) { + AbstractUser assignRole(String roleId, PetriNet net, AbstractUser user = userService.loggedUserFromContext) { AbstractUser actualUser = userService.addRole(user, net.roles.values().find { role -> role.importId == roleId }.stringId) return actualUser } - AbstractUser assignRole(String roleId, String netId, Version version, AbstractUser user = userService.loggedUser) { + AbstractUser assignRole(String roleId, String netId, Version version, AbstractUser user = userService.loggedUserFromContext) { PetriNet net = petriNetService.getPetriNet(netId, version) return assignRole(roleId, net, user) } - AbstractUser removeRole(String roleMongoId, AbstractUser user = userService.loggedUser) { + AbstractUser removeRole(String roleMongoId, AbstractUser user = userService.loggedUserFromContext) { AbstractUser actualUser = userService.removeRole(user, roleMongoId) return actualUser } - AbstractUser removeRole(String roleId, String netId, AbstractUser user = userService.loggedUser, Pageable pageable = Pageable.unpaged()) { + AbstractUser removeRole(String roleId, String netId, AbstractUser user = userService.loggedUserFromContext, Pageable pageable = Pageable.unpaged()) { List nets = petriNetService.getByIdentifier(netId, pageable).content nets.forEach({ net -> user = removeRole(roleId, net, user) }) return user } - AbstractUser removeRole(String roleId, PetriNet net, AbstractUser user = userService.loggedUser) { + AbstractUser removeRole(String roleId, PetriNet net, AbstractUser user = userService.loggedUserFromContext) { AbstractUser actualUser = userService.removeRole(user, net.roles.values().find { role -> role.importId == roleId }.stringId) return actualUser } - AbstractUser removeRole(String roleId, String netId, Version version, AbstractUser user = userService.loggedUser) { + AbstractUser removeRole(String roleId, String netId, Version version, AbstractUser user = userService.loggedUserFromContext) { PetriNet net = petriNetService.getPetriNet(netId, version) return removeRole(roleId, net, user) } @@ -1232,7 +1240,7 @@ class ActionDelegate { } AbstractUser loggedUser() { - return userService.loggedUser + return userService.loggedUserFromContext } void saveFileToField(Case targetCase, String targetTransitionId, String targetFieldId, String filename, String storagePath = null) { @@ -1536,7 +1544,7 @@ class ActionDelegate { } File exportCasesToFile(List requests, String pathName, ExportDataConfig config = null, - LoggedUser user = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), + LoggedUser user = userService.getLoggedOrSystem(), int pageSize = exportConfiguration.getMongoPageSize(), Locale locale = LocaleContextHolder.getLocale(), Boolean isIntersection = false) { @@ -1547,7 +1555,7 @@ class ActionDelegate { } OutputStream exportCases(List requests, File outFile, ExportDataConfig config = null, - LoggedUser user = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), + LoggedUser user = userService.getLoggedOrSystem(), int pageSize = exportConfiguration.getMongoPageSize(), Locale locale = LocaleContextHolder.getLocale(), Boolean isIntersection = false) { @@ -1567,7 +1575,7 @@ class ActionDelegate { } File exportTasksToFile(List requests, String pathName, ExportDataConfig config = null, - LoggedUser user = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), + LoggedUser user = userService.getLoggedOrSystem(), int pageSize = exportConfiguration.getMongoPageSize(), Locale locale = LocaleContextHolder.getLocale(), Boolean isIntersection = false) { @@ -1578,7 +1586,7 @@ class ActionDelegate { } OutputStream exportTasks(List requests, File outFile, ExportDataConfig config = null, - LoggedUser user = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), + LoggedUser user = userService.getLoggedOrSystem(), int pageSize = exportConfiguration.getMongoPageSize(), Locale locale = LocaleContextHolder.getLocale(), Boolean isIntersection = false) { @@ -1599,7 +1607,7 @@ class ActionDelegate { * @param isIntersection to decide null query handling * @return page of cases * */ - Page findCasesElastic(List requests, LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), + Page findCasesElastic(List requests, LoggedUser loggedUser = userService.getLoggedOrSystem(), int page = 1, int pageSize = 25, Locale locale = Locale.default, boolean isIntersection = false) { return elasticCaseService.search(requests, loggedUser, PageRequest.of(page, pageSize), locale, isIntersection) } @@ -1614,7 +1622,7 @@ class ActionDelegate { * @param isIntersection to decide null query handling * @return page of cases * */ - Page findCasesElastic(Map request, LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), + Page findCasesElastic(Map request, LoggedUser loggedUser = userService.getLoggedOrSystem(), int page = 1, int pageSize = 25, Locale locale = Locale.default, boolean isIntersection = false) { List requests = Collections.singletonList(new CaseSearchRequest(request)) return findCasesElastic(requests, loggedUser, page, pageSize, locale, isIntersection) @@ -1630,7 +1638,7 @@ class ActionDelegate { * @param isIntersection to decide null query handling * @return page of cases * */ - Page findTasks(List requests, LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), + Page findTasks(List requests, LoggedUser loggedUser = userService.getLoggedOrSystem(), int page = 1, int pageSize = 25, Locale locale = Locale.default, boolean isIntersection = false) { return elasticTaskService.search(requests, loggedUser, PageRequest.of(page, pageSize), locale, isIntersection) } @@ -1645,7 +1653,7 @@ class ActionDelegate { * @param isIntersection to decide null query handling * @return page of cases * */ - Page findTasks(Map request, LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), + Page findTasks(Map request, LoggedUser loggedUser = userService.getLoggedOrSystem(), int page = 1, int pageSize = 25, Locale locale = Locale.default, boolean isIntersection = false) { List requests = Collections.singletonList(new ElasticTaskSearchRequest(request)) return findTasks(requests, loggedUser, page, pageSize, locale, isIntersection) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/actions/ActionApiImpl.java b/application-engine/src/main/java/com/netgrif/application/engine/actions/ActionApiImpl.java index e96009961a2..a0b1633d696 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/actions/ActionApiImpl.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/actions/ActionApiImpl.java @@ -127,7 +127,7 @@ public CreateCaseEventOutcome createCaseByIdentifier(String identifier, String t .processIdentifier(identifier) .title(title) .color(color) - .author(resolveAbstractUser(authPrincipalDto)) + .author(ActorTransformer.toLoggedUser(resolveAbstractUser(authPrincipalDto))) .locale(locale) .params(params) .build()); @@ -158,7 +158,7 @@ public Page searchTasks(List elasticStringQueries, AuthPrincipalDt @Override public AssignTaskEventOutcome assignTask(String taskId, AuthPrincipalDto authPrincipalDto, Map params) throws TransitionNotExecutableException { Task task = taskService.findOne(taskId); - AbstractUser user = resolveAbstractUser(authPrincipalDto); + LoggedUser user = ActorTransformer.toLoggedUser(resolveAbstractUser(authPrincipalDto)); return taskService.assignTask(TaskParams.with() .task(task) .user(user) @@ -169,7 +169,7 @@ public AssignTaskEventOutcome assignTask(String taskId, AuthPrincipalDto authPri @Override public CancelTaskEventOutcome cancelTask(String taskId, AuthPrincipalDto authPrincipalDto, Map params) { Task task = taskService.findOne(taskId); - AbstractUser user = resolveAbstractUser(authPrincipalDto); + LoggedUser user = ActorTransformer.toLoggedUser(resolveAbstractUser(authPrincipalDto)); return taskService.cancelTask(TaskParams.with() .task(task) .user(user) @@ -180,7 +180,7 @@ public CancelTaskEventOutcome cancelTask(String taskId, AuthPrincipalDto authPri @Override public FinishTaskEventOutcome finishTask(String taskId, AuthPrincipalDto authPrincipalDto, Map params) throws TransitionNotExecutableException { Task task = taskService.findOne(taskId); - AbstractUser user = resolveAbstractUser(authPrincipalDto); + LoggedUser user = ActorTransformer.toLoggedUser(resolveAbstractUser(authPrincipalDto)); return taskService.finishTask(TaskParams.with() .task(task) .user(user) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/auth/service/AuthorizationService.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/service/AuthorizationService.java index 260f705d5e4..cf210345556 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/auth/service/AuthorizationService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/auth/service/AuthorizationService.java @@ -13,8 +13,6 @@ public class AuthorizationService implements IAuthorizationService { @Override public boolean hasAuthority(String authority) { - // TODO: impersonation -// LoggedUser loggedUser = userService.getLoggedUserFromContext().getSelfOrImpersonated(); LoggedUser loggedUser = userService.getLoggedUserFromContext(); return loggedUser.getAuthoritySet().stream().anyMatch(it -> it.getAuthority().equals(authority)); } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/auth/service/UserResourceHelperService.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/service/UserResourceHelperService.java deleted file mode 100644 index de08201760a..00000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/auth/service/UserResourceHelperService.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.netgrif.application.engine.auth.service; - -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.interfaces.IUserResourceHelperService; -import com.netgrif.application.engine.auth.web.responsebodies.User; -import com.netgrif.application.engine.auth.web.responsebodies.UserResource; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.util.Locale; - -@Slf4j -@Service -public class UserResourceHelperService implements IUserResourceHelperService { - - @Autowired - private UserService userService; - - @Autowired - private UserFactory userFactory; - - @Autowired - private IImpersonationService impersonationService; - - @Override - public UserResource getResource(LoggedUser loggedUser, Locale locale, boolean small) { - AbstractUser user = userService.findById(loggedUser.getStringId(), null); - // TODO: impersonation -// User result = loggedUser.isImpersonating() ? -// getLocalisedUser(user, getImpersonated(loggedUser, small), locale) : -// getLocalisedUser(user, locale); - User result = getLocalisedUser(user, locale); - return new UserResource(result, "profile"); - } - - @Override - public User getLocalisedUser(AbstractUser user, AbstractUser impersonated, Locale locale) { - User localisedUser = getLocalisedUser(user, locale); - User impersonatedUser = userFactory.getUser(impersonated, locale); - localisedUser.setImpersonated(impersonatedUser); - return localisedUser; - } - - @Override - public User getLocalisedUser(AbstractUser user, Locale locale) { - return userFactory.getUser(user, locale); - } - - // TODO: for impersonation -// protected AbstractUser getImpersonated(LoggedUser loggedUser, boolean small) { -// AbstractUser impersonated = userService.findById(loggedUser.getImpersonated().getId(), null); -// return impersonationService.reloadImpersonatedUserRoles(impersonated, loggedUser.getId()); -// } -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserResourceHelperService.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserResourceHelperService.java deleted file mode 100644 index f82c5efe437..00000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/auth/service/interfaces/IUserResourceHelperService.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.netgrif.application.engine.auth.service.interfaces; - -import com.netgrif.application.engine.auth.web.responsebodies.User; -import com.netgrif.application.engine.auth.web.responsebodies.UserResource; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; - -import java.util.Locale; - -public interface IUserResourceHelperService { - UserResource getResource(LoggedUser loggedUser, Locale locale, boolean small); - - User getLocalisedUser(AbstractUser user, AbstractUser impersonated, Locale locale); - - User getLocalisedUser(AbstractUser user, Locale locale); -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java index e1f1c07b70d..521190a1603 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/AuthenticationController.java @@ -1,19 +1,20 @@ package com.netgrif.application.engine.auth.web; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.configuration.properties.SecurityConfigurationProperties; -import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.service.InvalidUserTokenException; -import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService; +import com.netgrif.application.engine.auth.service.UserFactory; import com.netgrif.application.engine.auth.service.UserService; +import com.netgrif.application.engine.auth.service.interfaces.IRegistrationService; import com.netgrif.application.engine.auth.web.requestbodies.ChangePasswordRequest; import com.netgrif.application.engine.auth.web.requestbodies.NewUserRequest; import com.netgrif.application.engine.auth.web.requestbodies.RegistrationRequest; -import com.netgrif.application.engine.auth.service.UserFactory; +import com.netgrif.application.engine.auth.web.responsebodies.User; +import com.netgrif.application.engine.configuration.properties.SecurityConfigurationProperties; import com.netgrif.application.engine.mail.interfaces.IMailAttemptService; import com.netgrif.application.engine.mail.interfaces.IMailService; +import com.netgrif.application.engine.objects.auth.domain.AbstractUser; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.security.service.ISecurityContextService; +import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; import freemarker.template.TemplateException; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.security.SecurityRequirement; @@ -33,7 +34,9 @@ import java.io.IOException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; -import java.util.*; +import java.util.Base64; +import java.util.Locale; +import java.util.Optional; @Slf4j @RestController @@ -91,8 +94,6 @@ public MessageResource signup(@RequestBody RegistrationRequest regRequest) { @PostMapping(value = "/invite", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public MessageResource invite(@RequestBody NewUserRequest newUserRequest, Authentication auth) { try { - // TODO: impersonation -// if (!serverAuthProperties.isOpenRegistration() && (auth == null || !((LoggedUser) auth.getPrincipal()).getSelfOrImpersonated().isAdmin())) { if (!serverAuthProperties.isOpenRegistration() && (auth == null || !((LoggedUser) auth.getPrincipal()).isAdmin())) { return MessageResource.errorMessage("Only admin can invite new users!"); } @@ -148,7 +149,11 @@ public ResponseEntity login(Authentication auth, Locale locale) { return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } LoggedUser loggedUser = (LoggedUser) authentication.getPrincipal(); - return ResponseEntity.ok(userResponseFactory.getUser(userService.findById(loggedUser.getStringId(), null), locale)); + User userResponse = userResponseFactory.getUser(userService.findById(loggedUser.getStringId(), null), locale); + if (loggedUser.isImpersonating()) { + userResponse.setImpersonated(userResponseFactory.getUser(loggedUser.getImpersonatedUser(), locale)); + } + return ResponseEntity.ok(userResponse); } @Operation(summary = "Reset password") diff --git a/application-engine/src/main/java/com/netgrif/application/engine/auth/web/UserController.java b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/UserController.java index 2818d2d98ae..0f3c56a945c 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/auth/web/UserController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/auth/web/UserController.java @@ -124,8 +124,12 @@ public ResponseEntity getLoggedUser(Authentication auth, Locale locale) { log.error("Could not find user with id [{}]", loggedUser.getId(), e); return ResponseEntity.status(HttpStatus.BAD_REQUEST).build(); } + User userResponse = userFactory.getUser(user, locale); + if (loggedUser.isImpersonating()) { + userResponse.setImpersonated(userFactory.getUser(loggedUser.getImpersonatedUser(), locale)); + } - return ResponseEntity.ok(userFactory.getUser(user, locale)); + return ResponseEntity.ok(userResponse); } @ApiResponses(value = { @@ -155,9 +159,7 @@ public ResponseEntity> search(@RequestBody UserSearchRequestBody quer @GetMapping(value = "/{realmId}/{id}", produces = MediaType.APPLICATION_JSON_VALUE) public ResponseEntity getUser(@PathVariable("realmId") String realmId, @PathVariable("id") String userId, Locale locale) { LoggedUser actualUser = userService.getLoggedUserFromContext(); - // TODO: impersonation -// LoggedUser loggedUser = actualUser.getSelfOrImpersonated(); - LoggedUser loggedUser = actualUser; + LoggedUser loggedUser = actualUser.getSelfOrImpersonated(); if (!loggedUser.isAdmin() && !Objects.equals(loggedUser.getId(), userId)) { log.info("User [{}] trying to get another user with ID [{}]", actualUser.getUsername(), userId); return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); @@ -229,7 +231,7 @@ public ResponseEntity assignRolesToUser(@PathVariable("realmId" } } -// + // // @PreAuthorize("@authorizationService.hasAuthority('ADMIN')") // @Operation(summary = "Assign negative roles to the user", description = "Caller must have the ADMIN role", security = {@SecurityRequirement(name = "X-Auth-Token")}) // @PutMapping(value = "/{realmId}/{id}/negativeRole", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java b/application-engine/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java index 17a5affe1af..0f54661fb1b 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/configuration/NaeSecurityConfiguration.java @@ -1,16 +1,16 @@ package com.netgrif.application.engine.configuration; -import com.netgrif.application.engine.configuration.properties.SecurityConfigurationProperties; -import com.netgrif.application.engine.objects.auth.domain.Authority; +import com.netgrif.application.engine.auth.repository.ImpersonatorRepository; import com.netgrif.application.engine.auth.service.AuthorityService; import com.netgrif.application.engine.auth.service.UserService; +import com.netgrif.application.engine.configuration.properties.SecurityConfigurationProperties; import com.netgrif.application.engine.configuration.security.ImpersonationRequestFilter; import com.netgrif.application.engine.configuration.security.PublicAuthenticationFilter; import com.netgrif.application.engine.configuration.security.RestAuthenticationEntryPoint; import com.netgrif.application.engine.configuration.security.SecurityContextFilter; import com.netgrif.application.engine.configuration.security.filter.HostValidationRequestFilter; import com.netgrif.application.engine.configuration.security.jwt.IJwtService; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService; +import com.netgrif.application.engine.objects.auth.domain.Authority; import com.netgrif.application.engine.security.service.ISecurityContextService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -37,7 +37,6 @@ import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.filter.ForwardedHeaderFilter; -import java.util.HashSet; import java.util.List; import static org.springframework.http.HttpMethod.OPTIONS; @@ -75,7 +74,7 @@ public class NaeSecurityConfiguration extends AbstractSecurityConfiguration { private ISecurityContextService securityContextService; @Autowired - protected IImpersonationService impersonationService; + protected ImpersonatorRepository impersonatorRepository; @Autowired private List authenticationProviders; @@ -195,6 +194,6 @@ private HostValidationRequestFilter hostValidationRequestFilter() { } private ImpersonationRequestFilter impersonationRequestFilter() { - return new ImpersonationRequestFilter(impersonationService); + return new ImpersonationRequestFilter(impersonatorRepository); } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/configuration/SessionRegistryConfiguration.java b/application-engine/src/main/java/com/netgrif/application/engine/configuration/SessionRegistryConfiguration.java index 4e62ffdb6b3..de331e0eda0 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/configuration/SessionRegistryConfiguration.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/configuration/SessionRegistryConfiguration.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.configuration; -import com.netgrif.application.engine.configuration.properties.ImpersonationConfigurationProperties; +import com.netgrif.application.engine.adapter.spring.configuration.ImpersonationConfigurationProperties; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/application-engine/src/main/java/com/netgrif/application/engine/configuration/security/AuthenticationService.java b/application-engine/src/main/java/com/netgrif/application/engine/configuration/security/AuthenticationService.java index 8d9bbafb2c3..0606532acc3 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/configuration/security/AuthenticationService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/configuration/security/AuthenticationService.java @@ -1,16 +1,13 @@ package com.netgrif.application.engine.configuration.security; +import com.netgrif.application.engine.auth.repository.ImpersonatorRepository; import com.netgrif.application.engine.configuration.properties.SecurityConfigurationProperties; -import com.netgrif.application.engine.configuration.properties.ServerConfigurationProperties; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.configuration.security.interfaces.IAuthenticationService; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import jakarta.servlet.http.HttpServletRequest; import lombok.Data; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationListener; import org.springframework.context.event.EventListener; import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent; @@ -32,13 +29,13 @@ public class AuthenticationService implements IAuthenticationService, Applicatio private ConcurrentMap cache; - private final IImpersonationService impersonationService; + private final ImpersonatorRepository impersonatorRepository; private final SecurityConfigurationProperties securityConfigurationProperties; - public AuthenticationService(IImpersonationService impersonationService, + public AuthenticationService(ImpersonatorRepository impersonatorRepository, SecurityConfigurationProperties securityConfigurationProperties) { super(); - this.impersonationService = impersonationService; + this.impersonatorRepository = impersonatorRepository; this.securityConfigurationProperties = securityConfigurationProperties; cache = new ConcurrentHashMap<>(); } @@ -102,7 +99,7 @@ private void timeout(String key) { protected void resolveImpersonatorOnLogin(Object principal) { try { if (principal instanceof LoggedUser) { - impersonationService.removeImpersonator(((LoggedUser) principal).getStringId()); + impersonatorRepository.deleteById(((LoggedUser) principal).getStringId()); } } catch (Exception e) { log.warn("Failed to resolve impersonator " + principal, e); @@ -111,10 +108,11 @@ protected void resolveImpersonatorOnLogin(Object principal) { protected void resolveImpersonatorOnLogout(Object principal) { try { - // TODO: impersonation -// if (principal instanceof LoggedUser && ((LoggedUser) principal).isImpersonating()) { -// impersonationService.onSessionDestroy((LoggedUser) principal); -// } + if (principal instanceof LoggedUser && ((LoggedUser) principal).isImpersonating()) { + impersonatorRepository.deleteById(((LoggedUser) principal).getStringId()); + // TODO: event? +// publisher.publishEvent(new ImpersonationEvent(impersonator, impersonator.getImpersonated(), RunPhase.STOP)); + } } catch (Exception e) { log.warn("Failed to resolve impersonator " + principal, e); } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/configuration/security/ImpersonationRequestFilter.java b/application-engine/src/main/java/com/netgrif/application/engine/configuration/security/ImpersonationRequestFilter.java index a50d2b98753..af7627a3b03 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/configuration/security/ImpersonationRequestFilter.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/configuration/security/ImpersonationRequestFilter.java @@ -1,9 +1,12 @@ package com.netgrif.application.engine.configuration.security; +import com.netgrif.application.engine.auth.domain.Impersonator; +import com.netgrif.application.engine.auth.repository.ImpersonatorRepository; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.impersonation.domain.Impersonator; -import com.netgrif.application.engine.impersonation.domain.repository.ImpersonatorRepository; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.Authentication; @@ -11,10 +14,6 @@ import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler; import org.springframework.web.filter.OncePerRequestFilter; -import jakarta.servlet.FilterChain; -import jakarta.servlet.ServletException; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.time.LocalDateTime; import java.util.Optional; @@ -23,10 +22,10 @@ public class ImpersonationRequestFilter extends OncePerRequestFilter { public static final Logger log = LoggerFactory.getLogger(ImpersonationRequestFilter.class); - private final IImpersonationService impersonationService; + private final ImpersonatorRepository impersonatorRepository; - public ImpersonationRequestFilter(IImpersonationService impersonationService) { - this.impersonationService = impersonationService; + public ImpersonationRequestFilter(ImpersonatorRepository impersonatorRepository) { + this.impersonatorRepository = impersonatorRepository; } @Override @@ -46,15 +45,14 @@ public void doFilterInternal(HttpServletRequest servletRequest, HttpServletRespo protected void handleImpersonator(LoggedUser loggedUser, HttpServletRequest servletRequest, HttpServletResponse servletResponse) { try { - // TODO: impersonation -// if (!loggedUser.isImpersonating()) { -// return; -// } -// Optional imp = impersonationService.findImpersonator(loggedUser.getId()); -// if (loggedUser.isImpersonating() && (imp.isEmpty() || !isValid(imp.get()))) { -// imp.ifPresent(imper -> impersonationService.removeImpersonator(loggedUser.getId())); -// logout(servletRequest, servletResponse); -// } + if (!loggedUser.isImpersonating()) { + return; + } + Optional imp = impersonatorRepository.findById(loggedUser.getStringId()); + if (loggedUser.isImpersonating() && (imp.isEmpty() || !isValid(imp.get()))) { + imp.ifPresent(imper -> impersonatorRepository.deleteById(loggedUser.getStringId())); + logout(servletRequest, servletResponse); + } } catch (Exception e) { log.error("ImpersonationRequestFilter error {}", e.getMessage(), e); } @@ -62,8 +60,9 @@ protected void handleImpersonator(LoggedUser loggedUser, HttpServletRequest serv protected void handleImpersonated(LoggedUser loggedUser, HttpServletRequest servletRequest) { try { - log.debug("Filtering request {}, {}", servletRequest.getRequestURI(), loggedUser.getUsername()); - impersonationService.removeImpersonatorByImpersonated(loggedUser.getStringId()); + log.debug("Filtering request " + servletRequest.getRequestURI() + ", " + loggedUser.getUsername()); + Optional impersonatorObject = impersonatorRepository.findByImpersonatedId(loggedUser.getStringId()); + impersonatorObject.ifPresent(impersonatorRepository::delete); } catch (Exception e) { log.error("Failed to resolve impersonators for {}, {}", loggedUser.getUsername(), e.getMessage(), e); } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseService.java b/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseService.java index f7aba77b5f7..ff29c49f1e3 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticCaseService.java @@ -4,26 +4,26 @@ import co.elastic.clients.elasticsearch._types.FieldValue; import co.elastic.clients.elasticsearch._types.mapping.FieldType; import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery; +import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders; import co.elastic.clients.elasticsearch._types.query_dsl.QueryStringQuery; import co.elastic.clients.elasticsearch._types.query_dsl.TermsQueryField; -import co.elastic.clients.elasticsearch._types.query_dsl.QueryBuilders; import co.elastic.clients.elasticsearch.core.bulk.BulkOperation; import com.netgrif.application.engine.configuration.properties.DataConfigurationProperties; import com.netgrif.application.engine.elastic.domain.BulkOperationWrapper; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.objects.elastic.domain.ElasticCase; import com.netgrif.application.engine.elastic.domain.ElasticCaseRepository; import com.netgrif.application.engine.elastic.domain.ElasticQueryConstants; import com.netgrif.application.engine.elastic.service.executors.Executor; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCasePrioritySearch; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; +import com.netgrif.application.engine.objects.elastic.domain.ElasticCase; import com.netgrif.application.engine.objects.event.events.workflow.IndexCaseEvent; import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch; +import com.netgrif.application.engine.objects.workflow.domain.Case; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.petrinet.web.responsebodies.PetriNetReference; import com.netgrif.application.engine.utils.FullPageRequest; -import com.netgrif.application.engine.objects.workflow.domain.Case; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; import jakarta.annotation.PreDestroy; import org.slf4j.Logger; @@ -37,7 +37,7 @@ import org.springframework.data.elasticsearch.core.SearchHitSupport; import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates; -import org.springframework.data.elasticsearch.core.query.*; +import org.springframework.data.elasticsearch.core.query.Order; import org.springframework.stereotype.Service; import java.util.*; @@ -131,12 +131,12 @@ public Page search(List requests, LoggedUser user, Page if (requests == null) { throw new IllegalArgumentException("Request can not be null!"); } - log.debug("Searching for query with logged user [{}]", user.getId()); - // TODO: impersonation -// LoggedUser loggedOrImpersonated = user.getSelfOrImpersonated(); - LoggedUser loggedOrImpersonated = user; + log.debug("Searching for query with logged user [{}]", user.getSelfOrImpersonatedStringId()); // pageable = resolveUnmappedSortAttributes(pageable); - NativeQuery query = buildQuery(requests, loggedOrImpersonated, pageable, locale, isIntersection); + if (user.isProcessAccessDeny()) { + return new PageImpl<>(Collections.emptyList(), pageable, 0); + } + NativeQuery query = buildQuery(requests, user, pageable, locale, isIntersection); List casePage; long total; if (query != null) { @@ -158,11 +158,11 @@ public long count(List requests, LoggedUser user, Locale loca if (requests == null) { throw new IllegalArgumentException("Request can not be null!"); } + if (user.isProcessAccessDeny()) { + return 0; + } - // TODO: impersonation -// LoggedUser loggedOrImpersonated = user.getSelfOrImpersonated(); - LoggedUser loggedOrImpersonated = user; - NativeQuery query = buildQuery(requests, loggedOrImpersonated, new FullPageRequest(), locale, isIntersection); + NativeQuery query = buildQuery(requests, user, new FullPageRequest(), locale, isIntersection); if (query != null) { return template.count(query, com.netgrif.application.engine.adapter.spring.elastic.domain.ElasticCase.class); } else { @@ -171,7 +171,7 @@ public long count(List requests, LoggedUser user, Locale loca } protected NativeQuery buildQuery(List requests, LoggedUser user, Pageable pageable, Locale locale, Boolean isIntersection) { - List singleQueries = requests.stream().map(request -> buildSingleQuery(request, user, locale)).collect(Collectors.toList()); + List singleQueries = requests.stream().map(request -> buildSingleQuery(request, user.getSelfOrImpersonated(), locale)).collect(Collectors.toList()); if (isIntersection && !singleQueries.stream().allMatch(Objects::nonNull)) { // one of the queries evaluates to empty set => the entire result is an empty set @@ -186,6 +186,10 @@ protected NativeQuery buildQuery(List requests, LoggedUser us BinaryOperator reductionOperation = isIntersection ? (a, b) -> a.must(b.build()._toQuery()) : (a, b) -> a.should(b.build()._toQuery()); BoolQuery.Builder query = singleQueries.stream().reduce(new BoolQuery.Builder(), reductionOperation); + BoolQuery.Builder impersonatedProcessesQuery = buildAllowedProcessesQuery(user); + if (impersonatedProcessesQuery != null) { + query.filter(impersonatedProcessesQuery.build()._toQuery()); + } NativeQueryBuilder builder = new NativeQueryBuilder() .withQuery(query.build()._toQuery()) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java index d678c86eeae..ed154c8c9f9 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticPetriNetService.java @@ -111,11 +111,8 @@ public Page search(PetriNetSearch requests, LoggedUser user, if (requests == null) { throw new IllegalArgumentException("Request can not be null!"); } - log.debug("Searching for PetriNet query with logged user [{}]", user.getId()); - // TODO: impersonation -// LoggedUser loggedOrImpersonated = user.getSelfOrImpersonated(); - LoggedUser loggedOrImpersonated = user; - NativeQuery query = buildQuery(requests, loggedOrImpersonated, pageable, locale, isIntersection); + log.debug("Searching for PetriNet query with logged user [{}]", user.getSelfOrImpersonatedStringId()); + NativeQuery query = buildQuery(requests, user, pageable, locale, isIntersection); List netPage; long total; if (query != null) { @@ -161,7 +158,11 @@ protected BoolQuery.Builder buildSingleQuery(PetriNetSearch request, LoggedUser BoolQuery.Builder query = new BoolQuery.Builder(); buildFullTextQuery(request, query); - boolean resultAlwaysEmpty = buildGroupQuery(request, user, locale, query); + boolean impersonatedAccessDenied = buildImpersonatedProcessesQuery(user, query); + if (impersonatedAccessDenied) { + return null; + } + boolean resultAlwaysEmpty = buildGroupQuery(request, user.getSelfOrImpersonated(), locale, query); if (resultAlwaysEmpty) { return null; } @@ -202,4 +203,28 @@ protected boolean buildGroupQuery(PetriNetSearch request, LoggedUser user, Local query.filter(groupQuery.build()._toQuery()); return false; } + + protected boolean buildImpersonatedProcessesQuery(LoggedUser loggedUser, BoolQuery.Builder query) { + if (loggedUser.isAdmin() || !loggedUser.isImpersonating()) { + return false; + } + if (loggedUser.isProcessAccessDeny()) { + return true; + } + if (loggedUser.getImpersonatedProcesses() == null || loggedUser.getImpersonatedProcesses().isEmpty()) { + return false; + } + BoolQuery.Builder impersonatedProcessesQuery = new BoolQuery.Builder(); + if (loggedUser.isImpersonatedProcessesListAllowing()) { + loggedUser.getImpersonatedProcesses().stream() + .map(processIdentifier -> termQuery("identifier", processIdentifier)) + .forEach(termQuery -> impersonatedProcessesQuery.should(termQuery._toQuery())); + } else { + loggedUser.getImpersonatedProcesses().stream() + .map(processIdentifier -> termQuery("identifier", processIdentifier)) + .forEach(termQuery -> impersonatedProcessesQuery.mustNot(termQuery._toQuery())); + } + query.filter(impersonatedProcessesQuery.build()._toQuery()); + return false; + } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskService.java b/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskService.java index 6d554236b6a..ffbd342518a 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticTaskService.java @@ -4,28 +4,26 @@ import co.elastic.clients.elasticsearch._types.query_dsl.*; import com.google.common.collect.ImmutableList; import com.netgrif.application.engine.configuration.properties.DataConfigurationProperties; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.objects.elastic.domain.ElasticJob; import com.netgrif.application.engine.elastic.domain.ElasticQueryConstants; -import com.netgrif.application.engine.objects.elastic.domain.ElasticTask; import com.netgrif.application.engine.elastic.domain.ElasticTaskJob; import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService; import com.netgrif.application.engine.elastic.web.requestbodies.ElasticTaskSearchRequest; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; +import com.netgrif.application.engine.objects.elastic.domain.ElasticJob; +import com.netgrif.application.engine.objects.elastic.domain.ElasticTask; import com.netgrif.application.engine.objects.event.events.task.IndexTaskEvent; import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch; +import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; +import com.netgrif.application.engine.objects.workflow.domain.Task; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.petrinet.web.responsebodies.PetriNetReference; import com.netgrif.application.engine.utils.FullPageRequest; -import com.netgrif.application.engine.objects.workflow.domain.Task; import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; import com.netgrif.application.engine.workflow.web.requestbodies.TaskSearchRequest; -import com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.PetriNet; import com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.TaskSearchCaseRequest; -import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.annotation.Lazy; import org.springframework.data.domain.Page; @@ -42,7 +40,6 @@ import java.util.*; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.function.BinaryOperator; import java.util.stream.Collectors; @@ -141,8 +138,9 @@ public void indexNow(ElasticTask task) { @Override public Page search(List requests, LoggedUser user, Pageable pageable, Locale locale, Boolean isIntersection) { - // TODO: impersonation -// NativeQuery query = buildQuery(requests, user.getSelfOrImpersonated(), pageable, locale, isIntersection); + if (user.isProcessAccessDeny()) { + return new PageImpl<>(Collections.emptyList(), pageable, 0); + } NativeQuery query = buildQuery(requests, user, pageable, locale, isIntersection); List taskPage; long total; @@ -161,8 +159,9 @@ public Page search(List requests, LoggedUser use @Override public long count(List requests, LoggedUser user, Locale locale, Boolean isIntersection) { - // TODO: impersonation -// NativeQuery query = buildQuery(requests, user.getSelfOrImpersonated(), new FullPageRequest(), locale, isIntersection); + if (user.isProcessAccessDeny()) { + return 0; + } NativeQuery query = buildQuery(requests, user, new FullPageRequest(), locale, isIntersection); if (query != null) { return template.count(query, com.netgrif.application.engine.adapter.spring.elastic.domain.ElasticTask.class); @@ -172,7 +171,7 @@ public long count(List requests, LoggedUser user, Loca } protected NativeQuery buildQuery(List requests, LoggedUser user, Pageable pageable, Locale locale, Boolean isIntersection) { - List singleQueries = requests.stream().map(request -> buildSingleQuery(request, user, locale)).collect(Collectors.toList()); + List singleQueries = requests.stream().map(request -> buildSingleQuery(request, user.getSelfOrImpersonated(), locale)).collect(Collectors.toList()); if (isIntersection && !singleQueries.stream().allMatch(Objects::nonNull)) { // one of the queries evaluates to empty set => the entire result is an empty set @@ -187,6 +186,10 @@ protected NativeQuery buildQuery(List requests, Logged BinaryOperator reductionOperation = isIntersection ? (a, b) -> a.must(b.build()._toQuery()) : (a, b) -> a.should(b.build()._toQuery()); BoolQuery.Builder query = singleQueries.stream().reduce(new BoolQuery.Builder(), reductionOperation); + BoolQuery.Builder impersonatedProcessesQuery = buildAllowedProcessesQuery(user); + if (impersonatedProcessesQuery != null) { + query.filter(impersonatedProcessesQuery.build()._toQuery()); + } NativeQueryBuilder builder = new NativeQueryBuilder(); return builder diff --git a/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticViewPermissionService.java b/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticViewPermissionService.java index e8362e13fc3..af06c41d982 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticViewPermissionService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/elastic/service/ElasticViewPermissionService.java @@ -112,4 +112,27 @@ private BoolQuery union(BoolQuery setA, BoolQuery setB) { .minimumShouldMatch(String.valueOf(1)) .build(); } + + protected BoolQuery.Builder buildAllowedProcessesQuery(LoggedUser loggedUser) { + if (loggedUser.isAdmin() || !loggedUser.isImpersonating()) { + return null; + } + if (loggedUser.isProcessAccessDeny()) { + return null; + } + if (loggedUser.getImpersonatedProcesses() == null || loggedUser.getImpersonatedProcesses().isEmpty()) { + return null; + } + TermsQueryField identifiers = new TermsQueryField.Builder() + .value(loggedUser.getImpersonatedProcesses().stream().map(FieldValue::of).collect(Collectors.toList())) + .build(); + + BoolQuery.Builder petriNetQuery = new BoolQuery.Builder(); + if (loggedUser.isImpersonatedProcessesListAllowing()) { + petriNetQuery.should(QueryBuilders.terms(term -> term.field("processIdentifier").terms(identifiers))); + } else { + petriNetQuery.mustNot(QueryBuilders.terms(term -> term.field("processIdentifier").terms(identifiers))); + } + return petriNetQuery; + } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java b/application-engine/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java index 5cc48601259..2dd26b3f523 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/elastic/web/ElasticController.java @@ -1,10 +1,10 @@ package com.netgrif.application.engine.elastic.web; import com.netgrif.application.engine.configuration.properties.DataConfigurationProperties; +import com.netgrif.application.engine.elastic.service.ReindexingTask; import com.netgrif.application.engine.elastic.service.interfaces.IElasticIndexService; import com.netgrif.application.engine.elastic.web.requestbodies.IndexParams; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.elastic.service.ReindexingTask; import com.netgrif.application.engine.workflow.service.CaseSearchService; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; import com.netgrif.application.engine.workflow.web.responsebodies.MessageResource; @@ -18,7 +18,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.hateoas.MediaTypes; import org.springframework.http.MediaType; @@ -102,8 +101,10 @@ public MessageResource reindex(@RequestBody Map searchBody, Auth for (int page = 0; page < numOfPages; page++) { log.info("Indexing page {}", page + 1); - Predicate predicate = searchService.buildQuery(searchBody, user, locale); - reindexingTask.forceReindexPage(predicate, page, numOfPages); + if (!user.isProcessAccessDeny()) { + Predicate predicate = searchService.buildQuery(searchBody, user, locale); + reindexingTask.forceReindexPage(predicate, page, numOfPages); + } } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/export/service/ExportService.java b/application-engine/src/main/java/com/netgrif/application/engine/export/service/ExportService.java index 2e806ae1ebe..443f3b8623c 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/export/service/ExportService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/export/service/ExportService.java @@ -1,7 +1,5 @@ package com.netgrif.application.engine.export.service; -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService; @@ -10,6 +8,7 @@ import com.netgrif.application.engine.export.configuration.ExportConfiguration; import com.netgrif.application.engine.export.domain.ExportDataConfig; import com.netgrif.application.engine.export.service.interfaces.IExportService; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.petrinet.domain.I18nString; import com.netgrif.application.engine.objects.petrinet.domain.dataset.*; import com.netgrif.application.engine.objects.workflow.domain.Case; @@ -102,12 +101,12 @@ public OutputStream fillCsvCaseData(Predicate predicate, File outFile, ExportDat @Override public OutputStream fillCsvCaseData(List requests, File outFile) throws FileNotFoundException { - return fillCsvCaseData(requests, outFile, null, ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); + return fillCsvCaseData(requests, outFile, null, userService.getLoggedOrSystem(), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); } @Override public OutputStream fillCsvCaseData(List requests, File outFile, ExportDataConfig config) throws FileNotFoundException { - return fillCsvCaseData(requests, outFile, config, ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); + return fillCsvCaseData(requests, outFile, config, userService.getLoggedOrSystem(), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); } @Override @@ -159,12 +158,12 @@ public OutputStream buildCaseCsv(List exportCases, ExportDataConfig config @Override public OutputStream fillCsvTaskData(List requests, File outFile) throws FileNotFoundException { - return fillCsvTaskData(requests, outFile, null, ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); + return fillCsvTaskData(requests, outFile, null, userService.getLoggedOrSystem(), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); } @Override public OutputStream fillCsvTaskData(List requests, File outFile, ExportDataConfig config) throws FileNotFoundException { - return fillCsvTaskData(requests, outFile, config, ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); + return fillCsvTaskData(requests, outFile, config, userService.getLoggedOrSystem(), exportConfiguration.getMongoPageSize(), LocaleContextHolder.getLocale(), false); } @Override diff --git a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/exceptions/IllegalImpersonationAttemptException.java b/application-engine/src/main/java/com/netgrif/application/engine/impersonation/exceptions/IllegalImpersonationAttemptException.java deleted file mode 100644 index c75d0aebaf0..00000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/exceptions/IllegalImpersonationAttemptException.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.netgrif.application.engine.impersonation.exceptions; - -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; - -public class IllegalImpersonationAttemptException extends Exception { - - public IllegalImpersonationAttemptException(LoggedUser loggedUser, String id) { - super(loggedUser.getName() + " cannot impersonate user or config with ID " + id); - } - - public IllegalImpersonationAttemptException(String message) { - super(message); - } -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/exceptions/ImpersonatedUserHasSessionException.java b/application-engine/src/main/java/com/netgrif/application/engine/impersonation/exceptions/ImpersonatedUserHasSessionException.java deleted file mode 100644 index 3f28bf0ff78..00000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/exceptions/ImpersonatedUserHasSessionException.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.netgrif.application.engine.impersonation.exceptions; - -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import lombok.Getter; - -public class ImpersonatedUserHasSessionException extends Exception { - - @Getter - private final boolean isImpersonated; - - public ImpersonatedUserHasSessionException(LoggedUser impersonatedLogged, boolean isImpersonated) { - super(impersonatedLogged.getName() + " has an existing session!"); - this.isImpersonated = isImpersonated; - } -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationAuthorizationService.java b/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationAuthorizationService.java index 6898d62f6b3..e69de29bb2d 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationAuthorizationService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationAuthorizationService.java @@ -1,207 +0,0 @@ -package com.netgrif.application.engine.impersonation.service; - -import com.netgrif.application.engine.configuration.properties.ImpersonationConfigurationProperties; -import com.netgrif.application.engine.objects.auth.domain.Authority; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService; -import com.netgrif.application.engine.auth.service.AuthorityService; -import com.netgrif.application.engine.auth.service.UserService; -import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; -import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationAuthorizationService; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; -import com.netgrif.application.engine.objects.petrinet.domain.dataset.UserFieldValue; -import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; -import com.netgrif.application.engine.objects.workflow.domain.Case; -import com.netgrif.application.engine.objects.workflow.domain.DataField; -import com.netgrif.application.engine.utils.DateUtils; -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.PageImpl; -import org.springframework.data.domain.PageRequest; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; - -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.util.*; -import java.util.stream.Collectors; - -import static com.netgrif.application.engine.startup.runner.ImpersonationRunner.IMPERSONATION_CONFIG_PETRI_NET_IDENTIFIER; - -@Service -public class ImpersonationAuthorizationService implements IImpersonationAuthorizationService { - - @Autowired - protected ImpersonationConfigurationProperties properties; - - @Autowired - protected UserService userService; - - @Autowired - protected IElasticCaseService elasticCaseService; - - @Autowired - protected AuthorityService authorityService; - - @Autowired - protected IWorkflowService workflowService; - - @Autowired - protected ProcessRoleService processRoleService; - - @Override - public Page getConfiguredImpersonationUsers(String query, LoggedUser impersonator, Pageable pageable) { - if (impersonator.isAdmin()) { - return userService.searchAllCoMembers(query, null, null, impersonator, pageable); - - } else { - Page cases = searchConfigs(impersonator.getStringId(), pageable); - List users = cases.getContent().stream() - .map(c -> ((UserFieldValue) c.getDataSet().get("impersonated").getValue()).getId()) - .distinct() - .map(id -> userService.findById(id, null)) - .collect(Collectors.toList()); - return new PageImpl<>(users, pageable, cases.getTotalElements()); - } - } - - @Override - public boolean canImpersonate(LoggedUser impersonator, String configId) { - Case config = getConfig(configId); - return isValidAndContainsUser(config, impersonator.getStringId()); - } - - @Override - public boolean canImpersonateUser(LoggedUser impersonator, String userId) { - AbstractUser impersonated = userService.findById(userId, null); - return impersonator.isAdmin() || !searchConfigs(impersonator.getStringId(), impersonated.getStringId()).isEmpty(); - } - - @Override - public Page searchConfigs(String impersonatorId, Pageable pageable) { - return findCases(makeRequest(impersonatorId, null), pageable); - } - - @Override - public List searchConfigs(String impersonatorId, String impersonatedId) { - Page cases = findCases(makeRequest(impersonatorId, impersonatedId), PageRequest.of(0, properties.getConfigsPerUser())); - return cases.getContent(); - } - - @Override - public List getAuthorities(Collection configs, AbstractUser impersonated) { - if (configs.isEmpty()) { - return new ArrayList<>(); - } - Set authIds = extractSetFromField(configs, "impersonated_authorities"); - return authorityService.findAllByIds(new ArrayList<>(authIds), Pageable.unpaged()).stream() - .filter(configAuth -> impersonated.getAuthoritySet().stream().anyMatch(userAuth -> userAuth.getStringId().equals(configAuth.getStringId()))) - .collect(Collectors.toList()); - } - - @Override - public List getRoles(Collection configs, AbstractUser impersonated) { - List impersonatedRoles = new ArrayList<>(); - impersonatedRoles.add(processRoleService.getDefaultRole()); - if (configs.isEmpty()) { - return impersonatedRoles; - } - Set roleIds = extractSetFromField(configs, "impersonated_roles"); - impersonatedRoles.addAll((processRoleService.findByIds(roleIds)).stream() - .filter(configRole -> impersonated.getProcessRoles().stream().anyMatch(userRole -> userRole.getStringId().equals(configRole.getStringId()))) - .toList()); - return impersonatedRoles; - } - - @Override - public Case getConfig(String configId) { - return workflowService.findOne(configId); - } - - @Override - public String getImpersonatedUserId(Case config) { - return ((UserFieldValue) config.getDataSet().get("impersonated").getValue()).getId(); - } - - @Override - public LocalDateTime getValidUntil(Case config) { - return parseTime(config, "valid_to"); - } - - protected CaseSearchRequest makeRequest(String impersonatorId, String impersonatedId) { - CaseSearchRequest request = new CaseSearchRequest(); - List queries = new ArrayList<>(); - request.process = Collections.singletonList(new CaseSearchRequest.PetriNet(IMPERSONATION_CONFIG_PETRI_NET_IDENTIFIER)); - queries.add("(dataSet.impersonators.keyValue:" + impersonatorId + ")"); - queries.add("(dataSet.is_active.booleanValue:true)"); - queries.addAll(validityQueries()); - if (impersonatedId != null) { - queries.add("(dataSet.impersonated.actorIdValue.keyword:" + impersonatedId + ")"); - } - request.query = combineQueries(queries); - return request; - } - - protected List validityQueries() { - List queries = new ArrayList<>(); - queries.add("((!(_exists_:dataSet.valid_from.timestampValue)) OR (dataSet.valid_from.timestampValue:<" + DateUtils.localDateTimeToDate(LocalDateTime.now()).getTime() + "))"); - queries.add("((!(_exists_:dataSet.valid_to.timestampValue)) OR (dataSet.valid_to.timestampValue:>" + DateUtils.localDateTimeToDate(LocalDateTime.now()).getTime() + "))"); - return queries; - } - - protected String combineQueries(List queries) { - return "(" + String.join(" AND ", queries) + ")"; - } - - protected Page findCases(CaseSearchRequest request, Pageable pageable) { - return elasticCaseService.search(Collections.singletonList(request), ActorTransformer.toLoggedUser(userService.getSystem()), pageable, Locale.getDefault(), false); - } - - protected boolean isValidAndContainsUser(Case config, String id) { - Object value = config.getFieldValue("impersonators"); - if (!(value instanceof Collection)) { - return false; - } - LocalDateTime now = LocalDateTime.now(); - return (((Collection) value).contains(id)) && - ((Boolean) config.getFieldValue("is_active")) && - validateTime(parseTime(config, "valid_from"), now) && - validateTime(now, parseTime(config, "valid_to")); - - } - - protected boolean validateTime(LocalDateTime first, LocalDateTime second) { - if (first == null || second == null) { - return true; - } - return first.isBefore(second) || first.equals(second); - } - - protected Set extractSetFromField(Collection cases, String fieldId) { - return cases.stream() - .map(caze -> getMultichoiceValue(caze.getDataField(fieldId))) - .flatMap(List::stream) - .collect(Collectors.toSet()); - } - - protected List getMultichoiceValue(DataField field) { - if (field.getValue() == null || !(field.getValue() instanceof List)) { - return new ArrayList<>(); - } - return (List) field.getValue(); - } - - protected LocalDateTime parseTime(Case config, String field) { - Object val = config.getFieldValue(field); - if (val == null) { - return null; - } - if (val instanceof Date) { - return LocalDateTime.ofInstant(((Date) val).toInstant(), ZoneId.systemDefault()); - } - return (LocalDateTime) val; - } -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationService.java b/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationService.java deleted file mode 100644 index 62a6567054f..00000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationService.java +++ /dev/null @@ -1,195 +0,0 @@ -package com.netgrif.application.engine.impersonation.service; - -import com.netgrif.application.engine.adapter.spring.auth.domain.AuthorityImpl; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; -import com.netgrif.application.engine.objects.auth.domain.Authority; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.UserService; -import com.netgrif.application.engine.configuration.properties.ImpersonationConfigurationProperties; -import com.netgrif.application.engine.objects.event.RunPhase; -import com.netgrif.application.engine.objects.event.events.user.ImpersonationEvent; -import com.netgrif.application.engine.impersonation.domain.Impersonator; -import com.netgrif.application.engine.impersonation.domain.repository.ImpersonatorRepository; -import com.netgrif.application.engine.impersonation.exceptions.ImpersonatedUserHasSessionException; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationAuthorizationService; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationSessionService; -import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; -import com.netgrif.application.engine.security.service.ISecurityContextService; -import com.netgrif.application.engine.objects.workflow.domain.Case; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.stereotype.Service; - -import java.time.LocalDateTime; -import java.util.*; -import java.util.stream.Collectors; - -@Slf4j -@Service -public class ImpersonationService implements IImpersonationService { - - @Autowired - protected ImpersonationConfigurationProperties properties; - - @Autowired - protected UserService userService; - - @Autowired - protected ApplicationEventPublisher publisher; - - @Autowired - protected IImpersonationSessionService sessionService; - - @Autowired - protected ISecurityContextService securityContextService; - - @Autowired - protected ImpersonatorRepository impersonatorRepository; - - @Autowired - protected IImpersonationAuthorizationService impersonationAuthorizationService; - - @Override - public LoggedUser impersonateUser(String impersonatedId) throws ImpersonatedUserHasSessionException { - if (!properties.isEnabled()) { - throw new IllegalArgumentException("Impersonation is not enabled in app properties"); - } - LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedUser()); - AbstractUser impersonated = userService.findById(impersonatedId, null); - - List configs = impersonationAuthorizationService.searchConfigs(loggedUser.getStringId(), impersonated.getStringId()); - LoggedUser impersonatedLogged = ActorTransformer.toLoggedUser(applyRolesAndAuthorities(impersonated, loggedUser.getStringId(), configs)); - - return doImpersonate(loggedUser, impersonatedLogged, configs); - } - - @Override - public LoggedUser impersonateByConfig(String configId) throws ImpersonatedUserHasSessionException { - if (!properties.isEnabled()) { - throw new IllegalArgumentException("Impersonation is not enabled in app properties"); - } - Case config = impersonationAuthorizationService.getConfig(configId); - LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedUser()); - AbstractUser impersonated = userService.findById(impersonationAuthorizationService.getImpersonatedUserId(config), null); - - LoggedUser impersonatedLogged = ActorTransformer.toLoggedUser(applyRolesAndAuthorities(impersonated, loggedUser.getStringId(), Collections.singletonList(config))); - return doImpersonate(loggedUser, impersonatedLogged, Collections.singletonList(config)); - } - - protected LoggedUser doImpersonate(LoggedUser loggedUser, LoggedUser impersonatedLogged, List configs) throws ImpersonatedUserHasSessionException { - if (sessionService.existsSession(impersonatedLogged.getUsername())) { - throw new ImpersonatedUserHasSessionException(impersonatedLogged, false); - - } else if (sessionService.isImpersonated(impersonatedLogged.getStringId())) { - throw new ImpersonatedUserHasSessionException(impersonatedLogged, true); - } - updateImpersonatedId(loggedUser, impersonatedLogged.getStringId(), configs); - // TODO: impersonation -// loggedUser.impersonate(impersonatedLogged); - securityContextService.saveToken(loggedUser.getStringId()); - securityContextService.reloadSecurityContext(loggedUser); - log.info(loggedUser.getName() + " has just impersonated user " + impersonatedLogged.getName()); - publisher.publishEvent(new ImpersonationEvent(loggedUser, impersonatedLogged, RunPhase.START)); - return loggedUser; - } - - @Override - public Optional findImpersonator(String impersonatorId) { - return impersonatorRepository.findById(impersonatorId); - } - - @Override - public void removeImpersonatorByImpersonated(String impersonatedId) { - impersonatorRepository.findByImpersonatedId(impersonatedId).ifPresent(impersonatorRepository::delete); - } - - @Override - public void removeImpersonator(String impersonatorId) { - impersonatorRepository.deleteById(impersonatorId); - } - - @Override - public LoggedUser endImpersonation() { - return endImpersonation(userService.getLoggedUserFromContext()); - } - - @Override - public LoggedUser endImpersonation(LoggedUser impersonator) { - // TODO: impersonation -// LoggedUser impersonated = impersonator.getImpersonated(); - LoggedUser impersonated = impersonator; - removeImpersonator(impersonator.getStringId()); - // TODO: impersonation -// impersonator.clearImpersonated(); - log.info(impersonator.getName() + " has stopped impersonating user " + impersonated.getName()); - securityContextService.saveToken(impersonator.getStringId()); - securityContextService.reloadSecurityContext(impersonator); - publisher.publishEvent(new ImpersonationEvent(impersonator, impersonated, RunPhase.STOP)); - return impersonator; - } - - @Override - public void onSessionDestroy(LoggedUser impersonator) { - removeImpersonator(impersonator.getStringId()); - // TODO: impersonation -// log.info(impersonator.getFullName() + " has logged out and stopped impersonating user " + impersonator.getImpersonated().getFullName()); - log.info(impersonator.getName() + " has logged out and stopped impersonating user " + impersonator.getName()); - // TODO: impersonation -// publisher.publishEvent(new ImpersonationEvent(impersonator, impersonator.getImpersonated(), RunPhase.STOP)); - publisher.publishEvent(new ImpersonationEvent(impersonator, impersonator, RunPhase.STOP)); - } - - @Override - public AbstractUser reloadImpersonatedUserRoles(AbstractUser impersonated, String impersonatorId) { - Optional context = impersonatorRepository.findByImpersonatedId(impersonated.getStringId()); - if (context.isPresent()) { - List configs = context.get().getConfigIds().stream() - .map(id -> impersonationAuthorizationService.getConfig(id)) - .collect(Collectors.toList()); - return applyRolesAndAuthorities(impersonated, impersonatorId, configs); - } - return impersonated; - } - - @Override - public AbstractUser applyRolesAndAuthorities(AbstractUser impersonated, String impersonatorId, List configs) { - if ((Boolean) userService.findById(impersonatorId, null).getAuthoritySet().contains(new AuthorityImpl(Authority.admin))) { - return impersonated; - } - List authorities = impersonationAuthorizationService.getAuthorities(configs, impersonated); - List roles = impersonationAuthorizationService.getRoles(configs, impersonated); - - impersonated.setAuthoritySet(new HashSet<>(authorities)); - impersonated.setProcessRoles(new HashSet<>(roles)); - - return impersonated; - } - - protected void updateImpersonatedId(LoggedUser loggedUser, String id, List configs) { - Map configTimeMap = new HashMap<>(); - configs.forEach((config) -> configTimeMap.put(config, getConfigValidToTime(config))); - Optional> earliestEndingConfig = configTimeMap - .entrySet().stream() - .filter(it -> it.getValue() != null) - .min(Map.Entry.comparingByValue()); - updateImpersonatedId(loggedUser, id, configs, earliestEndingConfig.map(Map.Entry::getValue).orElse(null)); - } - - protected void updateImpersonatedId(LoggedUser loggedUser, String id, List configs, LocalDateTime validUntil) { - removeImpersonator(loggedUser.getStringId()); - impersonatorRepository.save(new Impersonator(loggedUser.getStringId(), id, - configs.stream().map(Case::getStringId).collect(Collectors.toList()), - LocalDateTime.now(), validUntil)); - } - - protected LocalDateTime getConfigValidToTime(Case config) { - LocalDateTime limitTime = null; - if (config != null) { - limitTime = impersonationAuthorizationService.getValidUntil(config); - } - return limitTime; - } -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationSessionService.java b/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationSessionService.java deleted file mode 100644 index 73dbb736fd4..00000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/ImpersonationSessionService.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.netgrif.application.engine.impersonation.service; - -import com.netgrif.application.engine.impersonation.domain.repository.ImpersonatorRepository; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationSessionService; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Lazy; -import org.springframework.session.FindByIndexNameSessionRepository; -import org.springframework.session.Session; -import org.springframework.session.security.SpringSessionBackedSessionRegistry; -import org.springframework.stereotype.Service; - -import java.util.Collection; - -@Service -public class ImpersonationSessionService implements IImpersonationSessionService { - - protected FindByIndexNameSessionRepository sessions; - protected SpringSessionBackedSessionRegistry registry; - protected ImpersonatorRepository impersonatorRepository; - - @Override - public boolean existsSession(String username) { - Collection usersSessions = this.sessions.findByPrincipalName(username).values(); - return usersSessions.stream().anyMatch(session -> !registry.getSessionInformation(session.getId()).isExpired()); - } - - @Override - public boolean isImpersonated(String userId) { - return impersonatorRepository.findByImpersonatedId(userId).isPresent(); - } - - @Autowired - @Lazy - public void setSessions(FindByIndexNameSessionRepository sessions) { - this.sessions = sessions; - } - - @Autowired - @Lazy - public void setRegistry(SpringSessionBackedSessionRegistry registry) { - this.registry = registry; - } - - @Autowired - @Lazy - public void setImpersonatorRepository(ImpersonatorRepository impersonatorRepository) { - this.impersonatorRepository = impersonatorRepository; - } -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationAuthorizationService.java b/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationAuthorizationService.java deleted file mode 100644 index 9847904243c..00000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationAuthorizationService.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.netgrif.application.engine.impersonation.service.interfaces; - -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.objects.auth.domain.Authority; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; -import com.netgrif.application.engine.objects.workflow.domain.Case; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; - -import java.time.LocalDateTime; -import java.util.Collection; -import java.util.List; - -public interface IImpersonationAuthorizationService { - - Page getConfiguredImpersonationUsers(String query, LoggedUser impersonator, Pageable pageable); - - boolean canImpersonate(LoggedUser loggedUser, String configId); - - boolean canImpersonateUser(LoggedUser impersonator, String userId); - - Page searchConfigs(String impersonatorId, Pageable pageable); - - List searchConfigs(String impersonatorId, String impersonatedId); - - List getAuthorities(Collection configs, AbstractUser impersonated); - - List getRoles(Collection configs, AbstractUser impersonated); - - Case getConfig(String configId); - - String getImpersonatedUserId(Case config); - - LocalDateTime getValidUntil(Case config); -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationService.java b/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationService.java deleted file mode 100644 index e08908673b3..00000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationService.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.netgrif.application.engine.impersonation.service.interfaces; - -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.impersonation.domain.Impersonator; -import com.netgrif.application.engine.impersonation.exceptions.ImpersonatedUserHasSessionException; -import com.netgrif.application.engine.objects.workflow.domain.Case; - -import java.util.List; -import java.util.Optional; - -public interface IImpersonationService { - - LoggedUser impersonateUser(String impersonatedId) throws ImpersonatedUserHasSessionException; - - LoggedUser impersonateByConfig(String configId) throws ImpersonatedUserHasSessionException; - - Optional findImpersonator(String impersonatorId); - - void removeImpersonatorByImpersonated(String impersonatedId); - - void removeImpersonator(String impersonatorId); - - LoggedUser endImpersonation(); - - LoggedUser endImpersonation(LoggedUser impersonator); - - void onSessionDestroy(LoggedUser impersonator); - - AbstractUser reloadImpersonatedUserRoles(AbstractUser impersonated, String impersonatorId); - - AbstractUser applyRolesAndAuthorities(AbstractUser impersonated, String impersonatorId, List configs); -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationSessionService.java b/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationSessionService.java deleted file mode 100644 index c28dc266758..00000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/service/interfaces/IImpersonationSessionService.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.netgrif.application.engine.impersonation.service.interfaces; - -public interface IImpersonationSessionService { - boolean existsSession(String username); - - boolean isImpersonated(String userId); -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/web/ImpersonationController.java b/application-engine/src/main/java/com/netgrif/application/engine/impersonation/web/ImpersonationController.java deleted file mode 100644 index 2f2b5b189f5..00000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/web/ImpersonationController.java +++ /dev/null @@ -1,107 +0,0 @@ -package com.netgrif.application.engine.impersonation.web; - -import com.netgrif.application.engine.auth.service.UserResourceHelperService; -import com.netgrif.application.engine.auth.web.responsebodies.UserResourceAssembler; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; -import com.netgrif.application.engine.workflow.web.responsebodies.ResourceLinkAssembler; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.UserService; -import com.netgrif.application.engine.auth.web.responsebodies.UserResource; -import com.netgrif.application.engine.impersonation.exceptions.IllegalImpersonationAttemptException; -import com.netgrif.application.engine.impersonation.exceptions.ImpersonatedUserHasSessionException; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationAuthorizationService; -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService; -import com.netgrif.application.engine.impersonation.web.requestbodies.SearchRequest; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.security.SecurityRequirement; -import io.swagger.v3.oas.annotations.tags.Tag; -import org.springframework.beans.factory.ObjectFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.web.PagedResourcesAssembler; -import org.springframework.hateoas.Link; -import org.springframework.hateoas.MediaTypes; -import org.springframework.hateoas.PagedModel; -import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; -import org.springframework.http.MediaType; -import org.springframework.security.core.Authentication; -import org.springframework.web.bind.annotation.*; - -import java.util.Locale; - -@RestController -@RequestMapping("/api/impersonate") -@ConditionalOnProperty( - value = "netgrif.engine.security.web.impersonation-enabled", - havingValue = "true", - matchIfMissing = true -) -@Tag(name = "Impersonation") -public class ImpersonationController { - - @Autowired - protected IImpersonationService impersonationService; - - @Autowired - protected IImpersonationAuthorizationService impersonationAuthorizationService; - - @Autowired - protected UserService userService; - - @Autowired - protected UserResourceHelperService userResourceHelperService; - - @Autowired - protected ObjectFactory userResourceAssemblerProvider; - - protected UserResourceAssembler getUserResourceAssembler(Locale locale, boolean small, String selfRel) { - UserResourceAssembler result = userResourceAssemblerProvider.getObject(); - result.initialize(locale, small, selfRel); - return result; - } - - @Operation(summary = "Search impersonable users", security = {@SecurityRequirement(name = "BasicAuth")}) - @PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) - public PagedModel getImpersonationUserOptions(@RequestBody SearchRequest request, Pageable pageable, PagedResourcesAssembler assembler, Authentication auth, Locale locale) { - LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); - Page page = impersonationAuthorizationService.getConfiguredImpersonationUsers(request.getQuery(), loggedUser, pageable); - Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(ImpersonationController.class) - .getImpersonationUserOptions(request, pageable, assembler, auth, locale)).withRel("all"); - PagedModel resources = assembler.toModel(page, getUserResourceAssembler(locale, false, "all"), selfLink); - ResourceLinkAssembler.addLinks(resources, AbstractUser.class, selfLink.getRel().toString()); - return resources; - } - - @Operation(summary = "Impersonate user through a specific configuration", security = {@SecurityRequirement(name = "BasicAuth")}) - @PostMapping("/config/{id}") - public UserResource impersonateByConfig(@PathVariable("id") String configId, Locale locale) throws IllegalImpersonationAttemptException, ImpersonatedUserHasSessionException { - LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedUser()); - if (!impersonationAuthorizationService.canImpersonate(loggedUser, configId)) { - throw new IllegalImpersonationAttemptException(loggedUser, configId); - } - loggedUser = impersonationService.impersonateByConfig(configId); - return userResourceHelperService.getResource(loggedUser, locale, false); - } - - @Operation(summary = "Impersonate user directly by id", security = {@SecurityRequirement(name = "BasicAuth")}) - @PostMapping("/user/{id}") - public UserResource impersonateUser(@PathVariable("id") String userId, Locale locale) throws IllegalImpersonationAttemptException, ImpersonatedUserHasSessionException { - LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedUser()); - if (!impersonationAuthorizationService.canImpersonateUser(loggedUser, userId)) { - throw new IllegalImpersonationAttemptException(loggedUser, userId); - } - loggedUser = impersonationService.impersonateUser(userId); - return userResourceHelperService.getResource(loggedUser, locale, false); - } - - @Operation(summary = "Stop impersonating currently impersonated user", security = {@SecurityRequirement(name = "BasicAuth")}) - @PostMapping("/clear") - public UserResource endImpersonation(Locale locale) { - LoggedUser loggedUser = impersonationService.endImpersonation(); - return userResourceHelperService.getResource(loggedUser, locale, false); - } - -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/web/ImpersonationControllerAdvice.java b/application-engine/src/main/java/com/netgrif/application/engine/impersonation/web/ImpersonationControllerAdvice.java deleted file mode 100644 index 61bda7893ff..00000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/web/ImpersonationControllerAdvice.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.netgrif.application.engine.impersonation.web; - -import com.netgrif.application.engine.impersonation.exceptions.IllegalImpersonationAttemptException; -import com.netgrif.application.engine.impersonation.exceptions.ImpersonatedUserHasSessionException; -import com.netgrif.application.engine.impersonation.web.responsebodies.ImpersonationNotAvailableResponse; -import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.ExceptionHandler; -import org.springframework.web.bind.annotation.ResponseStatus; -import org.springframework.web.bind.annotation.RestControllerAdvice; - -@Slf4j -@RestControllerAdvice(assignableTypes = ImpersonationController.class) -public class ImpersonationControllerAdvice { - - @ExceptionHandler - public ResponseEntity handleException(IllegalImpersonationAttemptException ex) { - log.error("Illegal attempt at impersonation", ex); - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } - - @ExceptionHandler - @ResponseStatus(HttpStatus.BAD_REQUEST) - public ImpersonationNotAvailableResponse handleException(ImpersonatedUserHasSessionException ex) { - log.error("User is already logged", ex); - return new ImpersonationNotAvailableResponse(ex.isImpersonated()); - } - -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/web/requestbodies/SearchRequest.java b/application-engine/src/main/java/com/netgrif/application/engine/impersonation/web/requestbodies/SearchRequest.java deleted file mode 100644 index 84f83785447..00000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/web/requestbodies/SearchRequest.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.netgrif.application.engine.impersonation.web.requestbodies; - -import lombok.Getter; -import lombok.Setter; - -public class SearchRequest { - - @Setter - @Getter - protected String query; - - public SearchRequest() { - } - - public SearchRequest(String query) { - this.query = query; - } -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/web/responsebodies/ImpersonationNotAvailableResponse.java b/application-engine/src/main/java/com/netgrif/application/engine/impersonation/web/responsebodies/ImpersonationNotAvailableResponse.java deleted file mode 100644 index ab670d644f3..00000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/impersonation/web/responsebodies/ImpersonationNotAvailableResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.netgrif.application.engine.impersonation.web.responsebodies; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -@Data -@NoArgsConstructor -@AllArgsConstructor -public class ImpersonationNotAvailableResponse { - - private boolean alreadyImpersonated; - - -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java index dc57d15c961..cb2d7bb9078 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardItemServiceImpl.java @@ -5,12 +5,7 @@ import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; import com.netgrif.application.engine.menu.services.interfaces.DashboardItemService; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.objects.common.ResourceNotFoundException; -import com.netgrif.application.engine.objects.common.ResourceNotFoundExceptionCode; -import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.throwable.TransitionNotExecutableException; import com.netgrif.application.engine.objects.utils.MenuItemUtils; import com.netgrif.application.engine.objects.workflow.domain.Case; @@ -66,7 +61,7 @@ public Case getOrCreate(DashboardItemBody body) throws TransitionNotExecutableEx return itemCase; } - LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()); + LoggedUser loggedUser = userService.getLoggedOrSystem(); itemCase = workflowService.createCase(CreateCaseParams.with() .processIdentifier(DashboardItemConstants.PROCESS_IDENTIFIER) .title(body.getName().getDefaultValue()) @@ -83,7 +78,7 @@ public Case getOrCreate(DashboardItemBody body) throws TransitionNotExecutableEx * Updates an existing dashboard item case with new data. * * @param itemCase The existing {@link Case} to update. - * @param body The {@link DashboardItemBody} containing updated data. + * @param body The {@link DashboardItemBody} containing updated data. * @return The updated {@link Case} representing the dashboard item. * @throws TransitionNotExecutableException if the task transition is not executable. */ @@ -115,7 +110,7 @@ protected Case setData(Case useCase, String transId, Map> dataSet) throws TransitionNotExecutableException { - AbstractUser loggedUser = userService.getLoggedOrSystem(); + LoggedUser loggedUser = userService.getLoggedOrSystem(); String taskId = MenuItemUtils.findTaskIdInCase(useCase, transId); Task task = taskService.findOne(taskId); task = taskService.assignTask(TaskParams.with() @@ -134,7 +129,7 @@ protected Case findCase(String processIdentifier, String query) { .process(Collections.singletonList(new CaseSearchRequest.PetriNet(processIdentifier))) .query(query) .build(); - Page resultPage = elasticCaseService.search(java.util.List.of(request), ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), + Page resultPage = elasticCaseService.search(java.util.List.of(request), userService.getLoggedOrSystem(), PageRequest.of(0, 1), Locale.getDefault(), false); return resultPage.hasContent() ? resultPage.getContent().get(0) : null; diff --git a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java index de0f5ac9ef7..f83e96c6cb4 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/DashboardManagementServiceImpl.java @@ -5,13 +5,8 @@ import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; import com.netgrif.application.engine.menu.services.interfaces.DashboardManagementService; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.objects.common.ResourceNotFoundException; -import com.netgrif.application.engine.objects.common.ResourceNotFoundExceptionCode; import com.netgrif.application.engine.objects.petrinet.domain.I18nString; -import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.throwable.TransitionNotExecutableException; import com.netgrif.application.engine.objects.utils.MenuItemUtils; import com.netgrif.application.engine.objects.workflow.domain.Case; @@ -68,7 +63,7 @@ public Case createDashboardManagement(DashboardManagementBody body) throws Trans return managementCase; } addReferencedMenuItems(body); - LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()); + LoggedUser loggedUser = userService.getLoggedOrSystem(); managementCase = workflowService.createCase(CreateCaseParams.with() .processIdentifier(DashboardManagementConstants.PROCESS_IDENTIFIER) .title(body.getName().getDefaultValue()) @@ -115,7 +110,7 @@ protected Case setData(Case useCase, String transId, Map> dataSet) throws TransitionNotExecutableException { - AbstractUser loggedUser = userService.getLoggedOrSystem(); + LoggedUser loggedUser = userService.getLoggedOrSystem(); String taskId = MenuItemUtils.findTaskIdInCase(useCase, transId); Task task = taskService.findOne(taskId); task = taskService.assignTask(TaskParams.with() @@ -134,7 +129,7 @@ protected Case findCase(String processIdentifier, String query) { .process(Collections.singletonList(new CaseSearchRequest.PetriNet(processIdentifier))) .query(query) .build(); - Page resultPage = elasticCaseService.search(java.util.List.of(request), ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), + Page resultPage = elasticCaseService.search(java.util.List.of(request), userService.getLoggedOrSystem(), PageRequest.of(0, 1), Locale.getDefault(), false); return resultPage.hasContent() ? resultPage.getContent().get(0) : null; diff --git a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java index 90283ee4d29..25e6b4ce90c 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/menu/services/MenuItemService.java @@ -6,8 +6,6 @@ import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; import com.netgrif.application.engine.menu.services.interfaces.IMenuItemService; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.petrinet.domain.I18nString; import com.netgrif.application.engine.objects.petrinet.domain.dataset.FieldType; @@ -60,8 +58,7 @@ public class MenuItemService implements IMenuItemService { */ @Override public Case createFilter(FilterBody body) throws TransitionNotExecutableException { - AbstractUser loggedUser = userService.getLoggedOrSystem(); - Case filterCase = createCase(FilterRunner.FILTER_PETRI_NET_IDENTIFIER, body.getTitle().getDefaultValue(), ActorTransformer.toLoggedUser(loggedUser)); + Case filterCase = createCase(FilterRunner.FILTER_PETRI_NET_IDENTIFIER, body.getTitle().getDefaultValue(), userService.getLoggedOrSystem()); filterCase.setIcon(body.getIcon()); filterCase = workflowService.save(filterCase); ToDataSetOutcome dataSetOutcome = body.toDataSet(); @@ -98,7 +95,6 @@ public Case updateFilter(Case filterCase, FilterBody body) { @Override public Case createMenuItem(MenuItemBody body) throws TransitionNotExecutableException { log.debug("Creation of menu item case with identifier [{}] started.", body.getIdentifier()); - AbstractUser loggedUser = userService.getLoggedOrSystem(); String sanitizedIdentifier = MenuItemUtils.sanitize(body.getIdentifier()); if (existsMenuItem(sanitizedIdentifier)) { @@ -112,7 +108,7 @@ public Case createMenuItem(MenuItemBody body) throws TransitionNotExecutableExce newName = new I18nString(body.getIdentifier()); } Case menuItemCase = createCase(MenuProcessRunner.MENU_NET_IDENTIFIER, newName.getDefaultValue(), - ActorTransformer.toLoggedUser(loggedUser)); + userService.getLoggedOrSystem()); menuItemCase = workflowService.save(menuItemCase); parentItemCase = appendChildCaseIdAndSave(parentItemCase, menuItemCase.getStringId()); @@ -331,7 +327,7 @@ public Case duplicateItem(Case originItem, I18nString newTitle, String newIdenti duplicatedViewCase = duplicateView(originViewCase); } Case duplicated = createCase(MenuProcessRunner.MENU_NET_IDENTIFIER, newTitle.getDefaultValue(), - ActorTransformer.toLoggedUser(userService.getLoggedOrSystem())); + userService.getLoggedOrSystem()); duplicated.setDataSet(originItem.getDataSet()); duplicated.setTitle(newTitle.getDefaultValue()); duplicated = workflowService.save(duplicated); @@ -397,7 +393,7 @@ protected Case findCase(String processIdentifier, String query) { .process(Collections.singletonList(new CaseSearchRequest.PetriNet(processIdentifier))) .query(query) .build(); - Page resultPage = elasticCaseService.search(List.of(request), ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), + Page resultPage = elasticCaseService.search(List.of(request), userService.getLoggedOrSystem(), PageRequest.of(0, 1), Locale.getDefault(), false); return resultPage.hasContent() ? resultPage.getContent().get(0) : null; @@ -408,7 +404,8 @@ protected long countCases(String processIdentifier, String query) { .process(Collections.singletonList(new CaseSearchRequest.PetriNet(processIdentifier))) .query(query) .build(); - return elasticCaseService.count(List.of(request), ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), + LoggedUser loggedUser = userService.getLoggedOrSystem(); + return elasticCaseService.count(List.of(request), loggedUser, Locale.getDefault(), false); } @@ -421,7 +418,7 @@ protected Case duplicateView(Case viewCase) throws TransitionNotExecutableExcept } Case duplicatedViewCase = createCase(viewCase.getProcessIdentifier(), viewCase.getTitle(), - ActorTransformer.toLoggedUser(userService.getLoggedOrSystem())); + userService.getLoggedOrSystem()); duplicatedViewCase.setDataSet(viewCase.getDataSet()); workflowService.save(duplicatedViewCase); @@ -467,9 +464,7 @@ protected Case handleView(Case existingViewCase, ViewBody body) throws Transitio } protected Case createView(ViewBody body) throws TransitionNotExecutableException { - AbstractUser loggedUser = userService.getLoggedOrSystem(); - Case viewCase = createCase(body.getViewProcessIdentifier(), body.getViewProcessIdentifier(), - ActorTransformer.toLoggedUser(loggedUser)); + Case viewCase = createCase(body.getViewProcessIdentifier(), body.getViewProcessIdentifier(), userService.getLoggedOrSystem()); Case associatedViewCase = null; if (body.hasAssociatedView()) { @@ -596,7 +591,6 @@ protected Case getOrCreateFolderRecursive(String path, MenuItemBody body) throws } protected Case getOrCreateFolderRecursive(String path, MenuItemBody body, Case childFolderCase) throws TransitionNotExecutableException { - AbstractUser loggedUser = userService.getLoggedOrSystem(); Case folderCase = findFolderCase(path); if (folderCase != null) { if (childFolderCase != null) { @@ -605,8 +599,7 @@ protected Case getOrCreateFolderRecursive(String path, MenuItemBody body, Case c return folderCase; } - folderCase = createCase(MenuProcessRunner.MENU_NET_IDENTIFIER, body.getMenuName().getDefaultValue(), - ActorTransformer.toLoggedUser(loggedUser)); + folderCase = createCase(MenuProcessRunner.MENU_NET_IDENTIFIER, body.getMenuName().getDefaultValue(), userService.getLoggedOrSystem()); ToDataSetOutcome dataSetOutcome = body.toDataSet(null, path, null); if (childFolderCase != null) { @@ -692,7 +685,7 @@ protected Case setData(String taskId, Map> dataSet) @SuppressWarnings({"unchecked", "rawtypes"}) protected Case setDataWithExecute(Case useCase, String transId, Map> dataSet) throws TransitionNotExecutableException { - AbstractUser loggedUser = userService.getLoggedOrSystem(); + LoggedUser loggedUser = userService.getLoggedOrSystem(); String taskId = MenuItemUtils.findTaskIdInCase(useCase, transId); Task task = taskService.findOne(taskId); task = taskService.assignTask(TaskParams.with() diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/params/ImportPetriNetParams.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/params/ImportPetriNetParams.java index c6eac84847e..4025b3f05cb 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/params/ImportPetriNetParams.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/params/ImportPetriNetParams.java @@ -1,8 +1,8 @@ package com.netgrif.application.engine.petrinet.params; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.petrinet.service.PetriNetService; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.petrinet.domain.VersionType; +import com.netgrif.application.engine.petrinet.service.PetriNetService; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -27,17 +27,18 @@ public class ImportPetriNetParams { /** * Release type of the process + * * @see VersionType */ private VersionType releaseType; /// Author of the process - private AbstractUser author; + private LoggedUser author; @Builder.Default private Map params = new HashMap<>(); - public ImportPetriNetParams(InputStream xmlFile, VersionType releaseType, AbstractUser author, String uriNodeId) { + public ImportPetriNetParams(InputStream xmlFile, VersionType releaseType, LoggedUser author, String uriNodeId) { this.xmlFile = xmlFile; this.releaseType = releaseType; this.author = author; @@ -45,7 +46,7 @@ public ImportPetriNetParams(InputStream xmlFile, VersionType releaseType, Abstra this.params = new HashMap<>(); } - public ImportPetriNetParams(InputStream xmlFile, VersionType releaseType, AbstractUser author) { + public ImportPetriNetParams(InputStream xmlFile, VersionType releaseType, LoggedUser author) { this(xmlFile, releaseType, author, null); } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java index 759527b8bb4..d53672a83e6 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/PetriNetService.java @@ -2,37 +2,36 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.type.TypeFactory; -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; +import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService; +import com.netgrif.application.engine.auth.service.GroupService; +import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.configuration.properties.CacheConfigurationProperties; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetMappingService; +import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetService; import com.netgrif.application.engine.files.minio.StorageConfigurationProperties; -import com.netgrif.application.engine.petrinet.params.DeletePetriNetParams; -import com.netgrif.application.engine.petrinet.params.ImportPetriNetParams; +import com.netgrif.application.engine.importer.service.Importer; +import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; +import com.netgrif.application.engine.objects.event.events.petrinet.ProcessDeleteEvent; +import com.netgrif.application.engine.objects.event.events.petrinet.ProcessDeployEvent; import com.netgrif.application.engine.objects.event.events.petrinet.ProcessEvent; import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch; import com.netgrif.application.engine.objects.petrinet.domain.Transition; import com.netgrif.application.engine.objects.petrinet.domain.VersionType; -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.petrinet.web.responsebodies.ArcImportReference; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.UserService; -import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetMappingService; -import com.netgrif.application.engine.elastic.service.interfaces.IElasticPetriNetService; -import com.netgrif.application.engine.objects.event.events.petrinet.ProcessDeleteEvent; -import com.netgrif.application.engine.objects.event.events.petrinet.ProcessDeployEvent; -import com.netgrif.application.engine.importer.service.Importer; -import com.netgrif.application.engine.auth.service.GroupService; import com.netgrif.application.engine.objects.petrinet.domain.dataset.logic.action.Action; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.FieldActionsRunner; import com.netgrif.application.engine.objects.petrinet.domain.events.EventPhase; -import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository; import com.netgrif.application.engine.objects.petrinet.domain.throwable.MissingIconKeyException; import com.netgrif.application.engine.objects.petrinet.domain.throwable.MissingPetriNetMetaDataException; import com.netgrif.application.engine.objects.petrinet.domain.version.Version; -import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService; -import com.netgrif.application.engine.petrinet.web.responsebodies.*; import com.netgrif.application.engine.objects.workflow.domain.Case; import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.petrinetoutcomes.ImportPetriNetEventOutcome; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.FieldActionsRunner; +import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository; +import com.netgrif.application.engine.petrinet.params.DeletePetriNetParams; +import com.netgrif.application.engine.petrinet.params.ImportPetriNetParams; +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; +import com.netgrif.application.engine.petrinet.web.responsebodies.*; import com.netgrif.application.engine.workflow.service.interfaces.IEventService; import com.netgrif.application.engine.workflow.service.interfaces.IFieldActionsCacheService; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; @@ -186,7 +185,7 @@ public ImportPetriNetEventOutcome importPetriNet(ImportPetriNetParams importPetr PetriNet processToMakeNonDefault = checkAndHandleProcessVersion(newProcess, importPetriNetParams.getReleaseType()); processRoleService.saveAll(newProcess.getRoles().values()); - newProcess.setAuthor(ActorTransformer.toActorRef(importPetriNetParams.getAuthor())); + newProcess.setAuthor(ActorTransformer.toActorRef(importPetriNetParams.getAuthor().getSelfOrImpersonated())); Path savedPath = getImporter().saveNetFile(newProcess, new ByteArrayInputStream(xmlCopy.toByteArray())); xmlCopy.close(); log.info("Petri net {} ({} v{}) imported successfully and saved in a folder: {}", newProcess.getTitle(), @@ -496,7 +495,14 @@ public Page getReferencesByVersion(Version version, LoggedUse @Override public List getReferencesByUsersProcessRoles(LoggedUser user, Locale locale) { - Query query = Query.query(getProcessRolesCriteria(user)); + if (user.isProcessAccessDeny()) { + return new ArrayList<>(); + } + Criteria processRolesCriteria = getProcessRolesCriteria(user); + Criteria impersonatedProcessesCriteria = getImpersonatedProcessesCriteria(user); + Query query = impersonatedProcessesCriteria == null + ? Query.query(processRolesCriteria) + : Query.query(processRolesCriteria.andOperator(impersonatedProcessesCriteria)); return mongoTemplate.find(query, com.netgrif.application.engine.adapter.spring.petrinet.domain.PetriNet.class).stream() .map(net -> transformToReference(net, locale)) .collect(Collectors.toList()); @@ -549,13 +555,16 @@ public Page search(PetriNetSearch criteriaClass, LoggedUser u Query query = new Query(); Query queryTotal = new Query(); - // TODO: resolve impersonation if (!user.isAdmin()) { + if (user.isProcessAccessDeny()) { + return Page.empty(); + } query.addCriteria(getProcessRolesCriteria(user)); + Criteria impersonatedProcessesCriteria = getImpersonatedProcessesCriteria(user); + if (impersonatedProcessesCriteria != null) { + query.addCriteria(impersonatedProcessesCriteria); + } } -// if (!user.getSelfOrImpersonated().isAdmin()) -// query.addCriteria(getProcessRolesCriteria(user.getSelfOrImpersonated())); - if (criteriaClass.getIdentifier() != null) { this.addValueCriteria(query, queryTotal, Criteria.where("identifier").regex(criteriaClass.getIdentifier(), "i")); } @@ -640,7 +649,7 @@ protected void doDeletePetriNet(DeletePetriNetParams deletePetriNetParams, boole processRoleService.deleteRolesOfNet(petriNet, deletePetriNetParams.getLoggedUser()); log.info("[{}]: User [{}] is deleting Petri net {} version {}", deletePetriNetParams.getPetriNetId(), - deletePetriNetParams.getLoggedUser().getStringId(), petriNet.getIdentifier(), petriNet.getVersion().toString()); + deletePetriNetParams.getLoggedUser().getSelfOrImpersonatedStringId(), petriNet.getIdentifier(), petriNet.getVersion().toString()); publisher.publishEvent(new ProcessDeleteEvent(petriNet, EventPhase.PRE)); repository.deleteBy_id(petriNet.getObjectId()); evictCache(petriNet); @@ -662,6 +671,16 @@ protected Criteria getProcessRolesCriteria(LoggedUser user) { .map(role -> Criteria.where("permissions." + role).exists(true)).toArray(Criteria[]::new)); } + private Criteria getImpersonatedProcessesCriteria(LoggedUser user) { + if (user.isAdmin() || !user.isImpersonating() || user.getImpersonatedProcesses() == null || user.getImpersonatedProcesses().isEmpty()) { + return null; + } + if (user.isImpersonatedProcessesListAllowing()) { + return Criteria.where("identifier").in(user.getImpersonatedProcesses()); + } + return Criteria.where("identifier").nin(user.getImpersonatedProcesses()); + } + @Override public void runActions(List actions, PetriNet petriNet) { log.info("Running actions of net [{}]", petriNet.getStringId()); @@ -698,7 +717,7 @@ protected void fillAndValidateAttributes(DeletePetriNetParams deletePetriNetPara throw new IllegalArgumentException("No petriNet identifier was provided."); } if (deletePetriNetParams.getLoggedUser() == null) { - deletePetriNetParams.setLoggedUser(ActorTransformer.toLoggedUser(userService.getLoggedOrSystem())); + deletePetriNetParams.setLoggedUser(userService.getLoggedOrSystem()); } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/ProcessRoleService.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/ProcessRoleService.java index e61ebf9c30a..5085f4f8dee 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/ProcessRoleService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/service/ProcessRoleService.java @@ -5,26 +5,26 @@ import com.netgrif.application.engine.adapter.spring.petrinet.domain.roles.RoleReferencedException; import com.netgrif.application.engine.adapter.spring.utils.PaginationProperties; import com.netgrif.application.engine.auth.service.GroupService; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.auth.service.RealmService; +import com.netgrif.application.engine.auth.service.UserService; +import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.Group; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.objects.auth.domain.Realm; import com.netgrif.application.engine.objects.event.events.user.UserRoleChangeEvent; import com.netgrif.application.engine.objects.importer.model.EventPhaseType; import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.dataset.logic.action.Action; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.context.RoleContext; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.runner.RoleActionsRunner; import com.netgrif.application.engine.objects.petrinet.domain.events.Event; import com.netgrif.application.engine.objects.petrinet.domain.events.EventType; -import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository; import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; +import com.netgrif.application.engine.objects.workflow.domain.ProcessResourceId; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.context.RoleContext; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.runner.RoleActionsRunner; +import com.netgrif.application.engine.petrinet.domain.repositories.PetriNetRepository; import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.security.service.ISecurityContextService; -import com.netgrif.application.engine.objects.workflow.domain.ProcessResourceId; import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; import lombok.Getter; @@ -152,9 +152,9 @@ protected void saveUserAndReloadContext(AbstractUser user, LoggedUser loggedUser String userId = user.getStringId(); securityContextService.saveToken(userId); - if (Objects.equals(userId, loggedUser.getStringId())) { + if (Objects.equals(userId, loggedUser.getSelfOrImpersonatedStringId())) { loggedUser.getProcessRoles().clear(); - loggedUser.setProcessRoles(user.getProcessRoles()); + loggedUser.setProcessRolesToLoggedUser(user.getProcessRoles()); securityContextService.reloadSecurityContext(loggedUser); } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java index d4b062650c2..bb7fe00b696 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PetriNetController.java @@ -209,8 +209,12 @@ ResponseEntity> searchPetriNets(@RequestBody Pet PagedModel searchElasticPetriNets(@RequestBody PetriNetSearch criteria, Authentication auth, Pageable pageable, PagedResourcesAssembler assembler, Locale locale) { LoggedUser user = (LoggedUser) auth.getPrincipal(); // TODO: add Merge Filters and its operations - - Page nets = elasticService.search(criteria, user, pageable, locale, false); + Page nets; + if (user.isProcessAccessDeny()) { + nets = Page.empty(); + } else { + nets = elasticService.search(criteria, user, pageable, locale, false); + } Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(PetriNetController.class) .searchElasticPetriNets(criteria, auth, pageable, assembler, locale)).withRel("search_elastic"); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PublicPetriNetController.java b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PublicPetriNetController.java index ab2ce973c53..9b2028b9304 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PublicPetriNetController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/petrinet/web/PublicPetriNetController.java @@ -1,12 +1,11 @@ package com.netgrif.application.engine.petrinet.web; +import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService; import com.netgrif.application.engine.auth.service.UserService; -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch; import com.netgrif.application.engine.petrinet.domain.version.StringToVersionConverter; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService; import com.netgrif.application.engine.petrinet.web.responsebodies.*; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; @@ -16,10 +15,8 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.web.PagedResourcesAssembler; -import org.springframework.hateoas.Link; import org.springframework.hateoas.MediaTypes; import org.springframework.hateoas.PagedModel; -import org.springframework.hateoas.server.mvc.WebMvcLinkBuilder; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; @@ -65,13 +62,13 @@ public PetriNetReferenceResource getOne(@PathVariable("id") String id, Locale lo @ResponseBody public PetriNetReferenceResource getOne(@PathVariable("identifier") String identifier, @PathVariable("version") String version, Locale locale) { String resolvedIdentifier = Base64.isBase64(identifier) ? new String(Base64.decodeBase64(identifier)) : identifier; - return new PetriNetReferenceResource(this.petriNetService.getReference(resolvedIdentifier, this.converter.convert(version), ActorTransformer.toLoggedUser(userService.getLoggedUser()), locale)); + return new PetriNetReferenceResource(this.petriNetService.getReference(resolvedIdentifier, this.converter.convert(version), userService.getLoggedUserFromContext(), locale)); } @Operation(summary = "Search processes") @PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public PagedModel searchPetriNets(@RequestBody PetriNetSearch criteria, Pageable pageable, PagedResourcesAssembler assembler, Locale locale) { - Page nets = petriNetService.search(criteria, ActorTransformer.toLoggedUser(userService.getLoggedUser()), pageable, locale); + Page nets = petriNetService.search(criteria, userService.getLoggedUserFromContext(), pageable, locale); // Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(PublicPetriNetController.class) // .searchPetriNets(criteria, pageable, assembler, locale)).withRel("search"); // PagedModel resources = assembler.toModel(nets, new PetriNetReferenceResourceAssembler(), selfLink); @@ -103,6 +100,6 @@ public DataFieldReferencesResource getDataFieldReferences(@RequestBody List ids, Locale locale) { ids.forEach(PetriNetController::decodeUrl); - return new TransitionReferencesResource(petriNetService.getTransitionReferences(ids, ActorTransformer.toLoggedUser(userService.getLoggedUser()), locale)); + return new TransitionReferencesResource(petriNetService.getTransitionReferences(ids, userService.getLoggedUserFromContext(), locale)); } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/security/service/SecurityContextService.java b/application-engine/src/main/java/com/netgrif/application/engine/security/service/SecurityContextService.java index 1947207cb86..d4e646e051e 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/security/service/SecurityContextService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/security/service/SecurityContextService.java @@ -1,18 +1,16 @@ package com.netgrif.application.engine.security.service; import com.netgrif.application.engine.adapter.spring.auth.domain.LoggedUserImpl; +import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.UserService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; -import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Service; -import java.util.Collection; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -73,7 +71,13 @@ public void forceReloadSecurityContext(LoggedUser loggedUser) { private void reloadSecurityContext(LoggedUser loggedUser, boolean forceRefresh) { if (isUserLogged(loggedUser) && cachedTokens.contains(loggedUser.getStringId())) { if (forceRefresh) { - loggedUser = ActorTransformer.toLoggedUser(userService.findById(loggedUser.getStringId(), null)); + LoggedUser reloadedLoggedUser = ActorTransformer.toLoggedUser(userService.findById(loggedUser.getStringId(), null)); + if (loggedUser.isImpersonating()) { + reloadedLoggedUser.setImpersonatedUser(loggedUser.getImpersonatedUser()); + reloadedLoggedUser.setImpersonatedProcessesListAllowing(loggedUser.isImpersonatedProcessesListAllowing()); + reloadedLoggedUser.setImpersonatedProcesses(loggedUser.getImpersonatedProcesses()); + } + loggedUser = reloadedLoggedUser; } UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(loggedUser, SecurityContextHolder.getContext().getAuthentication().getCredentials(), ((LoggedUserImpl) loggedUser).getAuthorities()); SecurityContextHolder.getContext().setAuthentication(token); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultFiltersRunner.java b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultFiltersRunner.java index fd2cad3b54f..dd9dc6ac1b4 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultFiltersRunner.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/DefaultFiltersRunner.java @@ -1,19 +1,18 @@ package com.netgrif.application.engine.startup.runner; -import com.netgrif.application.engine.configuration.properties.FilterConfigurationProperties; +import com.netgrif.application.engine.adapter.spring.workflow.domain.QCase; +import com.netgrif.application.engine.adapter.spring.workflow.domain.QTask; import com.netgrif.application.engine.auth.service.UserService; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; +import com.netgrif.application.engine.configuration.properties.FilterConfigurationProperties; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.petrinet.domain.I18nString; import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; +import com.netgrif.application.engine.objects.workflow.domain.Case; +import com.netgrif.application.engine.objects.workflow.domain.Task; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.startup.ApplicationEngineStartupRunner; import com.netgrif.application.engine.startup.ImportHelper; import com.netgrif.application.engine.startup.annotation.RunnerOrder; -import com.netgrif.application.engine.objects.workflow.domain.Case; -import com.netgrif.application.engine.adapter.spring.workflow.domain.QCase; -import com.netgrif.application.engine.adapter.spring.workflow.domain.QTask; -import com.netgrif.application.engine.objects.workflow.domain.Task; import com.netgrif.application.engine.workflow.params.CreateCaseParams; import com.netgrif.application.engine.workflow.params.TaskParams; import com.netgrif.application.engine.workflow.service.interfaces.IDataService; @@ -429,7 +428,7 @@ private Optional createFilterCase(String title, String icon, String filter return Optional.empty(); } - AbstractUser loggedUser = this.userService.getLoggedOrSystem(); + LoggedUser loggedUser = this.userService.getLoggedOrSystem(); if (loggedUser.getStringId().equals(this.userService.getSystem().getStringId())) { Case filterCase = this.workflowService.searchOne(QCase.case$.processIdentifier.eq("filter").and(QCase.case$.title.eq(title)).and(QCase.case$.author.id.eq(userService.getSystem().getStringId()))); if (filterCase != null) { @@ -442,7 +441,7 @@ private Optional createFilterCase(String title, String icon, String filter .process(filterNet) .title(title) .color(null) - .author(ActorTransformer.toLoggedUser(loggedUser)) + .author(loggedUser) .build()).getCase(); filterCase.setIcon(icon); filterCase = this.workflowService.save(filterCase); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/ImpersonationRunner.java b/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/ImpersonationRunner.java deleted file mode 100644 index 4244f1e6079..00000000000 --- a/application-engine/src/main/java/com/netgrif/application/engine/startup/runner/ImpersonationRunner.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.netgrif.application.engine.startup.runner; - -import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; -import com.netgrif.application.engine.objects.petrinet.domain.VersionType; -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.startup.ApplicationEngineStartupRunner; -import com.netgrif.application.engine.startup.ImportHelper; -import com.netgrif.application.engine.startup.annotation.RunnerOrder; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.ApplicationArguments; -import org.springframework.stereotype.Component; - -import java.util.Optional; - -@Slf4j -@Component -@RunnerOrder(130) -@RequiredArgsConstructor -public class ImpersonationRunner implements ApplicationEngineStartupRunner { - - public static final String IMPERSONATION_CONFIG_FILE_NAME = "engine-processes/impersonation_config.xml"; - public static final String IMPERSONATION_CONFIG_PETRI_NET_IDENTIFIER = "impersonation_config"; - public static final String IMPERSONATION_CONFIG_USER_SELECT_FILE_NAME = "engine-processes/impersonation_users_select.xml"; - public static final String IMPERSONATION_CONFIG_USER_SELECT_PETRI_NET_IDENTIFIER = "impersonation_users_select"; - - protected final IPetriNetService petriNetService; - protected final ImportHelper helper; - protected final SystemUserRunner systemCreator; - - @Override - public void run(ApplicationArguments args) throws Exception { - createConfigNets(); - } - - public void createConfigNets() { - importProcess("Petri net for impersonation config", IMPERSONATION_CONFIG_PETRI_NET_IDENTIFIER, IMPERSONATION_CONFIG_FILE_NAME); - importProcess("Petri net for impersonation user select", IMPERSONATION_CONFIG_USER_SELECT_PETRI_NET_IDENTIFIER, IMPERSONATION_CONFIG_USER_SELECT_FILE_NAME); - } - - public Optional importProcess(final String message, String netIdentifier, String netFileName) { - PetriNet foundNet = petriNetService.getDefaultVersionByIdentifier(netIdentifier); - if (foundNet != null) { - log.info("{} has already been imported.", message); - return Optional.of(foundNet); - } - - Optional net = helper.createNet(netFileName, VersionType.MAJOR, systemCreator.getLoggedSystem()); - if (net.isEmpty()) { - log.error("Import of {} failed!", message); - } - - return net; - } - -} diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/repositories/CaseRepositoryImpl.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/repositories/CaseRepositoryImpl.java index 9e69bf4e24e..7d1d009b481 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/repositories/CaseRepositoryImpl.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/domain/repositories/CaseRepositoryImpl.java @@ -1,11 +1,11 @@ package com.netgrif.application.engine.workflow.domain.repositories; +import com.netgrif.application.engine.adapter.spring.workflow.domain.QCase; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; +import com.netgrif.application.engine.objects.workflow.domain.QDataField; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.petrinet.web.responsebodies.PetriNetReference; import com.netgrif.application.engine.petrinet.web.responsebodies.Reference; -import com.netgrif.application.engine.adapter.spring.workflow.domain.QCase; -import com.netgrif.application.engine.objects.workflow.domain.QDataField; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.core.types.dsl.Expressions; import com.querydsl.core.types.dsl.StringExpression; @@ -30,8 +30,6 @@ public abstract class CaseRepositoryImpl implements CaseRepository { @Override public void customize(QuerydslBindings bindings, QCase qCase) { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); - // TODO: impersonation -// List nets = petriNetService.getReferencesByUsersProcessRoles(((LoggedUser) auth.getPrincipal()).getSelfOrImpersonated(), null); List nets = petriNetService.getReferencesByUsersProcessRoles(((LoggedUser) auth.getPrincipal()), null); Set netIds = nets.stream().map(Reference::getStringId).collect(Collectors.toSet()); Set netIdentifiers = nets.stream().map(PetriNetReference::getIdentifier).collect(Collectors.toSet()); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/params/CreateCaseParams.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/params/CreateCaseParams.java index 5edb1679b31..f5cc0974c79 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/params/CreateCaseParams.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/params/CreateCaseParams.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.workflow.params; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.workflow.domain.Case; import com.netgrif.application.engine.workflow.service.WorkflowService; @@ -39,7 +39,7 @@ public class CreateCaseParams { private String color; /// Author of the Case - private AbstractUser author; + private LoggedUser author; @Builder.Default private Locale locale = LocaleContextHolder.getLocale(); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/params/DelegateTaskParams.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/params/DelegateTaskParams.java index c1c8ad177b4..144a4e82b52 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/params/DelegateTaskParams.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/params/DelegateTaskParams.java @@ -1,9 +1,10 @@ package com.netgrif.application.engine.workflow.params; import com.netgrif.application.engine.objects.auth.domain.AbstractUser; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.workflow.domain.Case; -import com.netgrif.application.engine.workflow.service.TaskService; import com.netgrif.application.engine.objects.workflow.domain.Task; +import com.netgrif.application.engine.workflow.service.TaskService; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -35,7 +36,7 @@ public class DelegateTaskParams { private String newAssigneeId; /// The user, who is performing the delegation - private AbstractUser delegator; + private LoggedUser delegator; /// The user's string id, who is performing the delegation private String delegatorId; @@ -63,7 +64,7 @@ public DelegateTaskParamsBuilder newAssignee(AbstractUser newAssignee) { } /// Sets the {@link #delegator} and {@link #delegatorId} - public DelegateTaskParamsBuilder delegator(AbstractUser delegator) { + public DelegateTaskParamsBuilder delegator(LoggedUser delegator) { this.delegator = delegator; if (delegator != null) { this.delegatorId = delegator.getStringId(); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/params/TaskParams.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/params/TaskParams.java index 5bb54346297..1ea3a5fecc1 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/params/TaskParams.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/params/TaskParams.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.workflow.params; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.workflow.domain.Case; import com.netgrif.application.engine.objects.workflow.domain.Task; import com.netgrif.application.engine.workflow.service.TaskService; @@ -29,7 +29,7 @@ public class TaskParams { private Case useCase; /// Subject user for the specific task event (new assignee or current assignee) - private AbstractUser user; + private LoggedUser user; @Builder.Default private Map params = new HashMap<>(); @@ -38,7 +38,7 @@ public TaskParams(Task task) { this(task, null); } - public TaskParams(Task task, AbstractUser user) { + public TaskParams(Task task, LoggedUser user) { this.task = task; if (task != null) { this.taskId = task.getStringId(); @@ -51,7 +51,7 @@ public TaskParams(String taskId) { this(taskId, null); } - public TaskParams(String taskId, AbstractUser user) { + public TaskParams(String taskId, LoggedUser user) { this.taskId = taskId; this.user = user; this.params = new HashMap<>(); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationService.java index d6a9479369d..34ca47b3f23 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationService.java @@ -1,6 +1,6 @@ package com.netgrif.application.engine.workflow.service; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import java.util.HashMap; import java.util.HashSet; @@ -18,11 +18,9 @@ protected boolean hasRestrictedPermission(Boolean permissionValue) { return permissionValue != null && !permissionValue; } - protected Map getAggregatePermissions(AbstractUser user, Map> permissions) { + protected Map getAggregatePermissions(LoggedUser user, Map> permissions) { Map aggregatePermissions = new HashMap<>(); -// Set userProcessRoleIDs = user.getSelfOrImpersonated().getProcessRoles().stream().map(role -> role.get_id().toString()).collect(Collectors.toSet()); - // TODO: impersonation Set userProcessRoleIDs = user.getProcessRoles().stream() .map(role -> role.get_id().toString()) .collect(Collectors.toSet()); @@ -48,8 +46,7 @@ private void aggregatePermission(Set userProcessRoleIDs, Map.Entry findUserPermissions(Map> docPermissions, AbstractUser user) { - // TODO: impersonation + protected Map findUserPermissions(Map> docPermissions, LoggedUser user) { if (docPermissions == null) { return null; } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/CaseSearchService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/CaseSearchService.java index 31a07ef9fc7..c7b88718083 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/CaseSearchService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/CaseSearchService.java @@ -1,18 +1,18 @@ package com.netgrif.application.engine.workflow.service; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; +import com.netgrif.application.engine.adapter.spring.workflow.domain.QCase; import com.netgrif.application.engine.importer.service.FieldFactory; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.petrinet.domain.I18nString; import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch; import com.netgrif.application.engine.objects.petrinet.domain.dataset.ActorFieldValue; import com.netgrif.application.engine.objects.petrinet.domain.dataset.FieldType; +import com.netgrif.application.engine.objects.workflow.domain.Case; +import com.netgrif.application.engine.objects.workflow.domain.ProcessResourceId; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.petrinet.web.responsebodies.PetriNetReference; import com.netgrif.application.engine.utils.FullPageRequest; -import com.netgrif.application.engine.objects.workflow.domain.Case; -import com.netgrif.application.engine.objects.workflow.domain.ProcessResourceId; -import com.netgrif.application.engine.adapter.spring.workflow.domain.QCase; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Expression; import com.querydsl.core.types.Ops; @@ -61,7 +61,6 @@ public class CaseSearchService extends MongoSearchService { public Predicate buildQuery(Map requestQuery, LoggedUser user, Locale locale) { BooleanBuilder builder = new BooleanBuilder(); -// LoggedUser loggedOrImpersonated = user.getSelfOrImpersonated(); if (requestQuery.containsKey(PETRINET)) { builder.and(petriNet(requestQuery.get(PETRINET), user, locale)); @@ -95,11 +94,16 @@ public Predicate buildQuery(Map requestQuery, LoggedUser user, L return null; } } - BooleanBuilder permissionConstraints = new BooleanBuilder(buildViewRoleQueryConstraint(user)); - permissionConstraints.andNot(buildNegativeViewRoleQueryConstraint(user)); - permissionConstraints.or(buildViewActorQueryConstraint(user)); - permissionConstraints.andNot(buildNegativeViewActorsQueryConstraint(user)); + LoggedUser impersonationUser = user.getSelfOrImpersonated(); + BooleanBuilder permissionConstraints = new BooleanBuilder(buildViewRoleQueryConstraint(impersonationUser)); + permissionConstraints.andNot(buildNegativeViewRoleQueryConstraint(impersonationUser)); + permissionConstraints.or(buildViewActorQueryConstraint(impersonationUser)); + permissionConstraints.andNot(buildNegativeViewActorsQueryConstraint(impersonationUser)); builder.and(permissionConstraints); + BooleanExpression impersonatedProcessesConstraints = buildImpersonatedProcessesConstraint(user); + if (impersonatedProcessesConstraints != null) { + builder.and(impersonatedProcessesConstraints); + } return builder; } @@ -156,6 +160,22 @@ private static BooleanExpression petriNetObject(HashMap query, L return null; } + private static BooleanExpression buildImpersonatedProcessesConstraint(LoggedUser loggedUser) { + if (loggedUser.isAdmin() || !loggedUser.isImpersonating()) { + return null; + } + if (loggedUser.isProcessAccessDeny()) { + return null; + } + if (loggedUser.getImpersonatedProcesses() == null || loggedUser.getImpersonatedProcesses().isEmpty()) { + return null; + } + if (loggedUser.isImpersonatedProcessesListAllowing()) { + return QCase.case$.processIdentifier.in(loggedUser.getImpersonatedProcesses()); + } + return QCase.case$.processIdentifier.notIn(loggedUser.getImpersonatedProcesses()); + } + public Predicate author(Object query) { if (query instanceof ArrayList) { BooleanBuilder builder = new BooleanBuilder(); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/ConfigurableMenuService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/ConfigurableMenuService.java index 8a73bb41a51..fd5144170bd 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/ConfigurableMenuService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/ConfigurableMenuService.java @@ -1,5 +1,6 @@ package com.netgrif.application.engine.workflow.service; +import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService; import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; @@ -8,10 +9,9 @@ import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch; import com.netgrif.application.engine.objects.petrinet.domain.dataset.EnumerationMapField; import com.netgrif.application.engine.objects.petrinet.domain.dataset.MultichoiceMapField; -import com.netgrif.application.engine.petrinet.domain.version.StringToVersionConverter; import com.netgrif.application.engine.objects.petrinet.domain.version.Version; +import com.netgrif.application.engine.petrinet.domain.version.StringToVersionConverter; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService; import com.netgrif.application.engine.petrinet.web.responsebodies.PetriNetReference; import com.netgrif.application.engine.utils.FullPageRequest; import com.netgrif.application.engine.workflow.service.interfaces.IConfigurableMenuService; @@ -19,7 +19,10 @@ import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; -import java.util.*; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; import java.util.stream.Collectors; @Service @@ -38,12 +41,12 @@ public class ConfigurableMenuService implements IConfigurableMenuService { /** * Constructs a map that can be used as a value for any {@link com.netgrif.application.engine.objects.petrinet.domain.dataset.MapOptionsField}. - * + *

* The map will contain strings related to process nets authored by the provided user. - * + *

* A key of the map is a string of the form "<net identifier>:<net version>". * The version portion of the string uses the dash (-) character to separate the major, minor a patch version numbers instead of the traditional dot character. - * + *

* A value of the map is an {@link I18nString} with no translations of the form "<net identifier> : <net version>". * The default value of the net title is used. * @@ -52,7 +55,7 @@ public class ConfigurableMenuService implements IConfigurableMenuService { */ @Override public Map getNetsByAuthorAsMapOptions(AbstractUser author, Locale locale) { - LoggedUser loggedAuthor = ActorTransformer.toLoggedUser(author); + LoggedUser loggedAuthor = author instanceof LoggedUser ? (LoggedUser) author : ActorTransformer.toLoggedUser(author); PetriNetSearch requestQuery = new PetriNetSearch(); requestQuery.setAuthor(ActorTransformer.toActorRef(author)); List nets = this.petriNetService.search(requestQuery, loggedAuthor, new FullPageRequest(), locale).getContent(); @@ -110,7 +113,7 @@ public Map getAvailableRolesFromNet(EnumerationMapField proc /** * Constructs a map that can be used as a value for any {@link com.netgrif.application.engine.objects.petrinet.domain.dataset.MapOptionsField}. - * + *

* The map will contain all the options from the input field except for those that are selected in the input field. * * @param mapField a map field whose value complement we want to get @@ -126,11 +129,11 @@ public Map removeSelectedRoles(MultichoiceMapField mapField) /** * Constructs a map that can be used as a value for any {@link com.netgrif.application.engine.objects.petrinet.domain.dataset.MapOptionsField}. - * + *

* The map will contain a union of the options that are already present in the {@code addedRoles} field with the options selected in the {@code rolesAvailable} field. - * + *

* The keys remain unchanged. - * + *

* The values of the map are a combination of the options from the {@code addedRoles} field (they remain unchanged) * and new values corresponding to the new keys from the {@code rolesAvailable} field. The new values are of the form "<original value> (<net title>)" * diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java index d803d076a6c..504366ee1e6 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/FilterImportExportService.java @@ -6,35 +6,33 @@ import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; import com.google.common.collect.Lists; +import com.netgrif.application.engine.auth.service.UserService; +import com.netgrif.application.engine.configuration.properties.FilterConfigurationProperties; +import com.netgrif.application.engine.files.minio.StorageConfigurationProperties; import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; -import com.netgrif.application.engine.files.minio.StorageConfigurationProperties; import com.netgrif.application.engine.objects.common.ResourceNotFoundException; import com.netgrif.application.engine.objects.common.ResourceNotFoundExceptionCode; -import com.netgrif.application.engine.workflow.domain.FilterDeserializer; -import com.netgrif.application.engine.objects.workflow.domain.IllegalFilterFileException; -import com.netgrif.application.engine.auth.service.UserService; -import com.netgrif.application.engine.configuration.properties.FilterConfigurationProperties; -import com.netgrif.application.engine.objects.petrinet.domain.throwable.TransitionNotExecutableException; -import com.netgrif.application.engine.objects.workflow.domain.filter.FilterImportExport; -import com.netgrif.application.engine.objects.workflow.domain.filter.FilterImportExportList; import com.netgrif.application.engine.objects.petrinet.domain.I18nString; import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.dataset.EnumerationMapField; import com.netgrif.application.engine.objects.petrinet.domain.dataset.FileFieldValue; import com.netgrif.application.engine.objects.petrinet.domain.dataset.logic.FieldBehavior; +import com.netgrif.application.engine.objects.petrinet.domain.throwable.TransitionNotExecutableException; +import com.netgrif.application.engine.objects.workflow.domain.*; +import com.netgrif.application.engine.objects.workflow.domain.filter.FilterImportExport; +import com.netgrif.application.engine.objects.workflow.domain.filter.FilterImportExportList; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.startup.runner.DefaultFiltersRunner; import com.netgrif.application.engine.startup.ImportHelper; +import com.netgrif.application.engine.startup.runner.DefaultFiltersRunner; import com.netgrif.application.engine.utils.InputStreamToString; +import com.netgrif.application.engine.workflow.domain.FilterDeserializer; import com.netgrif.application.engine.objects.workflow.domain.*; import com.netgrif.application.engine.workflow.params.CreateCaseParams; import com.netgrif.application.engine.workflow.service.interfaces.IDataService; import com.netgrif.application.engine.workflow.service.interfaces.IFilterImportExportService; import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; -import com.netgrif.application.engine.objects.workflow.domain.Case; -import com.netgrif.application.engine.objects.workflow.domain.Task; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -263,7 +261,7 @@ protected Map performImport(FilterImportExportList filterList) t filterCase.get().getDataSet().get(FIELD_FILTER).addBehavior(IMPORT_FILTER_TRANSITION, Collections.singleton(FieldBehavior.VISIBLE)); workflowService.save(filterCase.get()); }); - taskService.assignTasks(taskService.findAllById(new ArrayList<>(importedFilterTaskIds.values())), userService.getLoggedUser()); + taskService.assignTasks(taskService.findAllById(new ArrayList<>(importedFilterTaskIds.values())), userService.getLoggedUserFromContext()); changeFilterField(importedFilterTaskIds.values()); return importedFilterTaskIds; } @@ -319,7 +317,7 @@ private void changeVisibilityByAllowedNets(boolean allowedNetsMissing, Case filt protected FilterImportExportList loadFromXML() throws IOException, IllegalFilterFileException { Case exportCase = workflowService.searchOne( QCase.case$.processIdentifier.eq(IMPORT_NET_IDENTIFIER) - .and(QCase.case$.author.id.eq(userService.getLoggedUser().getStringId())) + .and(QCase.case$.author.id.eq(userService.getLoggedUserFromContext().getStringId())) ); FileFieldValue ffv = (FileFieldValue) exportCase.getDataSet().get(UPLOAD_FILE_FIELD).getValue(); @@ -337,7 +335,7 @@ protected FilterImportExportList loadFromXML() throws IOException, IllegalFilter @Transactional protected FileFieldValue createXML(FilterImportExportList filters) throws IOException { - String filePath = fileStorageConfiguration.getPath() + "/filterExport/" + userService.getLoggedUser().getStringId() + "/" + filterProperties.getExport().getFileName(); + String filePath = fileStorageConfiguration.getPath() + "/filterExport/" + userService.getLoggedUserFromContext().getStringId() + "/" + filterProperties.getExport().getFileName(); File f = new File(filePath); f.getParentFile().mkdirs(); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java index 95c04ae26c7..21f70e1a507 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/MenuImportExportService.java @@ -8,12 +8,6 @@ import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.files.StorageResolverService; import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; -import com.netgrif.application.engine.workflow.domain.FilterDeserializer; -import com.netgrif.application.engine.workflow.domain.IllegalMenuFileException; -import com.netgrif.application.engine.workflow.params.CreateCaseParams; -import com.netgrif.application.engine.workflow.params.TaskParams; -import com.netgrif.application.engine.workflow.service.interfaces.IMenuImportExportService; -import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; import com.netgrif.application.engine.objects.petrinet.domain.I18nString; import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.dataset.EnumerationMapField; @@ -22,14 +16,21 @@ import com.netgrif.application.engine.objects.petrinet.domain.dataset.MultichoiceMapField; import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; import com.netgrif.application.engine.objects.petrinet.domain.throwable.TransitionNotExecutableException; -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.startup.ImportHelper; -import com.netgrif.application.engine.utils.InputStreamToString; -import com.netgrif.application.engine.objects.workflow.domain.*; +import com.netgrif.application.engine.objects.workflow.domain.AuthorizationType; +import com.netgrif.application.engine.objects.workflow.domain.Case; +import com.netgrif.application.engine.objects.workflow.domain.QTask; +import com.netgrif.application.engine.objects.workflow.domain.Task; import com.netgrif.application.engine.objects.workflow.domain.menu.Menu; import com.netgrif.application.engine.objects.workflow.domain.menu.MenuAndFilters; import com.netgrif.application.engine.objects.workflow.domain.menu.MenuEntry; import com.netgrif.application.engine.objects.workflow.domain.menu.MenuEntryRole; +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; +import com.netgrif.application.engine.startup.ImportHelper; +import com.netgrif.application.engine.utils.InputStreamToString; +import com.netgrif.application.engine.workflow.domain.FilterDeserializer; +import com.netgrif.application.engine.workflow.domain.IllegalMenuFileException; +import com.netgrif.application.engine.workflow.params.CreateCaseParams; +import com.netgrif.application.engine.workflow.params.TaskParams; import com.netgrif.application.engine.workflow.service.interfaces.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -274,7 +275,7 @@ public String createMenuItemCase(StringBuilder resultMessage, MenuEntry item, St try { taskService.assignTask(TaskParams.with() .task(task) - .user(userService.getLoggedUser()) + .user(userService.getLoggedUserFromContext()) .build()); menuItemCase.getDataSet().get(MENU_IDENTIFIER).setValue(menuIdentifier); menuItemCase.getDataSet().get(PARENT_ID).setValue(parentId); @@ -305,7 +306,7 @@ protected MenuAndFilters loadFromXML(FileFieldValue ffv) throws IOException, Ill protected FileFieldValue createXML(MenuAndFilters menuAndFilters, String parentId, FileField fileField) throws IOException { FileFieldValue ffv = new FileFieldValue(); try { - ffv.setName("menu_" + userService.getLoggedUser().getName().replaceAll("\\s+", "") + ".xml"); + ffv.setName("menu_" + userService.getLoggedUserFromContext().getName().replaceAll("\\s+", "") + ".xml"); ffv.setPath(storageResolverService.resolve(fileField.getStorageType()).getPath(parentId, fileField.getImportId(), ffv.getName())); File f = new File(ffv.getPath()); XmlMapper xmlMapper = new XmlMapper(); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/TaskAuthorizationService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/TaskAuthorizationService.java index fa2be2cce08..8c33f6e9bb4 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/TaskAuthorizationService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/TaskAuthorizationService.java @@ -1,16 +1,18 @@ package com.netgrif.application.engine.workflow.service; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.petrinet.domain.roles.RolePermission; -import com.netgrif.application.engine.petrinet.domain.throwable.IllegalTaskStateException; +import com.netgrif.application.engine.objects.workflow.domain.Case; import com.netgrif.application.engine.objects.workflow.domain.Task; +import com.netgrif.application.engine.petrinet.domain.throwable.IllegalTaskStateException; import com.netgrif.application.engine.workflow.service.interfaces.ITaskAuthorizationService; import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; +import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.*; +import java.util.Arrays; +import java.util.Map; @Service public class TaskAuthorizationService extends AbstractAuthorizationService implements ITaskAuthorizationService { @@ -18,13 +20,11 @@ public class TaskAuthorizationService extends AbstractAuthorizationService imple @Autowired private ITaskService taskService; - @Override - public Boolean userHasAtLeastOneRolePermission(LoggedUser loggedUser, String taskId, RolePermission... permissions) { - return userHasAtLeastOneRolePermission(loggedUser, taskService.findById(taskId), permissions); - } + @Autowired + private IWorkflowService workflowService; @Override - public Boolean userHasAtLeastOneRolePermission(AbstractUser user, Task task, RolePermission... permissions) { + public Boolean userHasAtLeastOneRolePermission(LoggedUser user, Task task, RolePermission... permissions) { if (task.getRoles() == null || task.getRoles().isEmpty()) return null; @@ -41,12 +41,7 @@ public Boolean userHasAtLeastOneRolePermission(AbstractUser user, Task task, Rol } @Override - public Boolean userHasUserListPermission(LoggedUser loggedUser, String taskId, RolePermission... permissions) { - return userHasUserListPermission(loggedUser, taskService.findById(taskId), permissions); - } - - @Override - public Boolean userHasUserListPermission(AbstractUser user, Task task, RolePermission... permissions) { + public Boolean userHasUserListPermission(LoggedUser user, Task task, RolePermission... permissions) { if (task.getActorRefs() == null || task.getActorRefs().isEmpty()) { return null; } @@ -67,27 +62,14 @@ public Boolean userHasUserListPermission(AbstractUser user, Task task, RolePermi } @Override - public boolean isAssignee(LoggedUser loggedUser, String taskId) { - return isAssignee(loggedUser, taskService.findById(taskId)); - } - - @Override - public boolean isAssignee(AbstractUser user, String taskId) { - return isAssignee(user, taskService.findById(taskId)); - } - - @Override - public boolean isAssignee(AbstractUser user, Task task) { + public boolean isAssignee(LoggedUser user, Task task) { if (!isAssigned(task)) return false; - else - // TODO: impersonation user.getSelfOrImpersonated().getStringId() - return task.getUserId().equals(user.getStringId()) - || (user.getAttributeValue("anonymous") != null && (Boolean) user.getAttributeValue("anonymous")); - } - - private boolean isAssigned(String taskId) { - return isAssigned(taskService.findById(taskId)); + else { + Case caze = workflowService.findOne(task.getCaseId()); + return user.hasProcessAccess(caze.getProcessIdentifier()) + && (task.getUserId().equals(user.getSelfOrImpersonatedStringId()) || (Boolean) user.getAttributeValue("anonymous") || task.getImpersonatorUserId().equals(user.getStringId())); + } } private boolean isAssigned(Task task) { @@ -96,116 +78,112 @@ private boolean isAssigned(Task task) { @Override public boolean canCallAssign(LoggedUser loggedUser, String taskId) { - // TODO: impersonation loggedUser.getSelfOrImpersonated().isAdmin() if (loggedUser.isAdmin()) { return true; } + Task currentTask = taskService.findById(taskId); + Case caze = workflowService.findOne(currentTask.getCaseId()); + boolean processPerm = loggedUser.hasProcessAccess(caze.getProcessIdentifier()); + if (!processPerm) { + return false; + } - Task task = taskService.findById(taskId); - // TODO: impersonation - Boolean userPerm = userHasUserListPermission(loggedUser, task, RolePermission.ASSIGN); + Boolean userPerm = userHasUserListPermission(loggedUser, currentTask, RolePermission.ASSIGN); if (userPerm != null) { return userPerm; } - // TODO: impersonation - Boolean rolePerm = userHasAtLeastOneRolePermission(loggedUser, task, RolePermission.ASSIGN); + Boolean rolePerm = userHasAtLeastOneRolePermission(loggedUser, currentTask, RolePermission.ASSIGN); return rolePerm != null && rolePerm; } @Override public boolean canCallDelegate(LoggedUser loggedUser, String taskId) { - // TODO: impersonation loggedUser.getSelfOrImpersonated().isAdmin() if (loggedUser.isAdmin()) { return true; } - - Task task = taskService.findById(taskId); - // TODO: impersonation - Boolean userPerm = userHasUserListPermission(loggedUser, task, RolePermission.DELEGATE); + Task currentTask = taskService.findById(taskId); + Case caze = workflowService.findOne(currentTask.getCaseId()); + boolean processPerm = loggedUser.hasProcessAccess(caze.getProcessIdentifier()); + if (!processPerm) { + return false; + } + Boolean userPerm = userHasUserListPermission(loggedUser, currentTask, RolePermission.DELEGATE); if (userPerm != null) { return userPerm; } - // TODO: impersonation - Boolean rolePerm = userHasAtLeastOneRolePermission(loggedUser, task, RolePermission.DELEGATE); + Boolean rolePerm = userHasAtLeastOneRolePermission(loggedUser, currentTask, RolePermission.DELEGATE); return rolePerm != null && rolePerm; } @Override public boolean canCallFinish(LoggedUser loggedUser, String taskId) throws IllegalTaskStateException { - if (!isAssigned(taskId)) { - throw new IllegalTaskStateException("Task with ID '%s' cannot be finished, because it is not assigned!".formatted(taskId)); + Task currentTask = taskService.findById(taskId); + if (!isAssigned(currentTask)) { + throw new IllegalTaskStateException("Task with ID '" + taskId + "' cannot be finished, because it is not assigned!"); } - // TODO: impersonation if (loggedUser.isAdmin()) { return true; } - - Task task = taskService.findById(taskId); - // TODO: impersonation - if (!isAssignee(loggedUser, task)) { + if (!isAssignee(loggedUser, currentTask)) { return false; } - // TODO: impersonation - Boolean userPerm = userHasUserListPermission(loggedUser, task, RolePermission.FINISH); + + Boolean userPerm = userHasUserListPermission(loggedUser, currentTask, RolePermission.FINISH); if (userPerm != null) { return userPerm; } - // TODO: impersonation - Boolean rolePerm = userHasAtLeastOneRolePermission(loggedUser, task, RolePermission.FINISH); + Boolean rolePerm = userHasAtLeastOneRolePermission(loggedUser, currentTask, RolePermission.FINISH); return rolePerm != null && rolePerm; } /** * To return true, the task should not have set up the assigned user policy for cancel to "false" - * */ + * + */ private boolean canAssignedCancel(Task task) { return task.getAssignedUserPolicy() == null || task.getAssignedUserPolicy().get("cancel") == null || task.getAssignedUserPolicy().get("cancel"); } + @Override public boolean canCallCancel(LoggedUser loggedUser, String taskId) throws IllegalTaskStateException { - if (!isAssigned(taskId)) { + Task currentTask = taskService.findById(taskId); + if (!isAssigned(currentTask)) { throw new IllegalTaskStateException("Task with ID '%s' cannot be canceled, because it is not assigned!".formatted(taskId)); } - // TODO: impersonation if (loggedUser.isAdmin()) { return true; } - - Task task = taskService.findById(taskId); - // TODO: impersonation - if (!isAssignee(loggedUser, task) || !canAssignedCancel(task)) { + if (!isAssignee(loggedUser, currentTask) || !canAssignedCancel(currentTask)) { return false; } - // TODO: impersonation - Boolean userPerm = userHasUserListPermission(loggedUser, task, RolePermission.CANCEL); + Boolean userPerm = userHasUserListPermission(loggedUser, currentTask, RolePermission.CANCEL); if (userPerm != null) { return userPerm; } - // TODO: impersonation - Boolean rolePerm = userHasAtLeastOneRolePermission(loggedUser, task, RolePermission.CANCEL); + Boolean rolePerm = userHasAtLeastOneRolePermission(loggedUser, currentTask, RolePermission.CANCEL); return rolePerm != null && rolePerm; } @Override public boolean canCallSaveData(LoggedUser loggedUser, String taskId) { - // TODO: impersonation loggedUser.getSelfOrImpersonated().isAdmin() - return loggedUser.isAdmin() || isAssignee(loggedUser, taskId); + Task currentTask = taskService.findById(taskId); + return loggedUser.isAdmin() || isAssignee(loggedUser, currentTask); } @Override public boolean canCallSaveFile(LoggedUser loggedUser, String taskId) { - // TODO: impersonation loggedUser.getSelfOrImpersonated().isAdmin() - return loggedUser.isAdmin() || isAssignee(loggedUser, taskId); + Task currentTask = taskService.findById(taskId); + return loggedUser.isAdmin() || isAssignee(loggedUser, currentTask); } - private Map findUserPermissions(Task task, AbstractUser user) { - return findUserPermissions(task.getActors(), user); + private Map findUserPermissions(Task task, LoggedUser user) { + return findUserPermissions(task.getActors(), user.getSelfOrImpersonated()); } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/TaskSearchService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/TaskSearchService.java index 377dda5ce86..4e2669e6101 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/TaskSearchService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/TaskSearchService.java @@ -1,21 +1,24 @@ package com.netgrif.application.engine.workflow.service; +import com.netgrif.application.engine.adapter.spring.workflow.domain.QTask; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.petrinet.domain.PetriNetSearch; +import com.netgrif.application.engine.objects.workflow.domain.ProcessResourceId; +import com.netgrif.application.engine.objects.workflow.domain.Task; import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.petrinet.web.responsebodies.PetriNetReference; import com.netgrif.application.engine.utils.FullPageRequest; -import com.netgrif.application.engine.objects.workflow.domain.ProcessResourceId; -import com.netgrif.application.engine.adapter.spring.workflow.domain.QTask; -import com.netgrif.application.engine.objects.workflow.domain.Task; import com.netgrif.application.engine.workflow.web.requestbodies.TaskSearchRequest; import com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.TaskSearchCaseRequest; import com.querydsl.core.BooleanBuilder; import com.querydsl.core.types.Predicate; +import com.querydsl.core.types.dsl.BooleanExpression; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.*; +import java.util.List; +import java.util.Locale; +import java.util.Objects; import java.util.stream.Collectors; @Service @@ -25,10 +28,8 @@ public class TaskSearchService extends MongoSearchService { private IPetriNetService petriNetService; public Predicate buildQuery(List requests, LoggedUser user, Locale locale, Boolean isIntersection) { - // TODO: impersonation -// LoggedUser loggedOrImpersonated = user.getSelfOrImpersonated(); - LoggedUser loggedOrImpersonated = user; - List singleQueries = requests.stream().map(r -> this.buildSingleQuery(r, loggedOrImpersonated, locale)).collect(Collectors.toList()); + LoggedUser loggedOrImpersonated = user.getSelfOrImpersonated(); + List singleQueries = requests.stream().map(r -> this.buildSingleQuery(r, user, locale)).collect(Collectors.toList()); if (isIntersection && !singleQueries.stream().allMatch(Objects::nonNull)) { // one of the queries evaluates to empty set => the entire result is an empty set @@ -52,6 +53,10 @@ public Predicate buildQuery(List requests, LoggedUser user, L permissionConstraints.or(buildViewActorQueryConstraint(loggedOrImpersonated)); permissionConstraints.andNot(buildNegativeViewActorsQueryConstraint(loggedOrImpersonated)); builder.and(permissionConstraints); + BooleanExpression impersonatedProcessesConstraints = buildImpersonatedProcessesConstraint(user); + if (impersonatedProcessesConstraints != null) { + builder.and(impersonatedProcessesConstraints); + } return builder; } @@ -289,6 +294,22 @@ public boolean buildGroupQuery(TaskSearchRequest request, LoggedUser user, Local return false; } + private static BooleanExpression buildImpersonatedProcessesConstraint(LoggedUser loggedUser) { + if (loggedUser.isAdmin() || !loggedUser.isImpersonating()) { + return null; + } + if (loggedUser.isProcessAccessDeny()) { + return null; + } + if (loggedUser.getImpersonatedProcesses() == null || loggedUser.getImpersonatedProcesses().isEmpty()) { + return null; + } + if (loggedUser.isImpersonatedProcessesListAllowing()) { + return QTask.task.processIdentifier.in(loggedUser.getImpersonatedProcesses()); + } + return QTask.task.processIdentifier.notIn(loggedUser.getImpersonatedProcesses()); + } + private void buildTagsQuery(TaskSearchRequest request, BooleanBuilder query) { if (request.tags == null || request.tags.isEmpty()) { return; diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/TaskService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/TaskService.java index e0cb97dc73b..fa6556bd8fc 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/TaskService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/TaskService.java @@ -1,38 +1,38 @@ package com.netgrif.application.engine.workflow.service; import com.google.common.collect.Ordering; +import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService; import com.netgrif.application.engine.auth.service.GroupService; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.objects.petrinet.domain.dataset.ActorFieldValue; -import com.netgrif.application.engine.objects.petrinet.domain.dataset.ActorListFieldValue; -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskMappingService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticTaskService; +import com.netgrif.application.engine.objects.auth.domain.AbstractUser; +import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.event.events.task.*; import com.netgrif.application.engine.objects.petrinet.domain.*; import com.netgrif.application.engine.objects.petrinet.domain.arcs.Arc; import com.netgrif.application.engine.objects.petrinet.domain.arcs.ArcOrderComparator; import com.netgrif.application.engine.objects.petrinet.domain.arcs.ResetArc; +import com.netgrif.application.engine.objects.petrinet.domain.dataset.ActorFieldValue; +import com.netgrif.application.engine.objects.petrinet.domain.dataset.ActorListFieldValue; import com.netgrif.application.engine.objects.petrinet.domain.dataset.Field; import com.netgrif.application.engine.objects.petrinet.domain.events.EventPhase; import com.netgrif.application.engine.objects.petrinet.domain.events.EventType; import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; import com.netgrif.application.engine.objects.petrinet.domain.roles.RolePermission; import com.netgrif.application.engine.objects.petrinet.domain.throwable.TransitionNotExecutableException; -import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService; -import com.netgrif.application.engine.utils.DateUtils; -import com.netgrif.application.engine.utils.FullPageRequest; -import com.netgrif.application.engine.validation.service.interfaces.IValidationService; import com.netgrif.application.engine.objects.workflow.domain.*; import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.EventOutcome; import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.dataoutcomes.SetDataEventOutcome; import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.taskoutcomes.*; -import com.netgrif.application.engine.workflow.domain.outcomes.ReloadTaskOutcome; -import com.netgrif.application.engine.workflow.domain.repositories.TaskRepository; import com.netgrif.application.engine.objects.workflow.domain.triggers.TimeTrigger; import com.netgrif.application.engine.objects.workflow.domain.triggers.Trigger; +import com.netgrif.application.engine.utils.DateUtils; +import com.netgrif.application.engine.utils.FullPageRequest; +import com.netgrif.application.engine.validation.service.interfaces.IValidationService; +import com.netgrif.application.engine.workflow.domain.outcomes.ReloadTaskOutcome; +import com.netgrif.application.engine.workflow.domain.repositories.TaskRepository; import com.netgrif.application.engine.workflow.params.DelegateTaskParams; import com.netgrif.application.engine.workflow.params.TaskParams; import com.netgrif.application.engine.workflow.service.interfaces.IDataService; @@ -123,11 +123,12 @@ public List assignTasks(List tasks, AbstractUser u @Override public List assignTasks(List tasks, AbstractUser user, Map params) throws TransitionNotExecutableException { + LoggedUser loggedUser = user instanceof LoggedUser ? (LoggedUser) user : ActorTransformer.toLoggedUser(user); List outcomes = new ArrayList<>(); for (Task task : tasks) { outcomes.add(assignTask(TaskParams.with() .task(task) - .user(user) + .user(loggedUser) .params(params) .build())); } @@ -141,6 +142,7 @@ public AssignTaskEventOutcome assignTask(TaskParams taskParams) throws Transitio Case useCase = taskParams.getUseCase(); Task task = taskParams.getTask(); Transition transition = useCase.getPetriNet().getTransition(task.getTransitionId()); + LoggedUser loggedUser = taskParams.getUser(); List outcomes = new ArrayList<>(eventService.runActions(transition.getPreAssignActions(), useCase, task, transition, taskParams.getParams())); @@ -157,9 +159,10 @@ public AssignTaskEventOutcome assignTask(TaskParams taskParams) throws Transitio publisher.publishEvent(new AssignTaskEvent(outcome, EventPhase.POST, taskParams.getUser())); addMessageToOutcome(transition, EventType.ASSIGN, outcome); - // TODO: impersonation user.getSelfOrImpersonated().getEmail() - log.info("[{}]: Task [{}] in case [{}] assigned to [{}]", useCase.getStringId(), task.getTitle(), - useCase.getTitle(), taskParams.getUser().getEmail()); + String userMessage = loggedUser.isImpersonating() + ? "[" + loggedUser.getUsername() + "] in realm [" + loggedUser.getRealmId() + "]. Impersonation for user [" + loggedUser.getImpersonatedUser().getUsername() + "]" + : "[" + loggedUser.getUsername() + "] in realm [" + loggedUser.getRealmId() + "]"; + log.info("[{}]: Task [{}] in case [{}] assigned to {}", useCase.getStringId(), task.getTitle(), useCase.getTitle(), userMessage); return outcome; } @@ -167,15 +170,19 @@ public AssignTaskEventOutcome assignTask(TaskParams taskParams) throws Transitio protected Case assignTaskToUser(AbstractUser user, Task task, Case useCase, Transition transition) throws TransitionNotExecutableException { useCase.getPetriNet().initializeArcs(); - // TODO: impersonation user.getSelfOrImpersonated().getEmail() - log.info("[{}]: Assigning task [{}] to user [{}]", useCase.getStringId(), task.getTitle(), user.getEmail()); - startExecution(transition, useCase); - // TODO: impersonation - task.setAssignee(ActorTransformer.toActorRef(user)); task.setStartDate(LocalDateTime.now()); - // TODO: impersonation - task.setUser(user); + String userMessage; + if (user instanceof LoggedUser loggedUser && loggedUser.isImpersonating()) { + task.setImpersonatorUserId(loggedUser.getStringId()); + task.setImpersonatorUsername(loggedUser.getUsername()); + task.setAssignee(ActorTransformer.toActorRef(loggedUser.getSelfOrImpersonated())); + userMessage = "[" + loggedUser.getUsername() + "] in realm [" + loggedUser.getRealmId() + "]. Impersonation for user [" + loggedUser.getImpersonatedUser().getUsername() + "]"; + } else { + task.setAssignee(ActorTransformer.toActorRef(user)); + userMessage = "[" + user.getUsername() + "] in realm [" + user.getRealmId() + "]"; + } + log.info("[{}]: Assigning task [{}] to user {}", useCase.getStringId(), task.getTitle(), userMessage); useCase = workflowService.save(useCase); save(task); @@ -193,11 +200,12 @@ public List finishTasks(List tasks, AbstractUser u @Override public List finishTasks(List tasks, AbstractUser user, Map params) throws TransitionNotExecutableException { + LoggedUser loggedUser = user instanceof LoggedUser ? (LoggedUser) user : ActorTransformer.toLoggedUser(user); List outcomes = new ArrayList<>(); for (Task task : tasks) { outcomes.add(finishTask(TaskParams.with() .task(task) - .user(user) + .user(loggedUser) .params(params) .build())); } @@ -210,19 +218,20 @@ public FinishTaskEventOutcome finishTask(TaskParams taskParams) throws Transitio Task task = taskParams.getTask(); Case useCase = taskParams.getUseCase(); - AbstractUser user = taskParams.getUser(); + LoggedUser user = taskParams.getUser(); if (task.getUserId() == null) { throw new IllegalArgumentException("Task with id=%s is not assigned to any user.".formatted(task.getStringId())); } - // TODO: impersonation - if (!task.getUserId().equals(user.getStringId()) && !((Boolean) user.getAttributes().containsKey("anonymous"))) { + if (!task.getUserId().equals(user.getSelfOrImpersonatedStringId()) && !((Boolean) user.getAttributes().containsKey("anonymous"))) { throw new IllegalArgumentException("User that is not assigned tried to finish task"); } Transition transition = useCase.getPetriNet().getTransition(task.getTransitionId()); - // TODO: impersonation - log.info("[{}]: Finishing task [{}] to user [{}]", useCase.getStringId(), task.getTitle(), user.getEmail()); + String userMessage = user.isImpersonating() + ? "[" + user.getUsername() + "] in realm [" + user.getRealmId() + "]. Impersonation for user [" + user.getImpersonatedUser().getUsername() + "]" + : "[" + user.getUsername() + "] in realm [" + user.getRealmId() + "]"; + log.info("[{}]: Finishing task [{}] to user {}", useCase.getStringId(), task.getTitle(), userMessage); validateData(transition, useCase); List outcomes = new ArrayList<>(eventService.runActions(transition.getPreFinishActions(), useCase, @@ -260,11 +269,12 @@ public List cancelTasks(List tasks, AbstractUser u @Override public List cancelTasks(List tasks, AbstractUser user, Map params) { + LoggedUser loggedUser = user instanceof LoggedUser ? (LoggedUser) user : ActorTransformer.toLoggedUser(user); List outcomes = new ArrayList<>(); for (Task task : tasks) { outcomes.add(cancelTask(TaskParams.with() .task(task) - .user(user) + .user(loggedUser) .params(params) .build())); } @@ -277,11 +287,13 @@ public CancelTaskEventOutcome cancelTask(TaskParams taskParams) { Task task = taskParams.getTask(); Case useCase = taskParams.getUseCase(); - AbstractUser user = taskParams.getUser(); + LoggedUser user = taskParams.getUser(); Transition transition = useCase.getPetriNet().getTransition(task.getTransitionId()); - // TODO: impersonation - log.info("[{}]: Canceling task [{}] to user [{}]", useCase.getStringId(), task.getTitle(), user.getEmail()); + String userMessage = user.isImpersonating() + ? "[" + user.getUsername() + "] in realm [" + user.getRealmId() + "]. Impersonation for user [" + user.getImpersonatedUser().getUsername() + "]" + : "[" + user.getUsername() + "] in realm [" + user.getRealmId() + "]"; + log.info("[{}]: Canceling task [{}] to user {}", useCase.getStringId(), task.getTitle(), userMessage); List outcomes = new ArrayList<>(eventService.runActions(transition.getPreCancelActions(), useCase, task, transition, taskParams.getParams())); @@ -305,9 +317,7 @@ public CancelTaskEventOutcome cancelTask(TaskParams taskParams) { outcome.setOutcomes(outcomes); addMessageToOutcome(transition, EventType.CANCEL, outcome); publisher.publishEvent(new CancelTaskEvent(outcome, EventPhase.POST, user)); - // TODO: impersonation - log.info("[{}]: Task [{}] in case [{}] assigned to [{}] was cancelled", useCase.getStringId(), task.getTitle(), - useCase.getTitle(), user.getEmail()); + log.info("[{}]: Task [{}] in case [{}] assigned to {} was cancelled", useCase.getStringId(), task.getTitle(), useCase.getTitle(), userMessage); return outcome; } @@ -356,7 +366,7 @@ protected void fillAndValidateAttributes(TaskParams taskParams) { taskParams.setUseCase(useCase); } if (taskParams.getUser() == null) { - AbstractUser user = userService.getLoggedOrSystem(); + LoggedUser user = userService.getLoggedOrSystem(); taskParams.setUser(user); } } @@ -378,7 +388,7 @@ protected void fillAndValidateAttributes(DelegateTaskParams taskParams) { if (delegator == null) { delegator = userService.getLoggedOrSystem(); } - taskParams.setDelegator(delegator); + taskParams.setDelegator(delegator instanceof LoggedUser loggedUser ? loggedUser : ActorTransformer.toLoggedUser(delegator)); } if (taskParams.getNewAssignee() == null) { if (taskParams.getNewAssigneeId() == null) { @@ -405,6 +415,8 @@ private Case returnTokens(Task task, Case useCase) { task.setAssignee(null); task.setStartDate(null); + task.setImpersonatorUserId(null); + task.setImpersonatorUsername(null); useCase = workflowService.save(useCase); save(task); @@ -417,12 +429,15 @@ public DelegateTaskEventOutcome delegateTask(DelegateTaskParams delegateTaskPara fillAndValidateAttributes(delegateTaskParams); AbstractUser newAssignee = delegateTaskParams.getNewAssignee(); - AbstractUser delegator = delegateTaskParams.getDelegator(); + LoggedUser delegator = delegateTaskParams.getDelegator(); Task task = delegateTaskParams.getTask(); Case useCase = delegateTaskParams.getUseCase(); Transition transition = useCase.getPetriNet().getTransition(task.getTransitionId()); - log.info("[{}]: Delegating task [{}] to user [{}]", useCase.getStringId(), task.getTitle(), newAssignee.getEmail()); + String userMessage = delegator.isImpersonating() + ? "[" + delegator.getUsername() + "] in realm [" + delegator.getRealmId() + "]. Impersonation for user [" + delegator.getImpersonatedUser().getUsername() + "]" + : "[" + delegator.getUsername() + "] in realm [" + delegator.getRealmId() + "]"; + log.info("[{}]: Delegating task [{}] to user [{}] from user {}", useCase.getStringId(), task.getTitle(), newAssignee.getEmail(), userMessage); List outcomes = new ArrayList<>(eventService.runActions(transition.getPreDelegateActions(), useCase, task, transition, delegateTaskParams.getParams())); @@ -447,9 +462,7 @@ public DelegateTaskEventOutcome delegateTask(DelegateTaskParams delegateTaskPara addMessageToOutcome(transition, EventType.DELEGATE, outcome); publisher.publishEvent(new DelegateTaskEvent(outcome, EventPhase.POST, delegator, newAssignee.getStringId())); - // TODO: impersonation - log.info("Task [{}] in case [{}] assigned to [{}] was delegated to [{}]", task.getTitle(), useCase.getTitle(), - newAssignee.getEmail(), newAssignee.getEmail()); + log.info("Task [{}] in case [{}] assigned to {} was delegated to [{}]", task.getTitle(), useCase.getTitle(), userMessage, newAssignee.getEmail()); return outcome; } @@ -458,6 +471,8 @@ protected Case delegate(AbstractUser delegated, Task task, Case useCase, Transit if (task.getUserId() != null) { task.setAssignee(ActorTransformer.toActorRef(delegated)); task.setUser(delegated); + task.setImpersonatorUsername(null); + task.setImpersonatorUserId(null); save(task); return useCase; } else { @@ -484,10 +499,9 @@ protected Case evaluateRules(TaskEvent taskEvent) { * * * - * @param useCase useCase for which to reload tasks + * @param useCase useCase for which to reload tasks * @param lazyCaseSave if set to true, the useCase is saved only if any task is about to be executed. If set to false * the useCase is saved every time this method is called. - * * @return {@link ReloadTaskOutcome}, which holds the information if any task was executed and if the useCase was saved */ @SuppressWarnings("StatementWithEmptyBody") @@ -576,6 +590,8 @@ protected Case finishExecution(Transition transition, Task task, Case useCase) t task.setFinishDate(LocalDateTime.now()); task.setFinishedBy(task.getUserId()); task.setAssignee(null); + task.setImpersonatorUsername(null); + task.setImpersonatorUserId(null); save(task); return workflowService.save(useCase); @@ -673,26 +689,30 @@ public Task findOne(String taskId) { @Override public Page getAll(LoggedUser loggedUser, Pageable pageable, Locale locale) { List tasks; - // TODO: impersonation -// LoggedUser loggedOrImpersonated = loggedUser.getSelfOrImpersonated(); - LoggedUser loggedOrImpersonated = loggedUser; - if (loggedOrImpersonated.getProcessRoles().isEmpty()) { + if (loggedUser.getProcessRoles().isEmpty() || loggedUser.isProcessAccessDeny()) { tasks = new ArrayList<>(); return new PageImpl<>(tasks, pageable, 0L); } else { StringBuilder queryBuilder = new StringBuilder(); queryBuilder.append("{$or:["); - loggedOrImpersonated.getProcessRoles().forEach(role -> { + loggedUser.getProcessRoles().forEach(role -> { queryBuilder.append("{\"roles."); queryBuilder.append(role); queryBuilder.append("\":{$exists:true}},"); }); - if (!loggedOrImpersonated.getProcessRoles().isEmpty()) - queryBuilder.deleteCharAt(queryBuilder.length() - 1); - else - queryBuilder.append("{}"); + queryBuilder.deleteCharAt(queryBuilder.length() - 1); queryBuilder.append("]}"); + if (loggedUser.isImpersonating() && loggedUser.getImpersonatedProcesses() != null && !loggedUser.getImpersonatedProcesses().isEmpty()) { + String processList = loggedUser.getImpersonatedProcesses().stream() + .map(p -> "\"" + p + "\"") + .collect(Collectors.joining(",")); + if (loggedUser.isImpersonatedProcessesListAllowing()) { + queryBuilder.append(",\"processIdentifier\":{$in:[").append(processList).append("]}"); + } else { + queryBuilder.append(",\"processIdentifier\":{$nin:[").append(processList).append("]}"); + } + } BasicQuery query = new BasicQuery(queryBuilder.toString()); query = (BasicQuery) query.with(pageable); tasks = mongoTemplate.find(query, Task.class); @@ -703,6 +723,9 @@ public Page getAll(LoggedUser loggedUser, Pageable pageable, Locale locale @Override public Page search(List requests, Pageable pageable, LoggedUser user, Locale locale, Boolean isIntersection) { + if (user.isProcessAccessDeny()) { + return Page.empty(); + } com.querydsl.core.types.Predicate searchPredicate = searchService.buildQuery(requests, user, locale, isIntersection); if (searchPredicate != null) { Page page = taskRepository.findAll(searchPredicate, pageable); @@ -716,6 +739,9 @@ public Page search(List requests, Pageable pageable, Lo @Override public long count(List requests, LoggedUser user, Locale locale, Boolean isIntersection) { + if (user.isProcessAccessDeny()) { + return 0; + } com.querydsl.core.types.Predicate searchPredicate = searchService.buildQuery(requests, user, locale, isIntersection); if (searchPredicate != null) { return taskRepository.count(searchPredicate); @@ -762,9 +788,7 @@ public List findAllById(List ids) { @Override public Page findByUser(Pageable pageable, AbstractUser user) { - // TODO: impersonation -// return loadUsers(taskRepository.findByUserId(pageable, user.getSelfOrImpersonated().getStringId())); - return loadUsers(taskRepository.findByAssignee_Id(pageable, user.getStringId())); + return loadUsers(taskRepository.findByAssignee_Id(pageable, user.getSelfOrImpersonatedStringId())); } @Override @@ -879,6 +903,7 @@ private Task createFromTransition(Transition transition, Case useCase) { final Task task = com.netgrif.application.engine.adapter.spring.workflow.domain.Task.with() .title(transition.getTitle()) .processId(useCase.getPetriNetId()) + .processIdentifier(useCase.getProcessIdentifier()) .caseId(useCase.get_id().toString()) .transitionId(transition.getImportId()) .layout(transition.getLayout()) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/UserFilterSearchService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/UserFilterSearchService.java index 6edd03cdac0..0e14ea09d39 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/UserFilterSearchService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/UserFilterSearchService.java @@ -3,7 +3,6 @@ import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest; -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.workflow.domain.Case; import com.netgrif.application.engine.startup.runner.FilterRunner; import com.netgrif.application.engine.workflow.service.interfaces.IUserFilterSearchService; @@ -33,12 +32,12 @@ public List autocompleteFindFilters(String userInput) { .query( String.format("(title:%s*) AND ((dataSet.visibility.keyValue:private AND authorEmail:%s) OR (dataSet.visibility.keyValue:public))", userInput, - userService.getLoggedUser().getEmail()) + userService.getLoggedUserFromContext().getEmail()) ) .transition(Collections.singletonList("view_filter")) .build() ), - ActorTransformer.toLoggedUser(userService.getLoggedOrSystem()), + userService.getLoggedOrSystem(), PageRequest.of(0, 100), LocaleContextHolder.getLocale(), true); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowAuthorizationService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowAuthorizationService.java index d3111107a51..3ed59a83c94 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowAuthorizationService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowAuthorizationService.java @@ -1,17 +1,17 @@ package com.netgrif.application.engine.workflow.service; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRolePermission; -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.objects.workflow.domain.Case; +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowAuthorizationService; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import java.util.*; +import java.util.Arrays; +import java.util.Map; @Service public class WorkflowAuthorizationService extends AbstractAuthorizationService implements IWorkflowAuthorizationService { @@ -24,37 +24,39 @@ public class WorkflowAuthorizationService extends AbstractAuthorizationService i @Override public boolean canCallDelete(LoggedUser user, String caseId) { - // TODO: impersonation user.getSelfOrImpersonated().isAdmin() if (user.isAdmin()) { return true; } - Case requestedCase = workflowService.findOne(caseId); - // TODO: impersonation user.getSelfOrImpersonated() + boolean processPerm = user.hasProcessAccess(requestedCase.getProcessIdentifier()); + if (!processPerm) { + return false; + } Boolean userPerm = userHasUserListPermission(user, requestedCase, ProcessRolePermission.DELETE); if (userPerm != null) { return userPerm; } - // TODO: impersonation user.getSelfOrImpersonated() Boolean rolePerm = userHasAtLeastOneRolePermission(user, requestedCase.getPetriNet(), ProcessRolePermission.DELETE); return rolePerm != null && rolePerm; } @Override public boolean canCallCreate(LoggedUser user, String netId) { - // TODO: impersonation if (user.isAdmin()) { return true; } - PetriNet net = petriNetService.getPetriNet(netId); - // TODO: impersonation + boolean processPerm = user.hasProcessAccess(net.getIdentifier()); + if (!processPerm) { + return false; + } + return userHasAtLeastOneRolePermission(user, net, ProcessRolePermission.CREATE); } @Override - public Boolean userHasAtLeastOneRolePermission(AbstractUser user, PetriNet net, ProcessRolePermission... permissions) { + public Boolean userHasAtLeastOneRolePermission(LoggedUser user, PetriNet net, ProcessRolePermission... permissions) { Map aggregatePermissions = getAggregatePermissions(user, net.getPermissions()); for (ProcessRolePermission permission : permissions) { @@ -68,7 +70,7 @@ public Boolean userHasAtLeastOneRolePermission(AbstractUser user, PetriNet net, } @Override - public Boolean userHasUserListPermission(AbstractUser user, Case useCase, ProcessRolePermission... permissions) { + public Boolean userHasUserListPermission(LoggedUser user, Case useCase, ProcessRolePermission... permissions) { if (useCase.getActorRefs() == null || useCase.getActorRefs().isEmpty()) { return null; } @@ -88,7 +90,7 @@ public Boolean userHasUserListPermission(AbstractUser user, Case useCase, Proces .anyMatch(permission -> hasPermission(userPermissions.get(permission.toString()))); } - private Map findUserPermissions(Case useCase, AbstractUser user) { - return findUserPermissions(useCase.getActors(), user); + private Map findUserPermissions(Case useCase, LoggedUser user) { + return findUserPermissions(useCase.getActors(), user.getSelfOrImpersonated()); } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java index 938f38bcc79..3a3c0a9ee98 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/WorkflowService.java @@ -1,41 +1,43 @@ package com.netgrif.application.engine.workflow.service; import com.google.common.collect.Ordering; +import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService; import com.netgrif.application.engine.auth.service.GroupService; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; -import com.netgrif.application.engine.objects.petrinet.domain.dataset.*; -import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRolePermission; -import com.netgrif.application.engine.objects.workflow.domain.Case; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseMappingService; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.event.evaluators.Evaluator; +import com.netgrif.application.engine.event.services.EvaluationService; +import com.netgrif.application.engine.importer.service.FieldFactory; +import com.netgrif.application.engine.objects.auth.domain.AbstractUser; +import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.event.events.workflow.CaseEvent; import com.netgrif.application.engine.objects.event.events.workflow.CreateCaseEvent; import com.netgrif.application.engine.objects.event.events.workflow.DeleteCaseEvent; -import com.netgrif.application.engine.event.services.EvaluationService; -import com.netgrif.application.engine.importer.service.FieldFactory; import com.netgrif.application.engine.objects.petrinet.domain.I18nString; import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; -import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.FieldActionsRunner; +import com.netgrif.application.engine.objects.petrinet.domain.dataset.ActorFieldValue; +import com.netgrif.application.engine.objects.petrinet.domain.dataset.ActorListFieldValue; +import com.netgrif.application.engine.objects.petrinet.domain.dataset.Field; +import com.netgrif.application.engine.objects.petrinet.domain.dataset.TaskField; import com.netgrif.application.engine.objects.petrinet.domain.events.CaseEventType; import com.netgrif.application.engine.objects.petrinet.domain.events.EventPhase; -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; -import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService; -import com.netgrif.application.engine.security.service.EncryptionService; -import com.netgrif.application.engine.utils.FullPageRequest; +import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRolePermission; import com.netgrif.application.engine.objects.workflow.domain.*; import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.EventOutcome; import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.caseoutcomes.DeleteCaseEventOutcome; +import com.netgrif.application.engine.objects.workflow.service.InitValueExpressionEvaluator; +import com.netgrif.application.engine.petrinet.domain.dataset.logic.action.FieldActionsRunner; +import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService; +import com.netgrif.application.engine.security.service.EncryptionService; +import com.netgrif.application.engine.utils.FullPageRequest; import com.netgrif.application.engine.workflow.domain.outcomes.ReloadTaskOutcome; import com.netgrif.application.engine.workflow.domain.repositories.CaseRepository; import com.netgrif.application.engine.workflow.params.CreateCaseParams; import com.netgrif.application.engine.workflow.params.DeleteCaseParams; import com.netgrif.application.engine.workflow.service.interfaces.IEventService; -import com.netgrif.application.engine.objects.workflow.service.InitValueExpressionEvaluator; import com.netgrif.application.engine.workflow.service.interfaces.ITaskService; import com.netgrif.application.engine.workflow.service.interfaces.IWorkflowService; import com.querydsl.core.types.Predicate; @@ -210,6 +212,9 @@ public Page search(Predicate predicate, Pageable pageable) { @Override public Page search(Map request, Pageable pageable, LoggedUser user, Locale locale) { + if (user.isProcessAccessDeny()) { + return Page.empty(); + } Predicate searchPredicate = searchService.buildQuery(request, user, locale); Page page; if (searchPredicate != null) { @@ -224,6 +229,9 @@ public Page search(Map request, Pageable pageable, LoggedU @Override public long count(Map request, LoggedUser user, Locale locale) { + if (user.isProcessAccessDeny()) { + return 0; + } Predicate searchPredicate = searchService.buildQuery(request, user, locale); if (searchPredicate != null) { return repository.count(searchPredicate); @@ -255,10 +263,9 @@ public Case resolveActorRef(Case useCase, boolean canSaveUseCase) { /** * Resolves actor permissions for the useCase based on the actor list data field. * - * @param useCase useCase where to resolve actor permissions + * @param useCase useCase where to resolve actor permissions * @param actorFieldId field id of the actor list - * @param permission permission associated with the useCase and actor list - * + * @param permission permission associated with the useCase and actor list * @return true if the useCase was modified, false otherwise */ private boolean resolveActorRefPermissions(Case useCase, String actorFieldId, Map permission) { @@ -332,15 +339,15 @@ public CreateCaseEventOutcome createCase(CreateCaseParams createCaseParams) { * Creates pure {@link Case} object without any {@link Task} object initialized. * * @param createCaseParams parameters for object creation - * * @return created {@link Case} object - * */ + * + */ private Case createCaseObject(CreateCaseParams createCaseParams) { PetriNet petriNet = new com.netgrif.application.engine.adapter.spring.petrinet.domain.PetriNet((com.netgrif.application.engine.adapter.spring.petrinet.domain.PetriNet) createCaseParams.getProcess()); Case useCase = new com.netgrif.application.engine.adapter.spring.workflow.domain.Case(petriNet); useCase.populateDataSet(initValueExpressionEvaluator, createCaseParams.getParams()); useCase.setColor(createCaseParams.getColor()); - useCase.setAuthor(ActorTransformer.toActorRef(createCaseParams.getAuthor())); // TODO: impersonation + useCase.setAuthor(ActorTransformer.toActorRef(createCaseParams.getAuthor().getSelfOrImpersonated())); useCase.setCreationDate(LocalDateTime.now()); useCase.setTitle(createCaseParams.getMakeTitle().apply(useCase)); @@ -529,7 +536,6 @@ public void setPetriNet(Case useCase) { * Initializes task ref data fields with the task ids based on field definition in petriNet * * @param useCase useCase where to initialize task ref data fields - * * @return true if useCase was modified, false otherwise */ protected boolean resolveTaskRefs(Case useCase) { diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/ITaskAuthorizationService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/ITaskAuthorizationService.java index 99b0c8e56b9..b18ebb82925 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/ITaskAuthorizationService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/ITaskAuthorizationService.java @@ -1,25 +1,17 @@ package com.netgrif.application.engine.workflow.service.interfaces; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.petrinet.domain.roles.RolePermission; -import com.netgrif.application.engine.petrinet.domain.throwable.IllegalTaskStateException; import com.netgrif.application.engine.objects.workflow.domain.Task; +import com.netgrif.application.engine.petrinet.domain.throwable.IllegalTaskStateException; public interface ITaskAuthorizationService { - Boolean userHasAtLeastOneRolePermission(LoggedUser loggedUser, String taskId, RolePermission... permissions); - - Boolean userHasAtLeastOneRolePermission(AbstractUser user, Task task, RolePermission... permissions); - - Boolean userHasUserListPermission(LoggedUser loggedUser, String taskId, RolePermission... permissions); - - Boolean userHasUserListPermission(AbstractUser user, Task task, RolePermission... permissions); - boolean isAssignee(LoggedUser loggedUser, String taskId); + Boolean userHasAtLeastOneRolePermission(LoggedUser user, Task task, RolePermission... permissions); - boolean isAssignee(AbstractUser user, String taskId); + Boolean userHasUserListPermission(LoggedUser user, Task task, RolePermission... permissions); - boolean isAssignee(AbstractUser user, Task task); + boolean isAssignee(LoggedUser user, Task task); boolean canCallAssign(LoggedUser loggedUser, String taskId); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IWorkflowAuthorizationService.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IWorkflowAuthorizationService.java index f99f950a31e..e63e7a7de68 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IWorkflowAuthorizationService.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/service/interfaces/IWorkflowAuthorizationService.java @@ -1,6 +1,5 @@ package com.netgrif.application.engine.workflow.service.interfaces; -import com.netgrif.application.engine.objects.auth.domain.AbstractUser; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.petrinet.domain.PetriNet; import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRolePermission; @@ -12,7 +11,7 @@ public interface IWorkflowAuthorizationService { boolean canCallCreate(LoggedUser user, String netId); - Boolean userHasAtLeastOneRolePermission(AbstractUser user, PetriNet net, ProcessRolePermission... permissions); + Boolean userHasAtLeastOneRolePermission(LoggedUser user, PetriNet net, ProcessRolePermission... permissions); - Boolean userHasUserListPermission(AbstractUser user, Case useCase, ProcessRolePermission... permissions); + Boolean userHasUserListPermission(LoggedUser user, Case useCase, ProcessRolePermission... permissions); } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/AbstractTaskController.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/AbstractTaskController.java index 1474f6a8fbd..8527367d094 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/AbstractTaskController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/AbstractTaskController.java @@ -109,7 +109,7 @@ public LocalisedTaskResource getOne(String taskId, Locale locale) { public EntityModel assign(LoggedUser loggedUser, String taskId, Locale locale) { try { - return EventOutcomeWithMessageResource.successMessage("LocalisedTask " + taskId + " assigned to " + loggedUser.getName(), + return EventOutcomeWithMessageResource.successMessage("LocalisedTask " + taskId + " assigned to " + (loggedUser.isImpersonating() ? loggedUser.getImpersonatedUser().getUsername() : loggedUser.getUsername()), LocalisedEventOutcomeFactory.from(taskService.assignTask(TaskParams.with() .taskId(taskId) .user(loggedUser) @@ -170,7 +170,7 @@ public EntityModel cancel(LoggedUser loggedUser, String } public PagedModel getMy(Authentication auth, Pageable pageable, PagedResourcesAssembler assembler, Locale locale) { - Page page = taskService.findByUser(pageable, userService.transformToUser(((LoggedUserImpl) auth.getPrincipal()))); + Page page = taskService.findByUser(pageable, ((LoggedUserImpl) auth.getPrincipal())); Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(TaskController.class) .getMy(auth, pageable, assembler, locale)).withRel("my"); PagedModel resources = assembler.toModel(page, new TaskResourceAssembler(locale), selfLink); @@ -179,7 +179,7 @@ public PagedModel getMy(Authentication auth, Pageable pag } public PagedModel getMyFinished(Pageable pageable, Authentication auth, PagedResourcesAssembler assembler, Locale locale) { - Page page = taskService.findByUser(pageable, userService.transformToUser(((LoggedUserImpl) auth.getPrincipal()))); + Page page = taskService.findByUser(pageable, ((LoggedUserImpl) auth.getPrincipal())); Link selfLink = WebMvcLinkBuilder.linkTo(WebMvcLinkBuilder.methodOn(TaskController.class) .getMyFinished(pageable, auth, assembler, locale)).withRel("finished"); PagedModel resources = assembler.toModel(page, new TaskResourceAssembler(locale), selfLink); diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java index 932db377fe0..69ff8911db5 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/PublicTaskController.java @@ -1,7 +1,6 @@ package com.netgrif.application.engine.workflow.web; import com.fasterxml.jackson.databind.node.ObjectNode; -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.workflow.domain.MergeFilterOperation; @@ -81,7 +80,7 @@ public List getTasksOfCase(@PathVariable("id") String caseId, Loc description = "Caller doesn't fulfill the authorisation requirements" )}) public EntityModel assign(@PathVariable("id") String taskId, Locale locale) { - LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedUser()); + LoggedUser loggedUser = userService.getLoggedUserFromContext(); return super.assign(loggedUser, taskId, locale); } @@ -96,7 +95,7 @@ public EntityModel assign(@PathVariable("id") String ta description = "Caller doesn't fulfill the authorisation requirements" )}) public EntityModel finish(@PathVariable("id") String taskId, Locale locale) { - LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedUser()); + LoggedUser loggedUser = userService.getLoggedUserFromContext(); return super.finish(loggedUser, taskId, locale); } @@ -111,7 +110,7 @@ public EntityModel finish(@PathVariable("id") String ta description = "Caller doesn't fulfill the authorisation requirements" )}) public EntityModel cancel(@PathVariable("id") String taskId, Locale locale) { - LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedUser()); + LoggedUser loggedUser = userService.getLoggedUserFromContext(); return super.cancel(loggedUser, taskId, locale); } @@ -210,6 +209,6 @@ public EntityModel deleteNamedFile(@PathVariable("id") @Operation(summary = "Generic task search on Mongo database") @PostMapping(value = "/search", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaTypes.HAL_JSON_VALUE) public PagedModel search(Pageable pageable, @RequestBody SingleTaskSearchRequestAsList searchBody, @RequestParam(defaultValue = "OR") MergeFilterOperation operation, PagedResourcesAssembler assembler, Locale locale) { - return super.searchPublic(ActorTransformer.toLoggedUser(userService.getLoggedUser()), pageable, searchBody, operation, assembler, locale); + return super.searchPublic(userService.getLoggedUserFromContext(), pageable, searchBody, operation, assembler, locale); } } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java index f25d6a3a7ed..f1c83b0e708 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/PublicWorkflowController.java @@ -1,9 +1,8 @@ package com.netgrif.application.engine.workflow.web; +import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.eventoutcomes.LocalisedEventOutcomeFactory; -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; -import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessage; import com.netgrif.application.engine.workflow.domain.eventoutcomes.response.EventOutcomeWithMessageResource; @@ -48,7 +47,7 @@ public PublicWorkflowController(IWorkflowService workflowService, UserService us @PostMapping(value = "/case", consumes = "application/json;charset=UTF-8", produces = MediaTypes.HAL_JSON_VALUE) @Operation(summary = "Create new case") public EntityModel createCase(@RequestBody CreateCaseBody body, Locale locale) { - LoggedUser loggedUser = ActorTransformer.toLoggedUser(userService.getLoggedUser()); + LoggedUser loggedUser = userService.getLoggedUserFromContext(); try { CreateCaseEventOutcome outcome = this.workflowService.createCase(CreateCaseParams.with() .processId(body.netId) diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java index 7222b4ae969..5771499d215 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/WorkflowController.java @@ -1,14 +1,14 @@ package com.netgrif.application.engine.workflow.web; -import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService; import com.netgrif.application.engine.elastic.web.requestbodies.singleaslist.SingleCaseSearchRequestAsList; import com.netgrif.application.engine.eventoutcomes.LocalisedEventOutcomeFactory; +import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.elastic.domain.ElasticCase; import com.netgrif.application.engine.objects.workflow.domain.Case; -import com.netgrif.application.engine.workflow.domain.MergeFilterOperation; import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.caseoutcomes.CreateCaseEventOutcome; import com.netgrif.application.engine.objects.workflow.domain.eventoutcomes.caseoutcomes.DeleteCaseEventOutcome; +import com.netgrif.application.engine.workflow.domain.MergeFilterOperation; 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.params.CreateCaseParams; @@ -49,7 +49,6 @@ import org.springframework.web.bind.annotation.*; import java.io.FileNotFoundException; -import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.nio.charset.StandardCharsets; import java.util.Locale; @@ -152,7 +151,8 @@ public PagedModel searchMongo(@RequestBody Map sea @Operation(summary = "Get count of the cases", security = {@SecurityRequirement(name = "BasicAuth")}) @PostMapping(value = "/case/count", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) public CountResponse count(@RequestBody SingleCaseSearchRequestAsList searchBody, @RequestParam(defaultValue = "OR") MergeFilterOperation operation, Authentication auth, Locale locale) { - long count = elasticCaseService.count(searchBody.getList(), (LoggedUser) auth.getPrincipal(), locale, operation == MergeFilterOperation.AND); + LoggedUser loggedUser = (LoggedUser) auth.getPrincipal(); + long count = elasticCaseService.count(searchBody.getList(), loggedUser, locale, operation == MergeFilterOperation.AND); return CountResponse.caseCount(count); } diff --git a/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/Task.java b/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/Task.java index 8978ba0526e..6ebc8be01e7 100644 --- a/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/Task.java +++ b/application-engine/src/main/java/com/netgrif/application/engine/workflow/web/responsebodies/Task.java @@ -27,6 +27,8 @@ public class Task { private String transitionId; + private String processIdentifier; + private TaskLayout layout; private String title; @@ -39,6 +41,10 @@ public class Task { private ActorRef assignee; + private String impersonatorUserId; + + private String impersonatorUsername; + private Map> roles; private Map> users; @@ -79,12 +85,15 @@ public Task(com.netgrif.application.engine.objects.workflow.domain.Task task, Lo this._id = task.getObjectId(); this.caseId = task.getCaseId(); this.transitionId = task.getTransitionId(); + this.processIdentifier = task.getProcessIdentifier(); this.layout = task.getLayout(); this.title = task.getTitle().getTranslation(locale); this.caseColor = task.getCaseColor(); this.caseTitle = task.getCaseTitle(); this.priority = task.getPriority(); this.assignee = task.getAssignee(); + this.impersonatorUserId = task.getImpersonatorUserId(); + this.impersonatorUsername = task.getImpersonatorUsername(); this.roles = task.getRoles(); this.users = task.getActors(); this.startDate = task.getStartDate(); @@ -109,6 +118,7 @@ public Task(ElasticTask entity) { _id = new ProcessResourceId(entity.getId()); caseId = entity.getCaseId(); transitionId = entity.getTransitionId(); + processIdentifier = entity.getProcessIdentifier(); title = entity.getTitle().getDefaultValue(); caseTitle = entity.getCaseTitle(); priority = entity.getPriority(); diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/TestHelper.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/TestHelper.groovy index f6921558abe..9df0f1ad7a6 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/TestHelper.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/TestHelper.groovy @@ -1,15 +1,15 @@ package com.netgrif.application.engine -import com.netgrif.application.engine.auth.service.UserService import com.netgrif.application.engine.adapter.spring.elastic.domain.ElasticCase -import com.netgrif.application.engine.elastic.domain.ElasticCaseRepository import com.netgrif.application.engine.adapter.spring.elastic.domain.ElasticPetriNet import com.netgrif.application.engine.adapter.spring.elastic.domain.ElasticTask +import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService +import com.netgrif.application.engine.auth.service.UserService +import com.netgrif.application.engine.elastic.domain.ElasticCaseRepository import com.netgrif.application.engine.elastic.domain.ElasticTaskRepository import com.netgrif.application.engine.elastic.service.ElasticIndexService import com.netgrif.application.engine.petrinet.domain.repository.UriNodeRepository import com.netgrif.application.engine.petrinet.domain.roles.ProcessRoleRepository -import com.netgrif.application.engine.adapter.spring.petrinet.service.ProcessRoleService import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService import com.netgrif.application.engine.startup.runner.* import com.netgrif.application.engine.workflow.service.interfaces.IFieldActionsCacheService @@ -71,9 +71,6 @@ class TestHelper { @Autowired private MenuProcessRunner menuProcessRunner - @Autowired - private ImpersonationRunner impersonationRunner - @Autowired private ElasticsearchRunner elasticsearchRunner @@ -104,7 +101,6 @@ class TestHelper { groupRunner.run() filterRunner.run() menuProcessRunner.run() - impersonationRunner.run() superCreator.run() finisherRunner.run() } diff --git a/application-engine/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy b/application-engine/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy index 0f69ac4bf94..e69de29bb2d 100644 --- a/application-engine/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy +++ b/application-engine/src/test/groovy/com/netgrif/application/engine/impersonation/ImpersonationServiceTest.groovy @@ -1,354 +0,0 @@ -package com.netgrif.application.engine.impersonation - -import com.netgrif.application.engine.TestHelper -import com.netgrif.application.engine.auth.service.AuthorityService -import com.netgrif.application.engine.auth.service.UserService -import com.netgrif.application.engine.elastic.service.interfaces.IElasticCaseService -import com.netgrif.application.engine.elastic.web.requestbodies.CaseSearchRequest -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationAuthorizationService -import com.netgrif.application.engine.impersonation.service.interfaces.IImpersonationService -import com.netgrif.application.engine.objects.auth.domain.AbstractUser -import com.netgrif.application.engine.objects.auth.domain.ActorTransformer -import com.netgrif.application.engine.objects.auth.domain.Authority - -import com.netgrif.application.engine.objects.auth.domain.User -import com.netgrif.application.engine.objects.auth.domain.enums.UserState -import com.netgrif.application.engine.objects.petrinet.domain.I18nString -import com.netgrif.application.engine.objects.petrinet.domain.PetriNet -import com.netgrif.application.engine.objects.petrinet.domain.dataset.UserFieldValue -import com.netgrif.application.engine.objects.petrinet.domain.dataset.ActorListFieldValue -import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole -import com.netgrif.application.engine.objects.workflow.domain.Case -import com.netgrif.application.engine.objects.workflow.domain.Task -import com.netgrif.application.engine.petrinet.service.interfaces.IPetriNetService -import com.netgrif.application.engine.startup.ImportHelper -import com.netgrif.application.engine.startup.runner.ImpersonationRunner -import com.netgrif.application.engine.workflow.service.interfaces.* -import com.netgrif.application.engine.workflow.web.requestbodies.TaskSearchRequest -import com.netgrif.application.engine.workflow.web.requestbodies.taskSearch.TaskSearchCaseRequest -import groovy.json.JsonSlurper -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.Disabled -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.context.i18n.LocaleContextHolder -import org.springframework.data.domain.PageRequest -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.core.GrantedAuthority -import org.springframework.security.core.context.SecurityContextHolder -import org.springframework.security.web.authentication.WebAuthenticationDetails -import org.springframework.session.web.http.SessionRepositoryFilter -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 java.time.LocalDateTime - -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic -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.request.MockMvcRequestBuilders.post -import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status - -@Disabled("Impersonation not reworked yet") -@SpringBootTest -@ActiveProfiles(["test"]) -@ExtendWith(SpringExtension.class) -class ImpersonationServiceTest { - - public static final String X_AUTH_TOKEN = "x-auth-token" - - @Autowired - private TestHelper testHelper - - @Autowired - private ImportHelper helper - - @Autowired - private UserService userService - - @Autowired - private IElasticCaseService elasticCaseService - - @Autowired - private IWorkflowService workflowService - - @Autowired - private IDataService dataService - - @Autowired - private ITaskService taskService - - @Autowired - private IPetriNetService petriNetService - - @Autowired - private AuthorityService authorityService - - @Autowired - private IImpersonationService impersonationService - - @Autowired - private IImpersonationAuthorizationService impersonationAuthorizationService - - @Autowired - private ITaskAuthorizationService taskAuthorizationService - - @Autowired - private IWorkflowAuthorizationService workflowAuthorizationService - - @Autowired - private WebApplicationContext wac - - MockMvc mvc - - Authentication auth1 - Authentication auth2 - Authentication adminUserAuth - - AbstractUser user1 - AbstractUser user2 - AbstractUser adminUser - - PetriNet testNet - - @BeforeEach - void before() { - testHelper.truncateDbs() - - SessionRepositoryFilter filter = wac.getBean(SessionRepositoryFilter.class); - mvc = MockMvcBuilders.webAppContextSetup(wac).addFilters(filter).apply(springSecurity()).build() - - testNet = helper.createNet("impersonation_test.xml").get() - def authority = authorityService.getOrCreate(Authority.user) - def authorityAnon = authorityService.getOrCreate(Authority.anonymous) - def authorityAdmin = authorityService.getOrCreate(Authority.admin) - - user1 = helper.createUser(new User(firstName: "Test", lastName: "User", email: "test@netgrif.com", "username": "test@netgrif.com", password: "password", state: UserState.ACTIVE), - [authority] as Authority[], - [] as ProcessRole[]) - - auth1 = new UsernamePasswordAuthenticationToken(ActorTransformer.toLoggedUser(user1), (user1 as User).password, user1.authoritySet as List) - auth1.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) - - user2 = helper.createUser(new User(firstName: "Test", lastName: "User2", email: "test2@netgrif.com", "username": "test2@netgrif.com", password: "password", state: UserState.ACTIVE), - [authority, authorityAnon] as Authority[], - testNet.roles.values() as ProcessRole[]) - - auth2 = new UsernamePasswordAuthenticationToken(ActorTransformer.toLoggedUser(user2), (user2 as User).password, user2.authoritySet as List) - auth2.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) - - adminUser = helper.createUser(new User(firstName: "Admin", lastName: "User", email: "admin@netgrif.com", "username": "admin@netgrif.com", password: "password", state: UserState.ACTIVE), - [authority, authorityAdmin] as Authority[], - testNet.roles.values() as ProcessRole[]) - - adminUserAuth = new UsernamePasswordAuthenticationToken(ActorTransformer.toLoggedUser(adminUser), (adminUser as User).password, adminUser.authoritySet as List) - adminUserAuth.setDetails(new WebAuthenticationDetails(new MockHttpServletRequest())) - } - - @Test - void testImpersonationAdmin() { - // TODO: impersonation -// SecurityContextHolder.getContext().setAuthentication(adminUserAuth) -// assert impersonationAuthorizationService.canImpersonateUser(userService.loggedUserFromContext, user2.stringId) -// impersonationService.impersonateUser(user2.stringId) -// def impersonated = userService.loggedUser.getSelfOrImpersonated() -// assert userService.loggedUser.isImpersonating() -// assert impersonated.stringId == user2.stringId -// assert impersonated.authorities.collect { it.stringId }.sort() == user2.authorities.collect { it.stringId }.sort() -// assert impersonated.processRoles.collect { it.stringId }.sort() == user2.processRoles.collect { it.stringId }.sort() - } - - @Test - void testImpersonation() { - // TODO: impersonation -// def config = setup() -// assert impersonationAuthorizationService.canImpersonate(userService.loggedUserFromContext, config.stringId) -// impersonationService.impersonateByConfig(config.stringId) -// assert userService.loggedUser.isImpersonating() -// assert userService.loggedUser.getSelfOrImpersonated().stringId == user2.stringId -// -// impersonationService.endImpersonation() -// assert !userService.loggedUser.isImpersonating() - } - - @Test - void testImpersonationRolesAndAuths() { - // TODO: impersonation -// def role = user2.processRoles.find { it.importId == "test_role" } -// def auth = user2.authorities.find { it.name == Authority.user } -// def config = setup([role.stringId], [auth.stringId, authorityService.getOrCreate(Authority.admin).stringId]) -// -// impersonationService.impersonateByConfig(config.stringId) -// def impersonatedRoles = userService.loggedUser.getImpersonated().getProcessRoles() -// def impersonatedAuths = userService.loggedUser.getImpersonated().getAuthorities() -// assert impersonatedRoles.size() == 2 && impersonatedRoles.any { it.stringId == role.stringId } -// // default role counts -// assert impersonatedAuths.size() == 1 && impersonatedAuths[0].stringId == auth.stringId -// -// def transformedUser = ActorTransformer.toLoggedUser(userService.loggedUser) -// def transformedUserImpersonated = transformedUser.getSelfOrImpersonated() -// assert transformedUser.isImpersonating() -// assert transformedUserImpersonated.getProcessRoles().size() == 2 && transformedUserImpersonated.getProcessRoles().any { it.stringId == role.stringId } -// // default role counts -// assert transformedUserImpersonated.getAuthoritySet().size() == 1 && (transformedUserImpersonated.getAuthoritySet()[0] as Authority).stringId == auth.stringId - } - - @Test - void testTaskSearchAssignFinish() { - def config = setup() - impersonationService.impersonateByConfig(config.stringId) - - assert workflowAuthorizationService.canCallCreate(userService.loggedUserFromContext, testNet.stringId) - def testCase = createTestCase() - assert workflowAuthorizationService.canCallDelete(userService.loggedUserFromContext, testCase.stringId) - def testTask1 = loadTask(testCase, "t1") - - sleep(8000) // elastic - - def caseReq = new CaseSearchRequest() - caseReq.process = [new CaseSearchRequest.PetriNet(testCase.processIdentifier)] - def cases = elasticCaseService.search([caseReq], ActorTransformer.toLoggedUser(userService.loggedUser) , PageRequest.of(0, 1), LocaleContextHolder.locale, false) - assert !cases.content.isEmpty() - - def searchReq = new TaskSearchRequest() - searchReq.transitionId = ["t1"] - searchReq.useCase = [new TaskSearchCaseRequest(testCase.stringId, null)] - def tasks = taskService.search([searchReq], PageRequest.of(0, 1), ActorTransformer.toLoggedUser(userService.loggedUser) , LocaleContextHolder.locale, false) - assert tasks.content[0].stringId == testTask1.stringId - - assert taskAuthorizationService.canCallAssign(userService.loggedUserFromContext, testTask1.stringId) - taskService.assignTask(ActorTransformer.toLoggedUser(userService.loggedUser) , testTask1.stringId) - testTask1 = reloadTask(testTask1) - assert testTask1.userId == user2.stringId - - assert taskAuthorizationService.canCallSaveData(userService.loggedUserFromContext, testTask1.stringId) - assert taskAuthorizationService.canCallSaveFile(userService.loggedUserFromContext, testTask1.stringId) - - assert taskAuthorizationService.canCallFinish(userService.loggedUserFromContext, testTask1.stringId) - taskService.finishTask(ActorTransformer.toLoggedUser(userService.loggedUser) , testTask1.stringId) - } - - @Test - void testAuthorization() { - def config = setup() - sleep(4000) // elastic - - def logged = ActorTransformer.toLoggedUser(userService.loggedUser) - assert impersonationAuthorizationService.canImpersonate(logged, config.stringId) - assert impersonationAuthorizationService.canImpersonateUser(logged, user2.stringId) - - config.dataSet["valid_to"].value = LocalDateTime.now().minusMinutes(1) - workflowService.save(config) - sleep(4000) - - assert !impersonationAuthorizationService.canImpersonate(logged, config.stringId) - assert !impersonationAuthorizationService.canImpersonateUser(logged, user2.stringId) - } - - - @Test - @Disabled("Disabled until user refactor is merged in v7.0.0") - void testAuthMe() { - def config = setup() - def result = mvc.perform(get("/api/auth/login") - .with(httpBasic(user1.email, "password")) - .contentType(MediaType.APPLICATION_JSON) - .characterEncoding("utf-8")) - .andExpect(status().isOk()) - .andReturn() - def token = result.response.getHeader(X_AUTH_TOKEN) - - result = mvc.perform(post("/api/impersonate/config/" + config.stringId) - .header(X_AUTH_TOKEN, token) - .contentType(MediaType.APPLICATION_JSON) - .characterEncoding("utf-8")) - .andExpect(status().isOk()) - .andReturn() - - result = mvc.perform(get("/api/users/me") - .header(X_AUTH_TOKEN, token) - .contentType(MediaType.APPLICATION_JSON) - .characterEncoding("utf-8")) - .andExpect(status().isOk()) - .andReturn() - - String string = result.getResponse().getContentAsString() - def json = new JsonSlurper().parse(string.getBytes()) - assert json["impersonated"] != null - // TODO this assert does not pass -> need fixing after user / impersonation refactor - - result = mvc.perform(post("/api/impersonate/clear") - .header(X_AUTH_TOKEN, token) - .contentType(MediaType.APPLICATION_JSON) - .characterEncoding("utf-8")) - .andExpect(status().isOk()) - .andReturn() - - result = mvc.perform(get("/api/users/me") - .header(X_AUTH_TOKEN, token) - .contentType(MediaType.APPLICATION_JSON) - .characterEncoding("utf-8")) - .andExpect(status().isOk()) - .andReturn() - - string = result.getResponse().getContentAsString() - json = new JsonSlurper().parse(string.getBytes()) - assert json["impersonated"] == null - } - - def setup(List roles = null, List auths = null) { - def config = createConfigCase(user2, user1.stringId, roles, auths) - SecurityContextHolder.getContext().setAuthentication(auth1) - return config - } - - def createConfigCase(AbstractUser user, String impersonator, List roles = null, List auths = null) { - def caze = helper.createCase("config", petriNetService.getDefaultVersionByIdentifier(ImpersonationRunner.IMPERSONATION_CONFIG_PETRI_NET_IDENTIFIER)) - def owner = new UserFieldValue(user) - caze.dataSet["impersonated"].value = owner - caze.dataSet["impersonated_email"].value = owner.username - caze.dataSet["config_owner"].value = new ActorListFieldValue([owner]) - caze.dataSet["impersonators"].value = [impersonator] - caze.dataSet["impersonated_roles"].value = roles ?: user.processRoles.stringId as List - caze.dataSet["impersonated_authorities"].value = auths ?: user.authoritySet.stringId as List - caze.dataSet["valid_from"].value = LocalDateTime.now().minusDays(1) - - /* set options so elastic indexing works */ - caze.dataSet["impersonators"].options = [(impersonator): new I18nString(impersonator)] - caze.dataSet["impersonated_roles"].options = (caze.dataSet["impersonated_roles"].value as List).collectEntries { [(it): new I18nString(it as String)] } as Map - caze.dataSet["impersonated_authorities"].options = (caze.dataSet["impersonated_authorities"].value as List).collectEntries { [(it): new I18nString(it as String)] } as Map - caze = workflowService.save(caze) - def initTask = caze.tasks.find { it.transition == "t2" }.task - taskService.assignTask(ActorTransformer.toLoggedUser(userService.system), initTask) - taskService.finishTask(ActorTransformer.toLoggedUser(userService.system), initTask) - return workflowService.findOne(caze.stringId) - } - - def createTestCase() { - return helper.createCase("test", testNet) - } - - def setData(Case caze, String transition, Map dataSet) { - dataService.setData(caze.tasks.find { it.transition == transition }.task, helper.populateDataset(dataSet.collectEntries { - [(it.key): (["value": it.value, "type": "text"])] - })) - return workflowService.findOne(caze.stringId) - } - - def loadTask(Case caze, String trans) { - return taskService.findById(caze.tasks.find { it.transition == trans }.task) - } - - def reloadTask(Task task) { - return taskService.findById(task.stringId) - } - -} diff --git a/application-engine/src/test/java/com/netgrif/application/engine/workflow/WorkflowMvcPerformanceTest.java b/application-engine/src/test/java/com/netgrif/application/engine/workflow/WorkflowMvcPerformanceTest.java index b952430ff48..ef3fa5fe46b 100644 --- a/application-engine/src/test/java/com/netgrif/application/engine/workflow/WorkflowMvcPerformanceTest.java +++ b/application-engine/src/test/java/com/netgrif/application/engine/workflow/WorkflowMvcPerformanceTest.java @@ -181,7 +181,7 @@ public void testCancelPerformance() throws Exception { String taskId = useCase.getTasks().stream().findFirst().get().getTask(); taskService.assignTask(TaskParams.with() .taskId(taskId) - .user(this.user1) + .user(ActorTransformer.toLoggedUser(this.user1)) .build()); long start = System.currentTimeMillis(); mvc.perform(get(CANCEL_TASK_URL + taskId) @@ -233,7 +233,7 @@ public void testFinishPerformance() throws Exception { String taskId = useCase.getTasks().stream().findFirst().get().getTask(); taskService.assignTask(TaskParams.with() .taskId(taskId) - .user(this.user1) + .user(ActorTransformer.toLoggedUser(this.user1)) .build()); long start = System.currentTimeMillis(); mvc.perform(get(FINISH_TASK_URL + taskId) diff --git a/application-engine/src/test/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationServiceTest.java b/application-engine/src/test/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationServiceTest.java index e2b9f2757fe..43ac195dc5b 100644 --- a/application-engine/src/test/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationServiceTest.java +++ b/application-engine/src/test/java/com/netgrif/application/engine/workflow/service/AbstractAuthorizationServiceTest.java @@ -1,6 +1,7 @@ package com.netgrif.application.engine.workflow.service; import com.netgrif.application.engine.objects.auth.domain.AbstractUser; +import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.auth.domain.User; import com.netgrif.application.engine.objects.petrinet.domain.roles.ProcessRole; import org.junit.jupiter.api.Test; @@ -19,7 +20,8 @@ @ExtendWith(SpringExtension.class) class AbstractAuthorizationServiceTest { - static class MockAuthorizationService extends AbstractAuthorizationService { } + static class MockAuthorizationService extends AbstractAuthorizationService { + } @Test public void hasPermission() { @@ -57,7 +59,7 @@ public void getAggregatePermissions() { netPermissions.put(roles.get(2).getStringId(), getInitEntryValue()); // situation 1 - Map aggregatePermission = mockInstance.getAggregatePermissions(user, netPermissions); + Map aggregatePermission = mockInstance.getAggregatePermissions(ActorTransformer.toLoggedUser(user), netPermissions); assert aggregatePermission.get("create"); assert aggregatePermission.get("view"); @@ -66,7 +68,7 @@ public void getAggregatePermissions() { // situation 2 netPermissions.get(roles.get(0).getStringId()).put("create", false); netPermissions.get(roles.get(1).getStringId()).put("delete", false); - aggregatePermission = mockInstance.getAggregatePermissions(user, netPermissions); + aggregatePermission = mockInstance.getAggregatePermissions(ActorTransformer.toLoggedUser(user), netPermissions); assert !aggregatePermission.get("create"); assert aggregatePermission.get("view"); diff --git a/application-engine/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java b/application-engine/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java index 046bf7fd11f..a2b090d9670 100644 --- a/application-engine/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java +++ b/application-engine/src/test/java/com/netgrif/application/engine/workflow/service/TaskServiceTest.java @@ -4,6 +4,7 @@ import com.netgrif.application.engine.auth.service.AuthorityService; import com.netgrif.application.engine.auth.service.UserService; import com.netgrif.application.engine.importer.service.throwable.MissingIconKeyException; +import com.netgrif.application.engine.objects.auth.domain.ActorTransformer; import com.netgrif.application.engine.objects.auth.domain.LoggedUser; import com.netgrif.application.engine.objects.auth.domain.User; import com.netgrif.application.engine.objects.auth.domain.enums.UserState; @@ -135,7 +136,7 @@ public void resetArcTest() throws TransitionNotExecutableException, MissingPetri service.assignTask(TaskParams.with() .task(task) - .user(user) + .user(ActorTransformer.toLoggedUser(user)) .build()); Case useCase = caseRepository.findById(outcome.getCase().getStringId()).get(); @@ -145,7 +146,7 @@ public void resetArcTest() throws TransitionNotExecutableException, MissingPetri service.cancelTask(TaskParams.with() .task(task) - .user(user) + .user(ActorTransformer.toLoggedUser(user)) .build()); useCase = caseRepository.findById(useCase.getStringId()).get(); diff --git a/application-engine/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java b/application-engine/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java index a1f61c2029f..7d12191ea24 100644 --- a/application-engine/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java +++ b/application-engine/src/test/java/com/netgrif/application/engine/workflow/web/VariableArcsTest.java @@ -173,14 +173,14 @@ private void assertInhibArcsFinishTask(List tasks) throws Transit Task task = taskService.findOne(taskRef.getStringId()); taskService.assignTask(TaskParams.with() .task(task) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); finishCase = workflowService.findOne(task.getCaseId()); assert !finishCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_start") && !finishCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_res"); taskService.finishTask(TaskParams.with() .task(task) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); finishCase = workflowService.findOne(task.getCaseId()); assert !finishCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_start") && @@ -195,7 +195,7 @@ private void assertReadArcsFinishTask(List tasks) throws Transiti markingBeforeAssign = finishCase.getActivePlaces().get(task.getTitle().getDefaultValue() + "_start"); taskService.assignTask(TaskParams.with() .task(task) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); finishCase = workflowService.findOne(task.getCaseId()); @@ -203,7 +203,7 @@ private void assertReadArcsFinishTask(List tasks) throws Transiti taskService.finishTask(TaskParams.with() .task(task) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); finishCase = workflowService.findOne(task.getCaseId()); @@ -218,7 +218,7 @@ private void assertFinishTasks(String arcType, List tasks) throws Task task = taskService.findOne(taskRef.getStringId()); taskService.assignTask(TaskParams.with() .task(task) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); finishCase = workflowService.findOne(task.getCaseId()); @@ -226,7 +226,7 @@ private void assertFinishTasks(String arcType, List tasks) throws taskService.finishTask(TaskParams.with() .task(task) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); finishCase = workflowService.findOne(task.getCaseId()); @@ -241,7 +241,7 @@ private void assertOutArcsFinishTasks(List tasks) throws Transiti Task task = taskService.findOne(taskRef.getStringId()); taskService.assignTask(TaskParams.with() .task(task) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); finishCase = workflowService.findOne(task.getCaseId()); @@ -249,7 +249,7 @@ private void assertOutArcsFinishTasks(List tasks) throws Transiti taskService.finishTask(TaskParams.with() .task(task) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); finishCase = workflowService.findOne(task.getCaseId()); @@ -288,7 +288,7 @@ private void assertCancelTasks(String arcType, List tasks) throws } taskService.assignTask(TaskParams.with() .task(task) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); cancelCase = workflowService.findOne(task.getCaseId()); assert !cancelCase.getActivePlaces().containsKey(task.getTitle().getDefaultValue() + "_res"); @@ -307,17 +307,17 @@ private void assertCancelTasks(String arcType, List tasks) throws Task addTokensTask = taskService.searchOne(qTask.transitionId.eq("add_tokens").and(qTask.caseId.eq(cancelCase.getStringId()))); taskService.assignTask(TaskParams.with() .task(addTokensTask) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); taskService.finishTask(TaskParams.with() .task(addTokensTask) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); } int tokensAfterCancel = 0; taskService.cancelTask(TaskParams.with() .task(task) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); cancelCase = workflowService.findOne(task.getCaseId()); if (!arcType.equals("inhib")) { @@ -340,11 +340,11 @@ private void assertCancelTasks(String arcType, List tasks) throws Task removeTokensTask = taskService.searchOne(qTask.transitionId.eq("remove_tokens").and(qTask.caseId.eq(cancelCase.getStringId()))); taskService.assignTask(TaskParams.with() .task(removeTokensTask) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); taskService.finishTask(TaskParams.with() .task(removeTokensTask) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); tasksAfterPlaceRefReset = taskService.findAllByCase(cancelCase.getStringId(), LocaleContextHolder.getLocale()); } @@ -357,7 +357,7 @@ private void assertOutArcsCancelTasks(List tasks) throws Transiti Task task = taskService.findOne(taskRef.getStringId()); taskService.assignTask(TaskParams.with() .task(task) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); cancelCase = workflowService.findOne(task.getCaseId()); @@ -365,7 +365,7 @@ private void assertOutArcsCancelTasks(List tasks) throws Transiti taskService.cancelTask(TaskParams.with() .task(task) - .user(testUser) + .user(ActorTransformer.toLoggedUser(testUser)) .build()); cancelCase = workflowService.findOne(task.getCaseId()); diff --git a/docs/javadoc/com/netgrif/application/engine/configuration/security/ImpersonationRequestFilter.html b/docs/javadoc/com/netgrif/application/engine/configuration/security/ImpersonationRequestFilter.html index 1b8ba8e6e0e..53d404226f6 100644 --- a/docs/javadoc/com/netgrif/application/engine/configuration/security/ImpersonationRequestFilter.html +++ b/docs/javadoc/com/netgrif/application/engine/configuration/security/ImpersonationRequestFilter.html @@ -254,7 +254,7 @@

Method Summary

protected boolean -isValid​(Impersonator impersonator) +isValid​(Impersonator impersonator)   @@ -380,7 +380,7 @@

handleImpersonated

javax.servlet.http.HttpServletRequest servletRequest) - +
    diff --git a/docs/javadoc/com/netgrif/application/engine/impersonation/domain/Impersonator.html b/docs/javadoc/com/netgrif/application/engine/impersonation/domain/Impersonator.html index a068e7080b3..425a2c33c5d 100644 --- a/docs/javadoc/com/netgrif/application/engine/impersonation/domain/Impersonator.html +++ b/docs/javadoc/com/netgrif/application/engine/impersonation/domain/Impersonator.html @@ -119,7 +119,7 @@

    Class Impersonator

  • java.lang.Object
    • -
    • com.netgrif.application.engine.impersonation.domain.Impersonator
    • +
    • com.netgrif.application.engine.auth.domain.Impersonator
@@ -137,7 +137,7 @@

Class Impersonator

implements java.io.Serializable
See Also:
-
Serialized Form
+
Serialized Form
diff --git a/docs/javadoc/com/netgrif/application/engine/impersonation/domain/class-use/Impersonator.html b/docs/javadoc/com/netgrif/application/engine/impersonation/domain/class-use/Impersonator.html index 22b624fa32f..d1f001a4094 100644 --- a/docs/javadoc/com/netgrif/application/engine/impersonation/domain/class-use/Impersonator.html +++ b/docs/javadoc/com/netgrif/application/engine/impersonation/domain/class-use/Impersonator.html @@ -3,7 +3,7 @@ -Uses of Class com.netgrif.application.engine.impersonation.domain.Impersonator (NETGRIF Application Engine 6.4.0 API) +Uses of Class com.netgrif.application.engine.auth.domain.Impersonator (NETGRIF Application Engine 6.4.0 API) @@ -22,7 +22,7 @@