http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java ---------------------------------------------------------------------- diff --git a/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java b/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java index 1acc1da..686677e 100644 --- a/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java +++ b/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/UserRequestLogic.java @@ -25,13 +25,12 @@ import org.apache.commons.lang3.tuple.Pair; import org.apache.syncope.common.lib.SyncopeClientException; import org.apache.syncope.common.lib.patch.UserPatch; import org.apache.syncope.common.lib.to.PropagationTaskTO; -import org.apache.syncope.common.lib.to.UserRequestTO; +import org.apache.syncope.common.lib.to.UserRequest; import org.apache.syncope.common.lib.to.UserTO; import org.apache.syncope.common.lib.to.UserRequestForm; import org.apache.syncope.common.lib.types.BpmnProcessFormat; import org.apache.syncope.common.lib.types.ClientExceptionType; import org.apache.syncope.common.lib.types.FlowableEntitlement; -import org.apache.syncope.common.lib.types.StandardEntitlement; import org.apache.syncope.core.flowable.api.BpmnProcessManager; import org.apache.syncope.core.persistence.api.dao.UserDAO; import org.apache.syncope.core.persistence.api.dao.search.OrderByClause; @@ -41,6 +40,7 @@ import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecu import org.apache.syncope.core.provisioning.api.WorkflowResult; import org.apache.syncope.core.provisioning.api.data.UserDataBinder; import org.apache.syncope.core.flowable.api.UserRequestHandler; +import org.apache.syncope.core.persistence.api.dao.NotFoundException; import org.apache.syncope.core.spring.security.AuthContextUtils; import org.flowable.engine.runtime.ProcessInstance; import org.springframework.beans.factory.annotation.Autowired; @@ -52,24 +52,49 @@ import org.springframework.transaction.annotation.Transactional; public class UserRequestLogic extends AbstractTransactionalLogic<UserRequestForm> { @Autowired - private BpmnProcessManager bpmnProcessManager; + protected BpmnProcessManager bpmnProcessManager; @Autowired - private UserRequestHandler userRequestHandler; + protected UserRequestHandler userRequestHandler; @Autowired - private PropagationManager propagationManager; + protected PropagationManager propagationManager; @Autowired - private PropagationTaskExecutor taskExecutor; + protected PropagationTaskExecutor taskExecutor; @Autowired - private UserDataBinder binder; + protected UserDataBinder binder; @Autowired - private UserDAO userDAO; + protected UserDAO userDAO; - protected UserRequestTO doStart(final String bpmnProcess, final User user) { + @PreAuthorize("isAuthenticated()") + @Transactional(readOnly = true) + public Pair<Integer, List<UserRequest>> list(final String userKey, + final int page, + final int size, + final List<OrderByClause> orderByClauses) { + + if (userKey == null) { + securityChecks(null, + FlowableEntitlement.USER_REQUEST_LIST, + "Listing user requests not allowed"); + } else { + User user = userDAO.find(userKey); + if (user == null) { + throw new NotFoundException("User " + userKey); + } + + securityChecks(user.getUsername(), + FlowableEntitlement.USER_REQUEST_LIST, + "Listing requests for user" + user.getUsername() + " not allowed"); + } + + return userRequestHandler.getUserRequests(userKey, page, size, orderByClauses); + } + + protected UserRequest doStart(final String bpmnProcess, final User user) { // check if BPMN process exists bpmnProcessManager.exportProcess(bpmnProcess, BpmnProcessFormat.XML, new NullOutputStream()); @@ -77,56 +102,84 @@ public class UserRequestLogic extends AbstractTransactionalLogic<UserRequestForm } @PreAuthorize("isAuthenticated()") - public UserRequestTO start(final String bpmnProcess) { + public UserRequest start(final String bpmnProcess) { return doStart(bpmnProcess, userDAO.findByUsername(AuthContextUtils.getUsername())); } @PreAuthorize("hasRole('" + FlowableEntitlement.USER_REQUEST_START + "')") - public UserRequestTO start(final String bpmnProcess, final String userKey) { + public UserRequest start(final String bpmnProcess, final String userKey) { return doStart(bpmnProcess, userDAO.authFind(userKey)); } - @PreAuthorize("isAuthenticated()") - public void cancel(final String executionId, final String reason) { - Pair<ProcessInstance, String> parsed = userRequestHandler.parse(executionId); - - if (!AuthContextUtils.getUsername().equals(userDAO.find(parsed.getRight()).getUsername()) + protected void securityChecks(final String username, final String entitlement, final String errorMessage) { + if (!AuthContextUtils.getUsername().equals(username) && !AuthContextUtils.getAuthorities().stream(). - anyMatch(auth -> FlowableEntitlement.USER_REQUEST_CANCEL.equals(auth.getAuthority()))) { + anyMatch(auth -> entitlement.equals(auth.getAuthority()))) { SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.DelegatedAdministration); - sce.getElements().add("Canceling " + executionId + " not allowed"); + sce.getElements().add(errorMessage); throw sce; } + } + + @PreAuthorize("isAuthenticated()") + public void cancel(final String executionId, final String reason) { + Pair<ProcessInstance, String> parsed = userRequestHandler.parse(executionId); + + securityChecks(userDAO.find(parsed.getRight()).getUsername(), + FlowableEntitlement.USER_REQUEST_CANCEL, + "Canceling " + executionId + " not allowed"); userRequestHandler.cancel(parsed.getLeft(), reason); } - @PreAuthorize("hasRole('" + FlowableEntitlement.WORKFLOW_FORM_CLAIM + "')") + @PreAuthorize("isAuthenticated()") public UserRequestForm claimForm(final String taskId) { - return userRequestHandler.claimForm(taskId); - } - - @PreAuthorize("hasRole('" + FlowableEntitlement.WORKFLOW_FORM_READ + "') " - + "and hasRole('" + StandardEntitlement.USER_READ + "')") - @Transactional(readOnly = true) - public List<UserRequestForm> getForms(final String key) { - User user = userDAO.authFind(key); - return userRequestHandler.getForms(user.getKey()); + UserRequestForm form = userRequestHandler.claimForm(taskId); + securityChecks(form.getUsername(), + FlowableEntitlement.USER_REQUEST_FORM_CLAIM, + "Claiming form " + taskId + " not allowed"); + return form; } - @PreAuthorize("hasRole('" + FlowableEntitlement.WORKFLOW_FORM_LIST + "')") + @PreAuthorize("isAuthenticated()") @Transactional(readOnly = true) public Pair<Integer, List<UserRequestForm>> getForms( + final String userKey, final int page, final int size, final List<OrderByClause> orderByClauses) { - return userRequestHandler.getForms(page, size, orderByClauses); + if (userKey == null) { + securityChecks(null, + FlowableEntitlement.USER_REQUEST_FORM_LIST, + "Listing forms not allowed"); + } else { + User user = userDAO.find(userKey); + if (user == null) { + throw new NotFoundException("User " + userKey); + } + + securityChecks(user.getUsername(), + FlowableEntitlement.USER_REQUEST_FORM_LIST, + "Listing forms for user" + user.getUsername() + " not allowed"); + } + + return userRequestHandler.getForms(userKey, page, size, orderByClauses); } - @PreAuthorize("hasRole('" + FlowableEntitlement.WORKFLOW_FORM_SUBMIT + "')") + @PreAuthorize("isAuthenticated()") public UserTO submitForm(final UserRequestForm form) { + if (form.getUsername() == null) { + securityChecks(null, + FlowableEntitlement.USER_REQUEST_FORM_SUBMIT, + "Submitting forms not allowed"); + } else { + securityChecks(form.getUsername(), + FlowableEntitlement.USER_REQUEST_FORM_SUBMIT, + "Submitting forms for user" + form.getUsername() + " not allowed"); + } + WorkflowResult<UserPatch> wfResult = userRequestHandler.submitForm(form); // propByRes can be made empty by the workflow definition if no propagation should occur
http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/UserRequestFormQuery.java ---------------------------------------------------------------------- diff --git a/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/UserRequestFormQuery.java b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/UserRequestFormQuery.java index 4097afd..c4ac3a0 100644 --- a/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/UserRequestFormQuery.java +++ b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/UserRequestFormQuery.java @@ -18,6 +18,8 @@ */ package org.apache.syncope.common.rest.api.beans; +import javax.ws.rs.QueryParam; + public class UserRequestFormQuery extends AbstractQuery { private static final long serialVersionUID = -4762457303770028554L; @@ -28,5 +30,21 @@ public class UserRequestFormQuery extends AbstractQuery { protected UserRequestFormQuery newInstance() { return new UserRequestFormQuery(); } + + public Builder user(final String user) { + getInstance().setUser(user); + return this; + } + } + + private String user; + + public String getUser() { + return user; + } + + @QueryParam("user") + public void setUser(final String user) { + this.user = user; } } http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/UserRequestQuery.java ---------------------------------------------------------------------- diff --git a/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/UserRequestQuery.java b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/UserRequestQuery.java new file mode 100644 index 0000000..3f53629 --- /dev/null +++ b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/beans/UserRequestQuery.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.common.rest.api.beans; + +import javax.ws.rs.QueryParam; + +public class UserRequestQuery extends AbstractQuery { + + private static final long serialVersionUID = 427312034580076640L; + + public static class Builder extends AbstractQuery.Builder<UserRequestQuery, Builder> { + + @Override + protected UserRequestQuery newInstance() { + return new UserRequestQuery(); + } + + public Builder user(final String user) { + getInstance().setUser(user); + return this; + } + } + + private String user; + + public String getUser() { + return user; + } + + @QueryParam("user") + public void setUser(final String user) { + this.user = user; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/BpmnProcessService.java ---------------------------------------------------------------------- diff --git a/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/BpmnProcessService.java b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/BpmnProcessService.java index 06cb056..bb34fdd 100644 --- a/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/BpmnProcessService.java +++ b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/BpmnProcessService.java @@ -19,6 +19,9 @@ package org.apache.syncope.common.rest.api.service; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; @@ -35,7 +38,7 @@ import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; -import org.apache.syncope.common.lib.to.BpmnProcessTO; +import org.apache.syncope.common.lib.to.BpmnProcess; import org.apache.syncope.common.rest.api.RESTHeaders; /** @@ -51,11 +54,16 @@ public interface BpmnProcessService extends JAXRSService { /** * Lists the available BPMN processes. * - * @return available BPMN processs, for the given any object type + * @return available BPMN processs */ + @ApiResponses( + @ApiResponse(responseCode = "200", description = "available BPMN processes", content = + @Content(array = + @ArraySchema(schema = + @Schema(implementation = BpmnProcess.class))))) @GET @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) - List<BpmnProcessTO> list(); + List<BpmnProcess> list(); /** * Exports the BPMN process for matching key. @@ -63,6 +71,8 @@ public interface BpmnProcessService extends JAXRSService { * @param key BPMN process key * @return BPMN process for matching key */ + @ApiResponses( + @ApiResponse(responseCode = "200", description = "BPMN process for matching key")) @GET @Path("{key}") @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) @@ -72,8 +82,10 @@ public interface BpmnProcessService extends JAXRSService { * Exports the BPMN diagram representation (if available), for matching key. * * @param key BPMN process key - * @return workflow diagram representation + * @return BPMN diagram representation */ + @ApiResponses( + @ApiResponse(responseCode = "200", description = "BPMN diagram representation")) @GET @Path("{key}/diagram.png") @Produces({ RESTHeaders.MEDIATYPE_IMAGE_PNG }) http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java ---------------------------------------------------------------------- diff --git a/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java index 701772d..5ad7b12 100644 --- a/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java +++ b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserRequestService.java @@ -18,10 +18,13 @@ */ package org.apache.syncope.common.rest.api.service; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityRequirements; import io.swagger.v3.oas.annotations.tags.Tag; -import java.util.List; import javax.validation.constraints.NotNull; import javax.ws.rs.BeanParam; import javax.ws.rs.Consumes; @@ -34,11 +37,12 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import org.apache.syncope.common.lib.to.PagedResult; -import org.apache.syncope.common.lib.to.UserRequestTO; +import org.apache.syncope.common.lib.to.UserRequest; import org.apache.syncope.common.lib.to.UserTO; import org.apache.syncope.common.lib.to.UserRequestForm; import org.apache.syncope.common.rest.api.RESTHeaders; import org.apache.syncope.common.rest.api.beans.UserRequestFormQuery; +import org.apache.syncope.common.rest.api.beans.UserRequestQuery; /** * REST operations related to user workflow. @@ -51,19 +55,37 @@ import org.apache.syncope.common.rest.api.beans.UserRequestFormQuery; public interface UserRequestService extends JAXRSService { /** - * Starts a new user request, for the given BOMN Process and - * user (if provided) or requesting user (if not provided). + * Returns a list of running user requests matching the given query. + * + * @param query query conditions + * @return list of all running user requests + */ + @ApiResponses( + @ApiResponse(responseCode = "200", description = "list of all running user requests", content = + @Content(schema = + @Schema(implementation = PagedResult.class)))) + @GET + @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) + PagedResult<UserRequest> list(@BeanParam UserRequestQuery query); + + /** + * Starts a new request for the given BPMN Process and user (if provided) or requesting user (if not provided). * * @param bpmnProcess BPMN process - * @param userKey user key + * @param user if value looks like a UUID then it is interpreted as key otherwise as a username * @return data about the started request service, including execution id */ + @ApiResponses( + @ApiResponse(responseCode = "200", + description = "data about the started request service, including execution id", content = + @Content(schema = + @Schema(implementation = UserRequest.class)))) @POST @Path("start/{bpmnProcess}") @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) - UserRequestTO start( + UserRequest start( @NotNull @PathParam("bpmnProcess") String bpmnProcess, - @QueryParam("userKey") String userKey); + @QueryParam("user") String user); /** * Cancel a running user request. @@ -71,6 +93,8 @@ public interface UserRequestService extends JAXRSService { * @param executionId execution id * @param reason reason to cancel the user request */ + @ApiResponses( + @ApiResponse(responseCode = "204", description = "Operation was successful")) @DELETE @Path("{executionId}") @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) @@ -79,44 +103,45 @@ public interface UserRequestService extends JAXRSService { @QueryParam("reason") String reason); /** - * Returns a list of all available workflow forms. + * Returns a list of user request forms matching the given query. * * @param query query conditions - * @return list of all available workflow forms + * @return list of all available user request forms */ + @ApiResponses( + @ApiResponse(responseCode = "200", description = "list of all available user request forms", content = + @Content(schema = + @Schema(implementation = PagedResult.class)))) @GET @Path("forms") @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) PagedResult<UserRequestForm> getForms(@BeanParam UserRequestFormQuery query); /** - * Returns a list of available forms for the given user key. - * - * @param userKey user key - * @return list of available forms for the given user key - */ - @GET - @Path("forms/{userKey}") - @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) - List<UserRequestForm> getForms(@NotNull @PathParam("userKey") String userKey); - - /** - * Claims the form for the given task id. + * Requests to manage the form for the given task id. * * @param taskId workflow task id - * @return the workflow form for the given task id + * @return the form for the given task id */ + @ApiResponses( + @ApiResponse(responseCode = "200", description = "the form for the given task id", content = + @Content(schema = + @Schema(implementation = UserRequestForm.class)))) @POST @Path("forms/{taskId}/claim") @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) UserRequestForm claimForm(@NotNull @PathParam("taskId") String taskId); /** - * Submits a workflow form. + * Submits a user request form. * - * @param form workflow form. + * @param form user request form. * @return updated user */ + @ApiResponses( + @ApiResponse(responseCode = "200", description = "updated user", content = + @Content(schema = + @Schema(implementation = UserTO.class)))) @POST @Path("forms") @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserWorkflowTaskService.java ---------------------------------------------------------------------- diff --git a/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserWorkflowTaskService.java b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserWorkflowTaskService.java index 54f38d0..b396d6e 100644 --- a/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserWorkflowTaskService.java +++ b/ext/flowable/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserWorkflowTaskService.java @@ -18,6 +18,11 @@ */ package org.apache.syncope.common.rest.api.service; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.security.SecurityRequirements; import io.swagger.v3.oas.annotations.tags.Tag; @@ -48,6 +53,11 @@ public interface UserWorkflowTaskService extends JAXRSService { * @param userKey user key * @return list of available tasks for the given user key */ + @ApiResponses( + @ApiResponse(responseCode = "200", description = "list of available tasks for the given user key", content = + @Content(array = + @ArraySchema(schema = + @Schema(implementation = WorkflowTask.class))))) @GET @Path("tasks/{userKey}") @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) @@ -59,6 +69,10 @@ public interface UserWorkflowTaskService extends JAXRSService { * @param workflowTaskExecInput input for task execution * @return updated user */ + @ApiResponses( + @ApiResponse(responseCode = "200", description = "updated user", content = + @Content(schema = + @Schema(implementation = UserTO.class)))) @POST @Path("tasks/{userKey}") @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML }) http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/BpmnProcessServiceImpl.java ---------------------------------------------------------------------- diff --git a/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/BpmnProcessServiceImpl.java b/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/BpmnProcessServiceImpl.java index dd1aea8..4f976b5 100644 --- a/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/BpmnProcessServiceImpl.java +++ b/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/BpmnProcessServiceImpl.java @@ -22,7 +22,7 @@ import java.util.List; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.StreamingOutput; -import org.apache.syncope.common.lib.to.BpmnProcessTO; +import org.apache.syncope.common.lib.to.BpmnProcess; import org.apache.syncope.common.lib.types.BpmnProcessFormat; import org.apache.syncope.common.rest.api.RESTHeaders; import org.apache.syncope.core.logic.BpmnProcessLogic; @@ -37,7 +37,7 @@ public class BpmnProcessServiceImpl extends AbstractServiceImpl implements BpmnP private BpmnProcessLogic logic; @Override - public List<BpmnProcessTO> list() { + public List<BpmnProcess> list() { return logic.list(); } http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java ---------------------------------------------------------------------- diff --git a/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java b/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java index 2f174a0..188d22e 100644 --- a/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java +++ b/ext/flowable/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserRequestServiceImpl.java @@ -21,14 +21,16 @@ package org.apache.syncope.core.rest.cxf.service; import java.util.List; import org.apache.commons.lang3.tuple.Pair; import org.apache.syncope.common.lib.to.PagedResult; -import org.apache.syncope.common.lib.to.UserRequestTO; +import org.apache.syncope.common.lib.to.UserRequest; import org.apache.syncope.common.lib.to.UserTO; import org.apache.syncope.common.lib.to.UserRequestForm; import org.apache.syncope.common.rest.api.beans.UserRequestFormQuery; +import org.apache.syncope.common.rest.api.beans.UserRequestQuery; import org.apache.syncope.core.logic.UserRequestLogic; +import org.apache.syncope.common.rest.api.service.UserRequestService; +import org.apache.syncope.core.persistence.api.dao.UserDAO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; -import org.apache.syncope.common.rest.api.service.UserRequestService; @Service public class UserRequestServiceImpl extends AbstractServiceImpl implements UserRequestService { @@ -36,11 +38,25 @@ public class UserRequestServiceImpl extends AbstractServiceImpl implements UserR @Autowired private UserRequestLogic logic; + @Autowired + private UserDAO userDAO; + + @Override + public PagedResult<UserRequest> list(final UserRequestQuery query) { + if (query.getUser() != null) { + query.setUser(getActualKey(userDAO, query.getUser())); + } + + Pair<Integer, List<UserRequest>> result = logic.list( + query.getUser(), query.getPage(), query.getSize(), getOrderByClauses(query.getOrderBy())); + return buildPagedResult(result.getRight(), query.getPage(), query.getSize(), result.getLeft()); + } + @Override - public UserRequestTO start(final String bpmnProcess, final String userKey) { - return userKey == null + public UserRequest start(final String bpmnProcess, final String user) { + return user == null ? logic.start(bpmnProcess) - : logic.start(bpmnProcess, userKey); + : logic.start(bpmnProcess, getActualKey(userDAO, user)); } @Override @@ -54,14 +70,13 @@ public class UserRequestServiceImpl extends AbstractServiceImpl implements UserR } @Override - public List<UserRequestForm> getForms(final String userKey) { - return logic.getForms(userKey); - } - - @Override public PagedResult<UserRequestForm> getForms(final UserRequestFormQuery query) { + if (query.getUser() != null) { + query.setUser(getActualKey(userDAO, query.getUser())); + } + Pair<Integer, List<UserRequestForm>> result = logic.getForms( - query.getPage(), query.getSize(), getOrderByClauses(query.getOrderBy())); + query.getUser(), query.getPage(), query.getSize(), getOrderByClauses(query.getOrderBy())); return buildPagedResult(result.getRight(), query.getPage(), query.getSize(), result.getLeft()); } @@ -69,5 +84,4 @@ public class UserRequestServiceImpl extends AbstractServiceImpl implements UserR public UserTO submitForm(final UserRequestForm form) { return logic.submitForm(form); } - } http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/fit/core-reference/pom.xml ---------------------------------------------------------------------- diff --git a/fit/core-reference/pom.xml b/fit/core-reference/pom.xml index c89241e..dc5e8d1 100644 --- a/fit/core-reference/pom.xml +++ b/fit/core-reference/pom.xml @@ -1541,6 +1541,26 @@ under the License. <build> <plugins> + <!-- Adds Flowable custom classes --> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <id>add-flowable-custom-classes</id> + <phase>initialize</phase> + <goals> + <goal>add-source</goal> + </goals> + <configuration> + <sources> + <source>${basedir}/src/main/java-all</source> + </sources> + </configuration> + </execution> + </executions> + </plugin> + <!-- Adds Flowable test content --> <plugin> <groupId>org.codehaus.mojo</groupId> http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/AssignDirectorGroup.java ---------------------------------------------------------------------- diff --git a/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/AssignDirectorGroup.java b/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/AssignDirectorGroup.java new file mode 100644 index 0000000..4db7ac2 --- /dev/null +++ b/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/AssignDirectorGroup.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.fit.core.reference.flowable; + +import org.apache.syncope.common.lib.patch.MembershipPatch; +import org.apache.syncope.common.lib.patch.UserPatch; +import org.apache.syncope.core.flowable.impl.FlowableRuntimeUtils; +import org.apache.syncope.core.flowable.task.AbstractFlowableServiceTask; +import org.apache.syncope.core.persistence.api.dao.UserDAO; +import org.apache.syncope.core.persistence.api.entity.user.User; +import org.apache.syncope.core.provisioning.api.PropagationByResource; +import org.apache.syncope.core.provisioning.api.data.UserDataBinder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class AssignDirectorGroup extends AbstractFlowableServiceTask { + + @Autowired + private UserDataBinder dataBinder; + + @Autowired + private UserDAO userDAO; + + @Override + protected void doExecute(final String executionId) { + User user = engine.getRuntimeService(). + getVariable(executionId, FlowableRuntimeUtils.USER, User.class); + + Boolean secondLevelApprove = engine.getRuntimeService(). + getVariable(executionId, "secondLevelApprove", Boolean.class); + if (Boolean.TRUE.equals(secondLevelApprove)) { + user = userDAO.save(user); + + UserPatch userPatch = new UserPatch(); + userPatch.setKey(user.getKey()); + userPatch.getMemberships().add(new MembershipPatch.Builder(). + group("ebf97068-aa4b-4a85-9f01-680e8c4cf227").build()); + + PropagationByResource propByRes = dataBinder.update(user, userPatch); + + // report updated user and propagation by resource as result + engine.getRuntimeService().setVariable(executionId, FlowableRuntimeUtils.USER, user); + engine.getRuntimeService().setVariable(executionId, FlowableRuntimeUtils.PROP_BY_RESOURCE, propByRes); + } else { + LOG.info("Second level was not approved, not assigning the director group to " + user.getUsername()); + } + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/CreateARelationship.java ---------------------------------------------------------------------- diff --git a/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/CreateARelationship.java b/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/CreateARelationship.java new file mode 100644 index 0000000..b0c5261 --- /dev/null +++ b/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/CreateARelationship.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.fit.core.reference.flowable; + +import org.apache.syncope.common.lib.patch.RelationshipPatch; +import org.apache.syncope.common.lib.patch.UserPatch; +import org.apache.syncope.common.lib.to.RelationshipTO; +import org.apache.syncope.core.flowable.impl.FlowableRuntimeUtils; +import org.apache.syncope.core.flowable.task.AbstractFlowableServiceTask; +import org.apache.syncope.core.persistence.api.dao.UserDAO; +import org.apache.syncope.core.persistence.api.entity.user.User; +import org.apache.syncope.core.provisioning.api.PropagationByResource; +import org.apache.syncope.core.provisioning.api.data.UserDataBinder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class CreateARelationship extends AbstractFlowableServiceTask { + + @Autowired + private UserDataBinder dataBinder; + + @Autowired + private UserDAO userDAO; + + @Override + protected void doExecute(final String executionId) { + User user = engine.getRuntimeService(). + getVariable(executionId, FlowableRuntimeUtils.USER, User.class); + + Boolean approve = engine.getRuntimeService(). + getVariable(executionId, "approve", Boolean.class); + if (Boolean.TRUE.equals(approve)) { + user = userDAO.save(user); + + String printer = engine.getRuntimeService(). + getVariable(executionId, "printer", String.class); + + UserPatch userPatch = new UserPatch(); + userPatch.setKey(user.getKey()); + userPatch.getRelationships().add(new RelationshipPatch.Builder(). + relationshipTO(new RelationshipTO.Builder(). + otherEnd("PRINTER", printer).type("neighborhood").build()). + build()); + + PropagationByResource propByRes = dataBinder.update(user, userPatch); + + // report updated user and propagation by resource as result + engine.getRuntimeService().setVariable(executionId, FlowableRuntimeUtils.USER, user); + engine.getRuntimeService().setVariable(executionId, FlowableRuntimeUtils.PROP_BY_RESOURCE, propByRes); + } else { + LOG.info("Printer assignment to " + user.getUsername() + " was not approved"); + } + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/PrintersValueProvider.java ---------------------------------------------------------------------- diff --git a/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/PrintersValueProvider.java b/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/PrintersValueProvider.java new file mode 100644 index 0000000..82e9693 --- /dev/null +++ b/fit/core-reference/src/main/java-all/org/apache/syncope/fit/core/reference/flowable/PrintersValueProvider.java @@ -0,0 +1,70 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.syncope.fit.core.reference.flowable; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import org.apache.syncope.common.lib.types.AnyTypeKind; +import org.apache.syncope.core.flowable.api.DropdownValueProvider; +import org.apache.syncope.core.persistence.api.dao.AnySearchDAO; +import org.apache.syncope.core.persistence.api.dao.search.AnyTypeCond; +import org.apache.syncope.core.persistence.api.dao.search.OrderByClause; +import org.apache.syncope.core.persistence.api.dao.search.SearchCond; +import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +public class PrintersValueProvider implements DropdownValueProvider { + + private static final SearchCond PRINTER_COND; + + private static final List<OrderByClause> ORDER_BY; + + static { + AnyTypeCond anyTypeCond = new AnyTypeCond(); + anyTypeCond.setAnyTypeKey("PRINTER"); + PRINTER_COND = SearchCond.getLeafCond(anyTypeCond); + + OrderByClause orderByNameAsc = new OrderByClause(); + orderByNameAsc.setField("name"); + orderByNameAsc.setDirection(OrderByClause.Direction.ASC); + ORDER_BY = Collections.singletonList(orderByNameAsc); + } + + @Autowired + private AnySearchDAO anySearchDAO; + + @Transactional(readOnly = true) + @Override + public Map<String, String> getValues() { + return anySearchDAO.<AnyObject>search(PRINTER_COND, ORDER_BY, AnyTypeKind.ANY_OBJECT).stream(). + collect(Collectors.toMap( + AnyObject::getKey, + AnyObject::getName, + (u, v) -> { + throw new IllegalStateException(String.format("Duplicate key %s", u)); + }, + LinkedHashMap::new)); + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/AssignDirectorGroup.java ---------------------------------------------------------------------- diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/AssignDirectorGroup.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/AssignDirectorGroup.java deleted file mode 100644 index abdfcb6..0000000 --- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/AssignDirectorGroup.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.syncope.fit.core.reference; - -import org.apache.syncope.common.lib.patch.MembershipPatch; -import org.apache.syncope.common.lib.patch.UserPatch; -import org.apache.syncope.core.flowable.impl.FlowableRuntimeUtils; -import org.apache.syncope.core.flowable.task.AbstractFlowableServiceTask; -import org.apache.syncope.core.persistence.api.dao.UserDAO; -import org.apache.syncope.core.persistence.api.entity.user.User; -import org.apache.syncope.core.provisioning.api.PropagationByResource; -import org.apache.syncope.core.provisioning.api.data.UserDataBinder; -import org.springframework.beans.factory.annotation.Autowired; - -public class AssignDirectorGroup extends AbstractFlowableServiceTask { - - @Autowired - private UserDataBinder dataBinder; - - @Autowired - private UserDAO userDAO; - - @Override - protected void doExecute(final String executionId) { - User user = engine.getRuntimeService(). - getVariable(executionId, FlowableRuntimeUtils.USER, User.class); - - Boolean secondLevelApprove = engine.getRuntimeService(). - getVariable(executionId, "secondLevelApprove", Boolean.class); - if (Boolean.TRUE.equals(secondLevelApprove)) { - user = userDAO.save(user); - - UserPatch userPatch = new UserPatch(); - userPatch.setKey(user.getKey()); - userPatch.getMemberships().add(new MembershipPatch.Builder(). - group("ebf97068-aa4b-4a85-9f01-680e8c4cf227").build()); - - PropagationByResource propByRes = dataBinder.update(user, userPatch); - - // report updated user and propagation by resource as result - engine.getRuntimeService().setVariable(executionId, FlowableRuntimeUtils.USER, user); - engine.getRuntimeService().setVariable(executionId, FlowableRuntimeUtils.PROP_BY_RESOURCE, propByRes); - } else { - LOG.info("Second level was not approved, not assigning the director group to " + user.getUsername()); - } - } -} http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/fit/core-reference/src/main/resources/all/workflowTestContext.xml ---------------------------------------------------------------------- diff --git a/fit/core-reference/src/main/resources/all/workflowTestContext.xml b/fit/core-reference/src/main/resources/all/workflowTestContext.xml index 2329c53..b14490a 100644 --- a/fit/core-reference/src/main/resources/all/workflowTestContext.xml +++ b/fit/core-reference/src/main/resources/all/workflowTestContext.xml @@ -19,9 +19,12 @@ under the License. --> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans - http://www.springframework.org/schema/beans/spring-beans.xsd"> + http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context.xsd"> - <bean id="assignDirectorGroup" class="org.apache.syncope.fit.core.reference.AssignDirectorGroup"/> + <context:component-scan base-package="org.apache.syncope.fit.core.reference.flowable"/> </beans> http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/fit/core-reference/src/main/resources/assignPrinterRequest.bpmn20.xml ---------------------------------------------------------------------- diff --git a/fit/core-reference/src/main/resources/assignPrinterRequest.bpmn20.xml b/fit/core-reference/src/main/resources/assignPrinterRequest.bpmn20.xml new file mode 100644 index 0000000..c9ecb9c --- /dev/null +++ b/fit/core-reference/src/main/resources/assignPrinterRequest.bpmn20.xml @@ -0,0 +1,92 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +Licensed to the Apache Software Foundation (ASF) under one +or more contributor license agreements. See the NOTICE file +distributed with this work for additional information +regarding copyright ownership. The ASF licenses this file +to you under the Apache License, Version 2.0 (the +"License"); you may not use this file except in compliance +with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, either express or implied. See the License for the +specific language governing permissions and limitations +under the License. +--> +<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:flowable="http://flowable.org/bpmn" + xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" + xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" + xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" + typeLanguage="http://www.w3.org/2001/XMLSchema" + expressionLanguage="http://www.w3.org/1999/XPath" + targetNamespace="http://www.flowable.org/processdef"> + + <process id="assignPrinterRequest" name="Assign printer" isExecutable="true"> + <startEvent id="startevent1" name="Start"/> + <endEvent id="endevent1" name="End"/> + <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="selectPrinter"/> + <userTask id="selectPrinter" name="Select printer" flowable:formKey="selectPrinter" flowable:assignee="${wfExecutor}"> + <extensionElements> + <flowable:formProperty id="printer" name="Printer" variable="printer" type="dropdown" required="true"> + <flowable:value id="dropdownValueProvider" name="printersValueProvider"/> + </flowable:formProperty> + <flowable:formProperty id="printMode" name="Preferred print mode?" type="enum"> + <flowable:value id="bw" name="Black / White"/> + <flowable:value id="color" name="Color"/> + </flowable:formProperty> + </extensionElements> + </userTask> + <userTask id="approvePrinter" name="Approve printer" flowable:formKey="approvePrinter"> + <extensionElements> + <flowable:formProperty id="username" name="Username" type="string" expression="${userTO.username}" writable="false"/> + <flowable:formProperty id="printer" name="Selected printer" type="string" expression="${printer}" writable="false"/> + <flowable:formProperty id="approve" name="Approve?" type="boolean" variable="approve" required="true"/> + </extensionElements> + </userTask> + <sequenceFlow id="sid-D7047714-8E57-46B8-B6D4-4844DE330329" sourceRef="selectPrinter" targetRef="approvePrinter"/> + <serviceTask id="createARelationship" name="Create ARelationship" flowable:expression="#{createARelationship.execute(execution.processInstanceId)}"/> + <sequenceFlow id="sid-33880AE7-35C6-4A39-8E5B-12D8BA53F042" sourceRef="approvePrinter" targetRef="createARelationship"/> + <sequenceFlow id="sid-831E1896-EDF9-4F7D-AA42-E86CC1F8C5D3" sourceRef="createARelationship" targetRef="endevent1"/> + </process> + <bpmndi:BPMNDiagram id="BPMNDiagram_assignPrinterRequest"> + <bpmndi:BPMNPlane bpmnElement="assignPrinterRequest" id="BPMNPlane_assignPrinterRequest"> + <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1"> + <omgdc:Bounds height="30.0" width="30.0" x="180.0" y="115.0"/> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1"> + <omgdc:Bounds height="28.0" width="28.0" x="885.0" y="116.0"/> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape bpmnElement="selectPrinter" id="BPMNShape_selectPrinter"> + <omgdc:Bounds height="80.0" width="100.0" x="330.0" y="90.0"/> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape bpmnElement="approvePrinter" id="BPMNShape_approvePrinter"> + <omgdc:Bounds height="80.0" width="100.0" x="495.5" y="90.0"/> + </bpmndi:BPMNShape> + <bpmndi:BPMNShape bpmnElement="createARelationship" id="BPMNShape_createARelationship"> + <omgdc:Bounds height="80.0" width="100.0" x="675.0" y="90.0"/> + </bpmndi:BPMNShape> + <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1"> + <omgdi:waypoint x="209.94999901196195" y="130.0"/> + <omgdi:waypoint x="330.0" y="130.0"/> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge bpmnElement="sid-D7047714-8E57-46B8-B6D4-4844DE330329" id="BPMNEdge_sid-D7047714-8E57-46B8-B6D4-4844DE330329"> + <omgdi:waypoint x="429.95000000000005" y="130.0"/> + <omgdi:waypoint x="495.5" y="130.0"/> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge bpmnElement="sid-33880AE7-35C6-4A39-8E5B-12D8BA53F042" id="BPMNEdge_sid-33880AE7-35C6-4A39-8E5B-12D8BA53F042"> + <omgdi:waypoint x="595.4499999999068" y="130.0"/> + <omgdi:waypoint x="675.0" y="130.0"/> + </bpmndi:BPMNEdge> + <bpmndi:BPMNEdge bpmnElement="sid-831E1896-EDF9-4F7D-AA42-E86CC1F8C5D3" id="BPMNEdge_sid-831E1896-EDF9-4F7D-AA42-E86CC1F8C5D3"> + <omgdi:waypoint x="774.9499999999266" y="130.0"/> + <omgdi:waypoint x="885.0" y="130.0"/> + </bpmndi:BPMNEdge> + </bpmndi:BPMNPlane> + </bpmndi:BPMNDiagram> +</definitions> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthenticationITCase.java ---------------------------------------------------------------------- diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthenticationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthenticationITCase.java index e2f351b..cbdb19b 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthenticationITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/AuthenticationITCase.java @@ -66,6 +66,7 @@ import org.apache.syncope.common.lib.types.StandardEntitlement; import org.apache.syncope.common.lib.types.StatusPatchType; import org.apache.syncope.common.rest.api.RESTHeaders; import org.apache.syncope.common.rest.api.beans.AnyQuery; +import org.apache.syncope.common.rest.api.beans.UserRequestFormQuery; import org.apache.syncope.common.rest.api.service.AnyObjectService; import org.apache.syncope.common.rest.api.service.SchemaService; import org.apache.syncope.common.rest.api.service.UserService; @@ -495,7 +496,8 @@ public class AuthenticationITCase extends AbstractITCase { } // 3. approve user - UserRequestForm form = userRequestService.getForms(userTO.getKey()).get(0); + UserRequestForm form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(userTO.getKey()).build()).getResult().get(0); form = userRequestService.claimForm(form.getTaskId()); form.getProperty("approveCreate").get().setValue(Boolean.TRUE.toString()); userTO = userRequestService.submitForm(form); http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BpmnProcessITCase.java ---------------------------------------------------------------------- diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BpmnProcessITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BpmnProcessITCase.java index 443cd83..21fb4fd 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BpmnProcessITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/BpmnProcessITCase.java @@ -28,7 +28,7 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import javax.ws.rs.core.Response; import org.apache.commons.io.IOUtils; -import org.apache.syncope.common.lib.to.BpmnProcessTO; +import org.apache.syncope.common.lib.to.BpmnProcess; import org.apache.syncope.fit.AbstractITCase; import org.apache.syncope.fit.FlowableDetector; import org.junit.jupiter.api.BeforeAll; @@ -42,7 +42,7 @@ public class BpmnProcessITCase extends AbstractITCase { public static void findDefault() { assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService)); bpmnProcessService.list().stream(). - filter(BpmnProcessTO::isUserWorkflow).findAny(). + filter(BpmnProcess::isUserWorkflow).findAny(). ifPresent(process -> { userWorkflowKey = process.getKey(); }); http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserRequestITCase.java ---------------------------------------------------------------------- diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserRequestITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserRequestITCase.java index 5446894..9281bce 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserRequestITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserRequestITCase.java @@ -25,14 +25,19 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.assumeTrue; import java.io.IOException; +import java.util.List; import javax.ws.rs.core.MediaType; import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.jaxrs.client.WebClient; +import org.apache.syncope.client.lib.SyncopeClient; import org.apache.syncope.common.lib.to.PagedResult; +import org.apache.syncope.common.lib.to.RelationshipTO; import org.apache.syncope.common.lib.to.UserRequestForm; -import org.apache.syncope.common.lib.to.UserRequestTO; +import org.apache.syncope.common.lib.to.UserRequest; import org.apache.syncope.common.lib.to.UserTO; import org.apache.syncope.common.rest.api.beans.UserRequestFormQuery; +import org.apache.syncope.common.rest.api.beans.UserRequestQuery; +import org.apache.syncope.common.rest.api.service.UserRequestService; import org.apache.syncope.fit.AbstractITCase; import org.apache.syncope.fit.FlowableDetector; import org.junit.jupiter.api.BeforeAll; @@ -42,9 +47,13 @@ public class UserRequestITCase extends AbstractITCase { @BeforeAll public static void loadBpmnProcesses() throws IOException { + assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService)); + WebClient.client(bpmnProcessService).type(MediaType.APPLICATION_XML_TYPE); bpmnProcessService.set("directorGroupRequest", IOUtils.toString(UserRequestITCase.class.getResourceAsStream("/directorGroupRequest.bpmn20.xml"))); + bpmnProcessService.set("assignPrinterRequest", + IOUtils.toString(UserRequestITCase.class.getResourceAsStream("/assignPrinterRequest.bpmn20.xml"))); } @Test @@ -56,17 +65,29 @@ public class UserRequestITCase extends AbstractITCase { assertFalse(user.getMembership("ebf97068-aa4b-4a85-9f01-680e8c4cf227").isPresent()); // start request - UserRequestTO req = userRequestService.start("directorGroupRequest", user.getKey()); + UserRequest req = userRequestService.start("directorGroupRequest", user.getKey()); assertNotNull(req); + assertEquals("directorGroupRequest", req.getBpmnProcess()); + assertNotNull(req.getExecutionId()); + assertEquals(req.getUser(), user.getKey()); + + // check that user can see the ongoing request + SyncopeClient client = clientFactory.create(user.getUsername(), "password123"); + PagedResult<UserRequest> requests = client.getService(UserRequestService.class). + list(new UserRequestQuery.Builder().user(user.getKey()).build()); + assertEquals(1, requests.getTotalCount()); + assertEquals("directorGroupRequest", requests.getResult().get(0).getBpmnProcess()); // 1st approval -> reject - UserRequestForm form = userRequestService.getForms(user.getKey()).get(0); + UserRequestForm form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(user.getKey()).build()).getResult().get(0); form = userRequestService.claimForm(form.getTaskId()); form.getProperty("firstLevelApprove").get().setValue(Boolean.FALSE.toString()); userRequestService.submitForm(form); // no more forms, group not assigned - assertTrue(userRequestService.getForms(user.getKey()).isEmpty()); + assertTrue(userRequestService.getForms( + new UserRequestFormQuery.Builder().user(user.getKey()).build()).getResult().isEmpty()); assertFalse(userService.read(user.getKey()).getMembership("ebf97068-aa4b-4a85-9f01-680e8c4cf227").isPresent()); // start request again @@ -74,19 +95,22 @@ public class UserRequestITCase extends AbstractITCase { assertNotNull(req); // 1st approval -> accept - form = userRequestService.getForms(user.getKey()).get(0); + form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(user.getKey()).build()).getResult().get(0); form = userRequestService.claimForm(form.getTaskId()); form.getProperty("firstLevelApprove").get().setValue(Boolean.TRUE.toString()); userRequestService.submitForm(form); // 2nd approval -> reject - form = userRequestService.getForms(user.getKey()).get(0); + form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(user.getKey()).build()).getResult().get(0); form = userRequestService.claimForm(form.getTaskId()); form.getProperty("secondLevelApprove").get().setValue(Boolean.FALSE.toString()); user = userRequestService.submitForm(form); // no more forms, group not assigned - assertTrue(userRequestService.getForms(user.getKey()).isEmpty()); + assertTrue(userRequestService.getForms( + new UserRequestFormQuery.Builder().user(user.getKey()).build()).getResult().isEmpty()); assertFalse(userService.read(user.getKey()).getMembership("ebf97068-aa4b-4a85-9f01-680e8c4cf227").isPresent()); // start request again @@ -94,13 +118,15 @@ public class UserRequestITCase extends AbstractITCase { assertNotNull(req); // 1st approval -> accept - form = userRequestService.getForms(user.getKey()).get(0); + form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(user.getKey()).build()).getResult().get(0); form = userRequestService.claimForm(form.getTaskId()); form.getProperty("firstLevelApprove").get().setValue(Boolean.TRUE.toString()); userRequestService.submitForm(form); // 2nd approval -> accept - form = userRequestService.getForms(user.getKey()).get(0); + form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(user.getKey()).build()).getResult().get(0); form = userRequestService.claimForm(form.getTaskId()); form.getProperty("secondLevelApprove").get().setValue(Boolean.TRUE.toString()); user = userRequestService.submitForm(form); @@ -115,7 +141,7 @@ public class UserRequestITCase extends AbstractITCase { assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService)); PagedResult<UserRequestForm> forms = - userRequestService.getForms(new UserRequestFormQuery.Builder().page(1).size(1000).build()); + userRequestService.getForms(new UserRequestFormQuery.Builder().build()); int preForms = forms.getTotalCount(); UserTO user = createUser(UserITCase.getUniqueSampleTO("twolevelsappro...@tirasa.net")).getEntity(); @@ -123,22 +149,101 @@ public class UserRequestITCase extends AbstractITCase { assertFalse(user.getMembership("ebf97068-aa4b-4a85-9f01-680e8c4cf227").isPresent()); // start request - UserRequestTO req = userRequestService.start("directorGroupRequest", user.getKey()); + UserRequest req = userRequestService.start("directorGroupRequest", user.getKey()); assertNotNull(req); // check that form was generated - forms = userRequestService.getForms(new UserRequestFormQuery.Builder().page(1).size(1000).build()); + forms = userRequestService.getForms(new UserRequestFormQuery.Builder().build()); assertEquals(preForms + 1, forms.getTotalCount()); - assertEquals(1, userRequestService.getForms(user.getKey()).size()); + assertEquals(1, userRequestService.getForms( + new UserRequestFormQuery.Builder().user(user.getKey()).build()).getResult().size()); // cancel request userRequestService.cancel(req.getExecutionId(), "nothing in particular"); // check that form was removed - forms = userRequestService.getForms(new UserRequestFormQuery.Builder().page(1).size(1000).build()); + forms = userRequestService.getForms(new UserRequestFormQuery.Builder().build()); + assertEquals(preForms, forms.getTotalCount()); + + assertTrue(userRequestService.getForms( + new UserRequestFormQuery.Builder().user(user.getKey()).build()).getResult().isEmpty()); + } + + @Test + public void userSelection() { + assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService)); + + assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService)); + + PagedResult<UserRequestForm> forms = + userRequestService.getForms(new UserRequestFormQuery.Builder().build()); + int preForms = forms.getTotalCount(); + + UserTO user = createUser(UserITCase.getUniqueSampleTO("userselect...@tirasa.net")).getEntity(); + assertNotNull(user); + List<RelationshipTO> relationships = userService.read(user.getKey()).getRelationships(); + assertTrue(relationships.isEmpty()); + + SyncopeClient client = clientFactory.create(user.getUsername(), "password123"); + + // start request as user + UserRequest req = client.getService(UserRequestService.class).start("assignPrinterRequest", null); + assertNotNull(req); + + // check (as admin) that a new form is available + forms = userRequestService.getForms(new UserRequestFormQuery.Builder().build()); + assertEquals(preForms + 1, forms.getTotalCount()); + + // get (as user) the form, claim and submit + PagedResult<UserRequestForm> userForms = client.getService(UserRequestService.class). + getForms(new UserRequestFormQuery.Builder().user(user.getKey()).build()); + assertEquals(1, userForms.getTotalCount()); + + UserRequestForm form = userForms.getResult().get(0); + assertEquals("assignPrinterRequest", form.getBpmnProcess()); + form = client.getService(UserRequestService.class).claimForm(form.getTaskId()); + + assertFalse(form.getProperty("printer").get().getDropdownValues().isEmpty()); + form.getProperty("printer").ifPresent(printer -> printer.setValue("8559d14d-58c2-46eb-a2d4-a7d35161e8f8")); + + assertFalse(form.getProperty("printMode").get().getEnumValues().isEmpty()); + form.getProperty("printMode").ifPresent(printMode -> printMode.setValue("color")); + + client.getService(UserRequestService.class).submitForm(form); + + userForms = client.getService(UserRequestService.class).getForms( + new UserRequestFormQuery.Builder().user(user.getKey()).build()); + assertEquals(0, userForms.getTotalCount()); + + // check that user can see the ongoing request + PagedResult<UserRequest> requests = client.getService(UserRequestService.class). + list(new UserRequestQuery.Builder().user(user.getKey()).build()); + assertEquals(1, requests.getTotalCount()); + assertEquals("assignPrinterRequest", requests.getResult().get(0).getBpmnProcess()); + + // get (as admin) the new form, claim and submit + form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(user.getKey()).build()).getResult().get(0); + assertEquals("assignPrinterRequest", form.getBpmnProcess()); + form = userRequestService.claimForm(form.getTaskId()); + + assertEquals("8559d14d-58c2-46eb-a2d4-a7d35161e8f8", form.getProperty("printer").get().getValue()); + + form.getProperty("approve").get().setValue(Boolean.TRUE.toString()); + userRequestService.submitForm(form); + + // no more forms available + forms = userRequestService.getForms(new UserRequestFormQuery.Builder().build()); assertEquals(preForms, forms.getTotalCount()); - assertTrue(userRequestService.getForms(user.getKey()).isEmpty()); + assertTrue(client.getService(UserRequestService.class). + list(new UserRequestQuery.Builder().user(user.getKey()).build()).getResult().isEmpty()); + + // check that relationship was made effective by approval + relationships = userService.read(user.getKey()).getRelationships(); + assertFalse(relationships.isEmpty()); + assertTrue(relationships.stream(). + anyMatch(relationship -> "8559d14d-58c2-46eb-a2d4-a7d35161e8f8".equals(relationship.getOtherEndKey()))); } } http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java ---------------------------------------------------------------------- diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java index 0e48cf2..63db20e 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserSelfITCase.java @@ -130,7 +130,8 @@ public class UserSelfITCase extends AbstractITCase { } // now approve and verify that propagation has happened - UserRequestForm form = userRequestService.getForms(userTO.getKey()).get(0); + UserRequestForm form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(userTO.getKey()).build()).getResult().get(0); form = userRequestService.claimForm(form.getTaskId()); form.getProperty("approveCreate").get().setValue(Boolean.TRUE.toString()); userTO = userRequestService.submitForm(form); @@ -228,7 +229,8 @@ public class UserSelfITCase extends AbstractITCase { } // 3. approve self-update as admin - UserRequestForm form = userRequestService.getForms(updated.getKey()).get(0); + UserRequestForm form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(updated.getKey()).build()).getResult().get(0); form = userRequestService.claimForm(form.getTaskId()); form.getProperty("approveUpdate").get().setValue(Boolean.TRUE.toString()); updated = userRequestService.submitForm(form); @@ -420,7 +422,8 @@ public class UserSelfITCase extends AbstractITCase { assertEquals("createApproval", userTO.getStatus()); // 2. request if there is any pending task for user just created - UserRequestForm form = userRequestService.getForms(userTO.getKey()).get(0); + UserRequestForm form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(userTO.getKey()).build()).getResult().get(0); assertNotNull(form); assertNotNull(form.getUsername()); assertEquals(userTO.getUsername(), form.getUsername()); @@ -480,8 +483,7 @@ public class UserSelfITCase extends AbstractITCase { assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService)); // read forms *before* any operation - PagedResult<UserRequestForm> forms = - userRequestService.getForms(new UserRequestFormQuery.Builder().page(1).size(1000).build()); + PagedResult<UserRequestForm> forms = userRequestService.getForms(new UserRequestFormQuery.Builder().build()); int preForms = forms.getTotalCount(); UserTO userTO = UserITCase.getUniqueSampleTO("createwithappro...@syncope.apache.org"); @@ -514,7 +516,7 @@ public class UserSelfITCase extends AbstractITCase { assertNotNull(exception); // 2. request if there is any pending form for user just created - forms = userRequestService.getForms(new UserRequestFormQuery.Builder().page(1).size(1000).build()); + forms = userRequestService.getForms(new UserRequestFormQuery.Builder().build()); assertEquals(preForms + 1, forms.getTotalCount()); // 3. as admin, update user: still pending approval @@ -524,7 +526,8 @@ public class UserSelfITCase extends AbstractITCase { userPatch.setUsername(new StringReplacePatchItem.Builder().value(updatedUsername).build()); updateUser(userPatch); - UserRequestForm form = userRequestService.getForms(userTO.getKey()).get(0); + UserRequestForm form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(userTO.getKey()).build()).getResult().get(0); assertNotNull(form); assertNotNull(form.getTaskId()); assertNotNull(form.getUserTO()); @@ -567,8 +570,8 @@ public class UserSelfITCase extends AbstractITCase { assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService)); // read forms *before* any operation - PagedResult<UserRequestForm> forms = userRequestService.getForms(new UserRequestFormQuery.Builder(). - page(1).size(1000).build()); + PagedResult<UserRequestForm> forms = userRequestService.getForms( + new UserRequestFormQuery.Builder().build()); int preForms = forms.getTotalCount(); UserTO created = createUser(UserITCase.getUniqueSampleTO("updateappro...@syncope.apache.org")).getEntity(); @@ -585,10 +588,11 @@ public class UserSelfITCase extends AbstractITCase { assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); assertEquals("updateApproval", userService.read(created.getKey()).getStatus()); - forms = userRequestService.getForms(new UserRequestFormQuery.Builder().page(1).size(1000).build()); + forms = userRequestService.getForms(new UserRequestFormQuery.Builder().build()); assertEquals(preForms + 1, forms.getTotalCount()); - UserRequestForm form = userRequestService.getForms(created.getKey()).get(0); + UserRequestForm form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(created.getKey()).build()).getResult().get(0); assertNotNull(form); assertNotNull(form.getTaskId()); assertNull(form.getOwner()); @@ -607,7 +611,8 @@ public class UserSelfITCase extends AbstractITCase { assertEquals(0, updated.getMemberships().size()); // the patch is not updated in the approval form - form = userRequestService.getForms(created.getKey()).get(0); + form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(created.getKey()).build()).getResult().get(0); assertEquals(patch, form.getUserPatch()); // approve the user @@ -642,8 +647,7 @@ public class UserSelfITCase extends AbstractITCase { assumeTrue(FlowableDetector.isFlowableEnabledForUserWorkflow(syncopeService)); // read forms *before* any operation - PagedResult<UserRequestForm> forms = userRequestService.getForms(new UserRequestFormQuery.Builder(). - page(1).size(1000).build()); + PagedResult<UserRequestForm> forms = userRequestService.getForms(new UserRequestFormQuery.Builder().build()); int preForms = forms.getTotalCount(); UserTO userTO = UserITCase.getUniqueSampleTO("issuesyncop...@syncope.apache.org"); @@ -667,10 +671,11 @@ public class UserSelfITCase extends AbstractITCase { assertEquals(userTO.getCreationDate(), userTO.getLastChangeDate()); // 2. request if there is any pending form for user just created - forms = userRequestService.getForms(new UserRequestFormQuery.Builder().page(1).size(1000).build()); + forms = userRequestService.getForms(new UserRequestFormQuery.Builder().build()); assertEquals(preForms + 1, forms.getTotalCount()); - UserRequestForm form = userRequestService.getForms(userTO.getKey()).get(0); + UserRequestForm form = userRequestService.getForms( + new UserRequestFormQuery.Builder().user(userTO.getKey()).build()).getResult().get(0); assertNotNull(form); // 3. first claim by bellini .... @@ -692,12 +697,12 @@ public class UserSelfITCase extends AbstractITCase { userTO = userRequestService.submitForm(form); assertNotNull(userTO); assertEquals(preForms, - userRequestService.getForms(new UserRequestFormQuery.Builder().page(1).size(1000).build()). - getTotalCount()); - assertTrue(userRequestService.getForms(userTO.getKey()).isEmpty()); + userRequestService.getForms(new UserRequestFormQuery.Builder().build()).getTotalCount()); + assertTrue(userRequestService.getForms( + new UserRequestFormQuery.Builder().user(userTO.getKey()).build()).getResult().isEmpty()); // 7.check that no more forms are still to be processed - forms = userRequestService.getForms(new UserRequestFormQuery.Builder().page(1).size(1000).build()); + forms = userRequestService.getForms(new UserRequestFormQuery.Builder().build()); assertEquals(preForms, forms.getTotalCount()); } http://git-wip-us.apache.org/repos/asf/syncope/blob/fee1317d/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index edc38b0..a04a9e5 100644 --- a/pom.xml +++ b/pom.xml @@ -1748,6 +1748,12 @@ under the License. </plugin> <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <version>3.0.0</version> + </plugin> + + <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-javadoc-plugin</artifactId> <version>2.10.4</version> @@ -2305,8 +2311,8 @@ under the License. <link>https://docs.spring.io/spring-security/site/docs/5.0.x/api/</link> <link>http://www.flowable.org/docs/javadocs/</link> <link>https://build.shibboleth.net/nexus/content/sites/site/java-opensaml/3.3.0/apidocs/</link> - <link>https://artifacts.elastic.co/javadoc/org/elasticsearch/elasticsearch/6.4.1/index.html</link> - <link>http://docs.swagger.io/swagger-core/v2.0.5/apidocs/</link> + <link>https://artifacts.elastic.co/javadoc/org/elasticsearch/elasticsearch/6.4.1/index.html</link> + <link>http://docs.swagger.io/swagger-core/v2.0.5/apidocs/</link> </links> </configuration> <reportSets>