diff --git a/wrenidm-workflow-flowable/src/main/java/org/wrensecurity/wrenidm/workflow/flowable/impl/identity/IdmIdentityService.java b/wrenidm-workflow-flowable/src/main/java/org/wrensecurity/wrenidm/workflow/flowable/impl/identity/IdmIdentityService.java index 332a51a19..27c0a776b 100644 --- a/wrenidm-workflow-flowable/src/main/java/org/wrensecurity/wrenidm/workflow/flowable/impl/identity/IdmIdentityService.java +++ b/wrenidm-workflow-flowable/src/main/java/org/wrensecurity/wrenidm/workflow/flowable/impl/identity/IdmIdentityService.java @@ -47,7 +47,7 @@ public class IdmIdentityService extends IdmIdentityServiceImpl { public static final String GIVEN_NAME_ATTR = "givenName"; public static final String SURNAME_ATTR = "sn"; public static final String MAIL_ATTR = "mail"; - public static final String MEMBERS_ATTR = "members"; + public static final String MEMBERS_ATTR = "authzMembers"; public static final String ROLES_ATTR = "authzRoles"; private ConnectionFactory connectionFactory; @@ -75,7 +75,7 @@ public void setAuthenticatedUserId(String userId) { @Override public UserQuery createUserQuery() { - throw new UnsupportedOperationException("Creating user query is not supported."); + return new IdmUserQuery(getConnection()); } @Override diff --git a/wrenidm-workflow-flowable/src/main/java/org/wrensecurity/wrenidm/workflow/flowable/impl/identity/IdmUser.java b/wrenidm-workflow-flowable/src/main/java/org/wrensecurity/wrenidm/workflow/flowable/impl/identity/IdmUser.java index 05471a195..e37a4e001 100644 --- a/wrenidm-workflow-flowable/src/main/java/org/wrensecurity/wrenidm/workflow/flowable/impl/identity/IdmUser.java +++ b/wrenidm-workflow-flowable/src/main/java/org/wrensecurity/wrenidm/workflow/flowable/impl/identity/IdmUser.java @@ -20,7 +20,7 @@ import org.forgerock.json.JsonValue; /** - * Component representing IdM user. + * IdM's managed user wrapper. */ public class IdmUser extends JsonValue implements User { @@ -37,6 +37,7 @@ public String getId() { @Override public void setId(String id) { + throw new UnsupportedOperationException("IdM user cannot be modified"); } @Override @@ -46,6 +47,7 @@ public String getFirstName() { @Override public void setFirstName(String firstName) { + throw new UnsupportedOperationException("IdM user cannot be modified"); } @Override @@ -55,6 +57,7 @@ public String getLastName() { @Override public void setLastName(String lastName) { + throw new UnsupportedOperationException("IdM user cannot be modified"); } @Override @@ -64,6 +67,7 @@ public String getDisplayName() { @Override public void setDisplayName(String displayName) { + throw new UnsupportedOperationException("IdM user cannot be modified"); } @Override @@ -73,6 +77,7 @@ public String getEmail() { @Override public void setEmail(String email) { + throw new UnsupportedOperationException("IdM user cannot be modified"); } @Override @@ -82,6 +87,7 @@ public String getPassword() { @Override public void setPassword(String password) { + throw new UnsupportedOperationException("IdM user cannot be modified"); } @Override @@ -91,6 +97,7 @@ public String getTenantId() { @Override public void setTenantId(String tenantId) { + throw new UnsupportedOperationException("IdM user cannot be modified"); } @Override diff --git a/wrenidm-workflow-flowable/src/main/java/org/wrensecurity/wrenidm/workflow/flowable/impl/identity/IdmUserQuery.java b/wrenidm-workflow-flowable/src/main/java/org/wrensecurity/wrenidm/workflow/flowable/impl/identity/IdmUserQuery.java index 7725f50e0..06f037a65 100644 --- a/wrenidm-workflow-flowable/src/main/java/org/wrensecurity/wrenidm/workflow/flowable/impl/identity/IdmUserQuery.java +++ b/wrenidm-workflow-flowable/src/main/java/org/wrensecurity/wrenidm/workflow/flowable/impl/identity/IdmUserQuery.java @@ -16,21 +16,27 @@ */ package org.wrensecurity.wrenidm.workflow.flowable.impl.identity; +import static org.forgerock.openidm.util.ContextUtil.createInternalContext; + import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.stream.Collectors; +import org.activiti.engine.ActivitiIllegalArgumentException; import org.flowable.common.engine.impl.interceptor.CommandContext; import org.flowable.idm.api.User; +import org.flowable.idm.api.UserQuery; import org.flowable.idm.engine.impl.UserQueryImpl; +import org.forgerock.json.JsonPointer; +import org.forgerock.json.JsonValue; +import org.forgerock.json.resource.BadRequestException; import org.forgerock.json.resource.Connection; +import org.forgerock.json.resource.NotFoundException; import org.forgerock.json.resource.QueryRequest; -import org.forgerock.json.resource.QueryResourceHandler; +import org.forgerock.json.resource.ReadRequest; import org.forgerock.json.resource.Requests; import org.forgerock.json.resource.ResourceException; import org.forgerock.json.resource.ResourceResponse; -import org.forgerock.openidm.util.ContextUtil; -import org.forgerock.services.context.Context; -import org.wrensecurity.wrenidm.workflow.flowable.WorkflowConstants; /** * Component handling flowable user queries. @@ -39,8 +45,6 @@ public class IdmUserQuery extends UserQueryImpl { private static final long serialVersionUID = 1L; - private static final Context context = ContextUtil.createInternalContext(); - private final Connection connection; public IdmUserQuery(Connection connection) { @@ -49,72 +53,183 @@ public IdmUserQuery(Connection connection) { @Override public List executeList(CommandContext commandContext) { - // FIXME: handle filtering + // Search for users with a specific role + if (this.groupId != null) { + List users = new ArrayList<>(); + for (JsonValue user : getRoleMembers(this.groupId)) { + users.add(new IdmUser(user)); + } + return users; + } + + // Perform standard user search QueryRequest request = Requests.newQueryRequest("managed/user"); - request.setQueryId(WorkflowConstants.QUERY_ALL_IDS); - List result = new ArrayList<>(); - QueryResourceHandler handler = new UserQueryResourceHandler(result); try { - connection.query(context, request, handler); - return result; + applyQueryRequestParams(request); + } catch (BadRequestException e) { + throw new RuntimeException(e); + } + applyQueryRequestFields(request); + Collection users = new ArrayList<>(); + try { + connection.query(createInternalContext(), request, users); } catch (ResourceException e) { throw new RuntimeException(e); } + return users.stream() + .map(user -> new IdmUser(user.getContent())) + .collect(Collectors.toList()); } @Override public long executeCount(CommandContext commandContext) { - // FIXME: handle filtering - try { - QueryRequest request = Requests.newQueryRequest("managed/user"); - if (getId() == null) { - request.setQueryId(WorkflowConstants.QUERY_ALL_IDS); - } else { - request.setQueryId("for-userName"); - request.setAdditionalParameter("uid", getId()); - } - Collection result = new ArrayList<>(); - connection.query(context, request, result); - return result.size(); - } catch (ResourceException e) { - throw new RuntimeException(e); - } + return executeList(commandContext).size(); } @Override public User executeSingleResult(CommandContext commandContext) { - return readUser(getId()); + if (this.id == null) { + throw new UnsupportedOperationException("Single result only supported for ID based search"); + } + List users = executeList(commandContext); + return !users.isEmpty() ? users.get(0) : null; } - /** - * Read IdM user with the specified identifier (username). - */ - private User readUser(String id) { - try { - QueryRequest request = Requests.newQueryRequest("managed/user"); - request.setQueryId("for-userName"); - request.setAdditionalParameter("uid", id); - List users = new ArrayList<>(); - connection.query(context, request, users); - return !users.isEmpty() ? new IdmUser(users.get(0).getContent()) : null; - } catch (ResourceException e) { - throw new RuntimeException(e); + @Override + public UserQuery userId(String id) { + if (this.groupId != null) { + throw new ActivitiIllegalArgumentException("Invalid query usage: cannot set both memberOfGroup and userId"); } + return super.userId(id); + } + @Override + public UserQuery memberOfGroup(String groupId) { + if (this.id != null) { + throw new ActivitiIllegalArgumentException("Invalid query usage: cannot set both userId and memberOfGroup"); + } + return super.memberOfGroup(groupId); + } + + @Override + public UserQuery userIds(List ids) { + throw new UnsupportedOperationException("Filtering by userId is not supported"); } - private class UserQueryResourceHandler implements QueryResourceHandler { + @Override + public UserQuery userIdIgnoreCase(String id) { + throw new UnsupportedOperationException("Filtering by user userIdIgnoreCase is not supported"); + } - private final List users; + @Override + public UserQuery userFirstName(String firstName) { + throw new UnsupportedOperationException("Filtering by user firstName is not supported"); + } - public UserQueryResourceHandler(List users) { - this.users = users; + @Override + public UserQuery userFirstNameLike(String firstNameLike) { + throw new UnsupportedOperationException("Filtering by user firstNameLike is not supported"); + } + + @Override + public UserQuery userFirstNameLikeIgnoreCase(String firstNameLikeIgnoreCase) { + throw new UnsupportedOperationException("Filtering by user firstNameLikeIgnoreCase is not supported"); + } + + @Override + public UserQuery userLastName(String lastName) { + throw new UnsupportedOperationException("Filtering by user lastName is not supported"); + } + + @Override + public UserQuery userLastNameLike(String lastNameLike) { + throw new UnsupportedOperationException("Filtering by user lastNameLike is not supported"); + } + + @Override + public UserQuery userLastNameLikeIgnoreCase(String lastNameLikeIgnoreCase) { + throw new UnsupportedOperationException("Filtering by user lastNameLikeIgnoreCase is not supported"); + } + + @Override + public UserQuery userFullNameLike(String fullNameLike) { + throw new UnsupportedOperationException("Filtering by user fullNameLike is not supported"); + } + + @Override + public UserQuery userFullNameLikeIgnoreCase(String fullNameLikeIgnoreCase) { + throw new UnsupportedOperationException("Filtering by user fullNameLikeIgnoreCase is not supported"); + } + + @Override + public UserQuery userDisplayName(String displayName) { + throw new UnsupportedOperationException("Filtering by user displayName is not supported"); + } + + @Override + public UserQuery userDisplayNameLike(String displayNameLike) { + throw new UnsupportedOperationException("Filtering by user displayNameLike is not supported"); + } + + @Override + public UserQuery userDisplayNameLikeIgnoreCase(String displayNameLikeIgnoreCase) { + throw new UnsupportedOperationException("Filtering by user displayNameLikeIgnoreCase is not supported"); + } + + @Override + public UserQuery userEmail(String email) { + throw new UnsupportedOperationException("Filtering by user email is not supported"); + } + + @Override + public UserQuery userEmailLike(String emailLike) { + throw new UnsupportedOperationException("Filtering by user emailLike is not supported"); + } + + @Override + public UserQuery memberOfGroups(List groupIds) { + throw new UnsupportedOperationException("Filtering by user groupIds is not supported"); + } + + @Override + public UserQuery tenantId(String tenantId) { + throw new UnsupportedOperationException("Filtering by tenantId is not supported"); + } + + private JsonValue getRoleMembers(String roleId) { + ReadRequest request = Requests.newReadRequest("managed/role", roleId); + request.addField( + new JsonPointer(IdmIdentityService.MEMBERS_ATTR, "*", IdmIdentityService.ID_ATTR), + new JsonPointer(IdmIdentityService.MEMBERS_ATTR, "*", IdmIdentityService.USERNAME_ATTR), + new JsonPointer(IdmIdentityService.MEMBERS_ATTR, "*", IdmIdentityService.GIVEN_NAME_ATTR), + new JsonPointer(IdmIdentityService.MEMBERS_ATTR, "*", IdmIdentityService.SURNAME_ATTR), + new JsonPointer(IdmIdentityService.MEMBERS_ATTR, "*", IdmIdentityService.MAIL_ATTR) + ); + try { + ResourceResponse result = connection.read(createInternalContext(), request); + return result.getContent().get(IdmIdentityService.MEMBERS_ATTR); + } catch (NotFoundException e) { + return new JsonValue(null); + } catch (ResourceException e) { + throw new RuntimeException("Unable to fetch role members", e); } + } - @Override - public boolean handleResource(ResourceResponse resource) { - return users.add(readUser(resource.getContent().get(WorkflowConstants.RESOURCE_ID).asString())); + private void applyQueryRequestParams(QueryRequest request) throws BadRequestException { + if (this.id != null) { + request.setQueryId("for-userName"); + request.setAdditionalParameter("uid", this.id); } } + private void applyQueryRequestFields(QueryRequest request) { + request.addField( + IdmIdentityService.ID_ATTR, + IdmIdentityService.USERNAME_ATTR, + IdmIdentityService.GIVEN_NAME_ATTR, + IdmIdentityService.SURNAME_ATTR, + IdmIdentityService.MAIL_ATTR + ); + } + }