diff --git a/Dockerfile b/Dockerfile index edfda217d31ab3b56c56c63d395485e2ec1ac169..931828e197642753f48b22cc0d60f8065a48b03a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,13 @@ +# +# Copyright: DAASI International GmbH 2020-2020. All rights reserved. +# +# This is Open Source Software +# License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) +# +# Author: Tamim Ziai DAASI International GmbH, www.daasi.de +# For questions please mail to info@daasi.de +# + FROM maven:3-jdk-8-slim COPY ./pom.xml /usr/app/pom.xml COPY ./dockerconfig/.m2/settings.xml /root/.m2/settings.xml diff --git a/build-overlay.bat b/build-overlay.bat index 917b78ff979c7985abd38ed875fc60675aaa5e49..da0345e0669114ab69548c6f98d4d7d81b0516cf 100644 --- a/build-overlay.bat +++ b/build-overlay.bat @@ -1,3 +1,13 @@ +@REM +@REM Copyright: DAASI International GmbH 2020-2020. All rights reserved. +@REM +@REM This is Open Source Software +@REM License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) +@REM +@REM Author: Tamim Ziai DAASI International GmbH, www.daasi.de +@REM For questions please mail to info@daasi.de +@REM + docker build -t scim-overlay:tests -f midpoint-scim2-service-overlay\Dockerfile . docker run --name scim-overlay-tmp scim-overlay:tests rem docker rm scim-overlay-tmp \ No newline at end of file diff --git a/build-server.bat b/build-server.bat index fd3d73abba616c807c6dc080c0dc594b1c46ac22..e9c68b73bf3861a0bd5f599a7f8ad8bb9a2d023b 100644 --- a/build-server.bat +++ b/build-server.bat @@ -1,3 +1,13 @@ +@REM +@REM Copyright: DAASI International GmbH 2020-2020. All rights reserved. +@REM +@REM This is Open Source Software +@REM License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) +@REM +@REM Author: Tamim Ziai DAASI International GmbH, www.daasi.de +@REM For questions please mail to info@daasi.de +@REM + docker build -t scim-server:tests -f midpoint-scim2-service-server\Dockerfile . docker run --name scim-server-tmp scim-server:tests rem docker rm scim-overlay-tmp \ No newline at end of file diff --git a/midpoint-scim2-service-overlay/Dockerfile b/midpoint-scim2-service-overlay/Dockerfile index 405fad12e6350be0047f597054a8ed9b72847ffc..d3c322912d1f8c7c806cef03d85fa87664f842cd 100644 --- a/midpoint-scim2-service-overlay/Dockerfile +++ b/midpoint-scim2-service-overlay/Dockerfile @@ -1,3 +1,13 @@ +# +# Copyright: DAASI International GmbH 2020-2020. All rights reserved. +# +# This is Open Source Software +# License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) +# +# Author: Tamim Ziai DAASI International GmbH, www.daasi.de +# For questions please mail to info@daasi.de +# + FROM maven:3-jdk-8-slim as dependency-environment COPY ./pom.xml /usr/app/pom.xml COPY ./midpoint-scim2-service-overlay/pom.xml /usr/app/midpoint-scim2-service-overlay/pom.xml diff --git a/midpoint-scim2-service-overlay/pom.xml b/midpoint-scim2-service-overlay/pom.xml index ee27cf0f39b7940b1bc65ac64735e71a6a58f6eb..4b439515ab54461f0bff01882342338f6ec7a86a 100644 --- a/midpoint-scim2-service-overlay/pom.xml +++ b/midpoint-scim2-service-overlay/pom.xml @@ -1,5 +1,15 @@ <?xml version="1.0"?> +<!-- + Copyright: DAASI International GmbH 2020-2020. All rights reserved. + + This is Open Source Software + License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + + Author: Tamim Ziai DAASI International GmbH, www.daasi.de + For questions please mail to info@daasi.de + +--> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> @@ -11,7 +21,7 @@ <parent> <groupId>de.daasi</groupId> <artifactId>midpoint-scim2-service</artifactId> - <version>1.3-PREVIEW.1</version> + <version>1.3.1</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/midpoint-scim2-service-server/Dockerfile b/midpoint-scim2-service-server/Dockerfile index c854f3c7e3908e77a91848f279aeaa5834167645..da37a32420e0e5400837cbae45d87c9339068456 100644 --- a/midpoint-scim2-service-server/Dockerfile +++ b/midpoint-scim2-service-server/Dockerfile @@ -1,3 +1,13 @@ +# +# Copyright: DAASI International GmbH 2020-2020. All rights reserved. +# +# This is Open Source Software +# License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) +# +# Author: Tamim Ziai DAASI International GmbH, www.daasi.de +# For questions please mail to info@daasi.de +# + FROM maven:3-jdk-8-slim as dependency-environment COPY ./pom.xml /usr/app/pom.xml COPY ./midpoint-scim2-service-server/pom.xml /usr/app/midpoint-scim2-service-server/pom.xml diff --git a/midpoint-scim2-service-server/pom.xml b/midpoint-scim2-service-server/pom.xml index d3a3ad170352524202a4852ed40fc38631b5f878..a4873c87b943317a5147978343c9c256cb99981c 100644 --- a/midpoint-scim2-service-server/pom.xml +++ b/midpoint-scim2-service-server/pom.xml @@ -1,4 +1,15 @@ <?xml version="1.0"?> +<!-- + + Copyright: DAASI International GmbH 2020-2020. All rights reserved. + + This is Open Source Software + License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + + Author: Tamim Ziai DAASI International GmbH, www.daasi.de + For questions please mail to info@daasi.de + +--> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> @@ -10,7 +21,7 @@ <parent> <groupId>de.daasi</groupId> <artifactId>midpoint-scim2-service</artifactId> - <version>1.3-PREVIEW.1</version> + <version>1.3.1</version> <relativePath>../pom.xml</relativePath> </parent> diff --git a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/model/ExtendedQName.java b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/model/ExtendedQName.java index 040da37e0b6adcaf92efcf2efd5271fb610bb037..f85f8bce7b36e8b9728f64f4e099f10e9b0e33ee 100644 --- a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/model/ExtendedQName.java +++ b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/model/ExtendedQName.java @@ -1,3 +1,12 @@ +/** + * Copyright: DAASI International GmbH 2020-2020. All rights reserved. + * + * This is Open Source Software + * License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + * + * Author: Tamim Ziai DAASI International GmbH, www.daasi.de + * For questions please mail to info@daasi.de + */ package de.daasi.midpoint.scim2.service.model; import javax.xml.namespace.QName; diff --git a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebService.java b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebService.java index 889e377d693b4ae10ce32c49c236d13f76abd562..ccd85c12106c495f85a115d4201e14ec89b4dc4a 100644 --- a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebService.java +++ b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebService.java @@ -1,3 +1,12 @@ +/** + * Copyright: DAASI International GmbH 2020-2020. All rights reserved. + * + * This is Open Source Software + * License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + * + * Author: Tamim Ziai DAASI International GmbH, www.daasi.de + * For questions please mail to info@daasi.de + */ package de.daasi.midpoint.scim2.service.server; import static com.unboundid.scim2.common.utils.ApiConstants.MEDIA_TYPE_SCIM; @@ -15,7 +24,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; -import java.util.stream.Collectors; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -38,7 +46,6 @@ import javax.xml.datatype.DatatypeFactory; import javax.xml.datatype.XMLGregorianCalendar; import javax.xml.namespace.QName; -import com.unboundid.scim2.common.types.*; import org.apache.commons.configuration.Configuration; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.Validate; @@ -134,9 +141,17 @@ import com.unboundid.scim2.common.messages.PatchOpType; import com.unboundid.scim2.common.messages.PatchOperation; import com.unboundid.scim2.common.messages.PatchRequest; import com.unboundid.scim2.common.messages.SearchRequest; +import com.unboundid.scim2.common.types.Address; +import com.unboundid.scim2.common.types.AttributeDefinition; import com.unboundid.scim2.common.types.AttributeDefinition.Builder; import com.unboundid.scim2.common.types.AttributeDefinition.Type; import com.unboundid.scim2.common.types.AttributeDefinition.Uniqueness; +import com.unboundid.scim2.common.types.Email; +import com.unboundid.scim2.common.types.Meta; +import com.unboundid.scim2.common.types.Name; +import com.unboundid.scim2.common.types.ResourceTypeResource; +import com.unboundid.scim2.common.types.SchemaResource; +import com.unboundid.scim2.common.types.UserResource; import com.unboundid.scim2.common.utils.JsonUtils; import com.unboundid.scim2.common.utils.Parser; import com.unboundid.scim2.common.utils.SchemaUtils; @@ -145,10 +160,6 @@ import com.unboundid.scim2.server.annotations.ResourceType; import de.daasi.midpoint.scim2.service.model.ExtendedQName; import de.daasi.midpoint.scim2.service.utils.ExtendedUserResource; -/** - * @author Tamim Ziai - */ - /** * A per resource life cycle Resource Endpoint implementation. */ @@ -177,8 +188,6 @@ public class Scim2WebService extends AbstractModelWebService { private Map<ExtendedQName, ExtendedQName> toScimAttributesMapping; - private Map<ExtendedQName, ExtendedQName> shortAttribute; - private Map<QName, ItemDefinition<?>> extendedAttributes; private ExtendedQName identifierQName; @@ -189,7 +198,7 @@ public class Scim2WebService extends AbstractModelWebService { private String scimSchemas; - private ExtendedQName additionalMailsAttribute; + private ExtendedQName additionalEMailAttribute; @Autowired(required = true) protected ModelService modelService; @@ -221,7 +230,6 @@ public class Scim2WebService extends AbstractModelWebService { protected void init(UriInfo ui) { try { setBaseUri(ui.getBaseUri().toString()); - shortAttribute = null; getExtendedAttributes(); getFromScimAttributesMapping(); } catch (Scim2WebServiceException se) { @@ -238,7 +246,7 @@ public class Scim2WebService extends AbstractModelWebService { this.baseUri = getConfiguredBaseUri(baseUri); } } - + /** * Retrieves a user object by it's name. * @@ -250,32 +258,27 @@ public class Scim2WebService extends AbstractModelWebService { @Path("/Users/{id}") @GET @Produces({ MEDIA_TYPE_SCIM, MediaType.APPLICATION_JSON }) - public Response getUser(@PathParam("id") final String id, @QueryParam("attributes") final String attributes, - @QueryParam("excludedAttributes") final String excludedAttributes, @Context UriInfo ui) throws ScimException { + public Response getUser(@PathParam("id") final String id, + @QueryParam("attributes") final String attributes, + @QueryParam("excludedAttributes") final String excludedAttributes, + @Context UriInfo ui) { Validate.notEmpty(id, "No id in person"); init(ui); Response response; - if (attributes != null || excludedAttributes != null) { - if (attributes != null && excludedAttributes != null) { - LOGGER.error("query parameters attributes and excludedAttributes are mutually exclusive"); - response = buildScimError(Status.BAD_REQUEST, "query parameters attributes and excludedAttributes are mutually exclusive", null); - return response; - } - else buildAttributeMapCopy(attributes, excludedAttributes); - } final String OPERATION_NAME = "getUser"; Task task = createTaskInstance(Scim2WebService.class.getName() + OPERATION_NAME); auditLogin(task); OperationResult result = task.getResult(); - try { + Map<ExtendedQName, ExtendedQName> mappingSubSet = buildAttributeMappingSubset(attributes, excludedAttributes); + PrismObject<UserType> userType = getUser(id, task, result); if (userType != null) { - UserResource resource = mapToUserResource(userType); + UserResource resource = mapToUserResource(userType, mappingSubSet ); LOGGER.debug("returning:\n{}", resource); response = Response.status(Status.OK).header("Location", getUserLocationUri(userType.getOid())) @@ -302,50 +305,74 @@ public class Scim2WebService extends AbstractModelWebService { } /** - * Builds a copy of the ToScimAttributesMapping Map with the specified - * Attributes. - * + * Builds a copy of the ToScimAttributesMapping Map with the specified Attributes. + * If both given attributes are null or empty null is returned. If both are not empty an exception is thrown. * @param attributes A coma separated list in a string containing the wanted attributes * @param excludedAttributes A coma separated list in a string containing the attributes to be excluded */ - private void buildAttributeMapCopy(String attributes, String excludedAttributes) { - - if (attributes != null) { - try { - if (attributes.contains("emails")) { - attributes = attributes + "," + getToScimAttributesMapping().get(getConfiguredAdditionalMailsAttribute()).getLocalPart(); - } - String[] trimmedAttributes = attributes.replace("\"", "").split(","); - shortAttribute = new HashMap<>(); + private Map<ExtendedQName, ExtendedQName> buildAttributeMappingSubset(String attributes, String excludedAttributes) throws Scim2WebServiceException { - for (ExtendedQName key : getFromScimAttributesMapping().keySet()) { - for (String trimmedAttribute : trimmedAttributes) { - if (key.getLocalPart().startsWith(trimmedAttribute)) { - shortAttribute.put(getFromScimAttributesMapping().get(key), key); - } - } - } - } catch (Scim2WebServiceException e) { - e.printStackTrace(); - } + if( StringUtils.isBlank( attributes ) && StringUtils.isBlank( excludedAttributes ) ) { + return null; + } + + if (StringUtils.isNotBlank( attributes ) && StringUtils.isNotBlank( excludedAttributes )) { + throw new Scim2WebServiceBadRequestException( "Parameters attributes and excludedAttributes are mutually exclusive", null); + } + + if (StringUtils.isNotBlank( attributes )) { + return buildAttributeMappingSubsetFromAttributes(attributes, false); } else { - try { - if (excludedAttributes.contains("emails")) { - excludedAttributes = excludedAttributes + "," + getToScimAttributesMapping().get(getConfiguredAdditionalMailsAttribute()).getLocalPart(); - } - String[] trimmedExcludedAttributes = excludedAttributes.replace("\"", "").split(","); - shortAttribute = getToScimAttributesMapping().entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, Entry::getValue)); + return buildAttributeMappingSubsetFromAttributes(excludedAttributes, true); + } + } + + /** + * Helper for buildAttributeMappingSubset + * @param attributes either excludedAttributes- or attributes-String depending on boolean exclude + * @param exclude tells if attributes should be excluded (true) or added (false) to the returned mapping + * @return + * @throws Scim2WebServiceException + */ + private Map<ExtendedQName, ExtendedQName> buildAttributeMappingSubsetFromAttributes(String attributes, boolean exclude) throws Scim2WebServiceException { + try { + if (attributes.contains("emails")) { + attributes = attributes + "," + getToScimAttributesMapping().get(getConfiguredAdditionalEMailAttribute()).getLocalPart(); + } + String[] trimmedAttributes = attributes.replace("\"", "").split(","); + Map<ExtendedQName, ExtendedQName> mapping = new HashMap<>(); + if(exclude) { + mapping.putAll( getToScimAttributesMapping() ); + } + for (String trimmedAttribute : trimmedAttributes) { + boolean found = false; for (ExtendedQName key : getFromScimAttributesMapping().keySet()) { - for (String trimmedAttribute : trimmedExcludedAttributes) { - if (key.getLocalPart().startsWith(trimmedAttribute)) { - shortAttribute.remove(getFromScimAttributesMapping().get(key)); + if( LOGGER.isDebugEnabled() ) { + LOGGER.debug( "Checking local name {} against attribute {}", key.getLocalPart(), trimmedAttribute ); + } + if (key.getLocalPart().equalsIgnoreCase(trimmedAttribute)) { + if(exclude) { + mapping.remove(getFromScimAttributesMapping().get(key)); + } + else { + mapping.put(getFromScimAttributesMapping().get(key), key); } + found = true; + break; } } - } catch (Scim2WebServiceException e) { - e.printStackTrace(); + if( !found ) { + throw new Scim2WebServiceBadRequestException( "Attribute " + trimmedAttribute + " is unknown", "invalidAttribute" ); + } } + + return mapping; + } catch (Scim2WebServiceBadRequestException e ) { + throw e; + } catch (Scim2WebServiceException e) { + //This was swallowed previously. why? + throw e; } } @@ -375,8 +402,11 @@ public class Scim2WebService extends AbstractModelWebService { try { resource = JsonUtils.getObjectReader().forType(SearchRequest.class).readValue(payload); LOGGER.debug("search resource: {}", resource); + String attributes = ( resource.getAttributes() == null || resource.getAttributes().isEmpty() ) ? null : StringUtils.join( resource.getAttributes(), ',' ); + String excludedAttributes = ( resource.getExcludedAttributes() == null || resource.getExcludedAttributes().isEmpty() ) ? null : StringUtils.join( resource.getExcludedAttributes(), ',' ); response = searchUser(resource.getFilter(), resource.getStartIndex(), resource.getCount(), - resource.getSortBy(), resource.getSortBy(), ui); + resource.getSortBy(), resource.getSortBy(), + attributes, excludedAttributes, ui); } catch (JsonProcessingException e) { LOGGER.warn(e.getMessage(), e); response = buildScimError(Status.BAD_REQUEST, e.getMessage(), null); @@ -402,8 +432,12 @@ public class Scim2WebService extends AbstractModelWebService { @GET @Produces({ MEDIA_TYPE_SCIM, MediaType.APPLICATION_JSON }) public Response searchUser(@QueryParam("filter") final String filter, - @QueryParam("startIndex") final Integer startIndex, @QueryParam("count") final Integer count, - @QueryParam("sortBy") final String sortBy, @QueryParam("sortOrder") final String sortOrder, + @QueryParam("startIndex") final Integer startIndex, + @QueryParam("count") final Integer count, + @QueryParam("sortBy") final String sortBy, + @QueryParam("sortOrder") final String sortOrder, + @QueryParam("attributes") final String attributes, + @QueryParam("excludedAttributes") final String excludedAttributes, @Context UriInfo ui) throws ScimException { StopWatch sw = StopWatch.createStarted(); init(ui); @@ -437,12 +471,21 @@ public class Scim2WebService extends AbstractModelWebService { response = buildScimError(Status.BAD_REQUEST, "Sort order must be either 'ascending' or 'descending'", null); } + Map<ExtendedQName, ExtendedQName> mappingSubSet = null; + if( response.getStatus() == Status.OK.getStatusCode() ) { + try { + mappingSubSet = buildAttributeMappingSubset(attributes, excludedAttributes); + } catch ( Scim2WebServiceException se ) { + LOGGER.warn(se.getMessage(), se); + response = buildScimError(se.getStatus(), se.getMessage(), se.getScimDetail()); + } + } if (response.getStatus() == Status.OK.getStatusCode()) { LOGGER.debug("Filter = {}", scimFilter); response.close(); try { - String body = buildSearchResult(startIndex, count, sortBy, sortOrder, scimFilter, task, result); + String body = buildSearchResult(startIndex, count, sortBy, sortOrder, scimFilter, mappingSubSet, task, result); response = Response.status(Status.OK).entity(body).build(); } catch (Scim2WebServiceException se) { LOGGER.warn(se.getMessage(), se); @@ -709,6 +752,7 @@ public class Scim2WebService extends AbstractModelWebService { * @param sortBy attribute to sort by * @param sortOrder sort order * @param scimFilter The SCIM filter to search for + * @param mappingSubSet an eventually computed subset of the complete mapping. may be null * @param task task instance * @param result operation result * @return The result as SCIM2 search result @@ -717,7 +761,7 @@ public class Scim2WebService extends AbstractModelWebService { * @throws Scim2WebServiceException */ protected String buildSearchResult(Integer startIndex, Integer itemsPerPage, String sortBy, String sortOrder, - Filter scimFilter, Task task, OperationResult result) + Filter scimFilter, Map<ExtendedQName, ExtendedQName> mappingSubSet, Task task, OperationResult result) throws ScimException, CommonException, Scim2WebServiceException { StopWatch sw = StopWatch.createStarted(); @@ -754,7 +798,7 @@ public class Scim2WebService extends AbstractModelWebService { List<UserResource> resources = new ArrayList<UserResource>(); if (itemsPerPage > 0) { for (PrismObject<UserType> user : users) { - UserResource resource = mapToUserResource(user); + UserResource resource = mapToUserResource(user, mappingSubSet ); resources.add(resource); } } @@ -879,7 +923,7 @@ public class Scim2WebService extends AbstractModelWebService { .getObjectDelta().getObjectToAdd(); // Return the created object - resource = mapToUserResource(createdUserType); + resource = mapToUserResource(createdUserType, null); LOGGER.debug("returning:\n{}", resource); response = Response.status(Status.CREATED).header("Location", getUserLocationUri(userType.getOid())) @@ -973,7 +1017,7 @@ public class Scim2WebService extends AbstractModelWebService { userType = getUser(userType.getOid(), task, result); } // Return the modified object - resource = mapToUserResource(userType); + resource = mapToUserResource(userType, null); LOGGER.debug("returning:\n{}", resource); response = Response.status(Status.OK).header("Location", getUserLocationUri(userType.getOid())) @@ -1046,7 +1090,7 @@ public class Scim2WebService extends AbstractModelWebService { PrismObject<UserType> modifiedUserType = getUser(userType.getOid(), task, result); // Return the modified object - UserResource resource = mapToUserResource(modifiedUserType); + UserResource resource = mapToUserResource(modifiedUserType, null); LOGGER.debug("returning:\n{}", resource); response = Response.status(Status.OK).header("Location", getUserLocationUri(userType.getOid())) @@ -1119,7 +1163,7 @@ public class Scim2WebService extends AbstractModelWebService { } if (!nonPrimaryValues.isEmpty()) { nonPrimaryPair = new ImmutablePair<QName, List<Object>>( - getConfiguredAdditionalMailsAttribute(), nonPrimaryValues); + getConfiguredAdditionalEMailAttribute(), nonPrimaryValues); userModifyDeltaAdd = addModifyDelta(oid, userModifyDeltaAdd, opType, nonPrimaryPair, true); } @@ -1685,11 +1729,12 @@ public class Scim2WebService extends AbstractModelWebService { * Converts PrismObject<UserType> to UserResource * * @param user user object of type PrismObject<UserType> + * @param mappingSubSet an eventually computed subset of the complete mapping. may be null * @return UserResource * @throws ScimException * @throws Scim2WebServiceException */ - protected UserResource mapToUserResource(PrismObject<UserType> user) + protected UserResource mapToUserResource(PrismObject<UserType> user, Map<ExtendedQName, ExtendedQName> mappingSubSet) throws ScimException, Scim2WebServiceException { UserType userType = user.asObjectable(); UserResource resource = new UserResource(); @@ -1699,10 +1744,10 @@ public class Scim2WebService extends AbstractModelWebService { items.add(oid); for (Item<?, ?> item : items) { QName qName = item.getElementName(); - if (shortAttribute == null || shortAttribute.containsKey(qName)) { + if (mappingSubSet == null || mappingSubSet.containsKey(qName)) { if (qName.equals(UserType.F_EMAIL_ADDRESS)) { addMailToResource(resource, item, true); - } else if (item.getElementName().equals(getConfiguredAdditionalMailsAttribute())) { + } else if (item.getElementName().equals(getConfiguredAdditionalEMailAttribute())) { addMailToResource(resource, item, false); } else if (getToScimAttributesMapping().containsKey(qName)) { updateResource(resource, item, userType); @@ -1715,12 +1760,12 @@ public class Scim2WebService extends AbstractModelWebService { if (asPrismContainerValue != null && asPrismContainerValue.getItems() != null) { for (Item<?, ?> item : asPrismContainerValue.getItems()) { if (asPrismContainerValue.contains(item)) { - if (shortAttribute == null || shortAttribute.containsKey(item.getElementName())){ + if (mappingSubSet == null || mappingSubSet.containsKey(item.getElementName())){ if (item.getElementName() - .equals(getConfiguredAdditionalMailsAttribute())) { + .equals(getConfiguredAdditionalEMailAttribute())) { addMailToResource(resource, item, false); } - // TODO should be concidered to map additional mails also in custom + // TODO should be considered to map additional mails also in custom // attribute? else { updateResource(resource, item, userType); @@ -1889,7 +1934,7 @@ public class Scim2WebService extends AbstractModelWebService { && nextEmail.getPrimary()) { addItemToUser(user, getQName("emails"), nextEmail.getValue()); } else { - addItemToUser(user, getConfiguredAdditionalMailsAttribute(), + addItemToUser(user, getConfiguredAdditionalEMailAttribute(), nextEmail.getValue()); } } @@ -2317,7 +2362,7 @@ public class Scim2WebService extends AbstractModelWebService { // handle emails if (scimAttr.equals("emails")) { ObjectFilter additionalFilter = createSimpleObjectFilter( - getConfiguredAdditionalMailsAttribute(), value, op); + getConfiguredAdditionalEMailAttribute(), value, op); List<ObjectFilter> combinedFilters = new ArrayList<ObjectFilter>(); combinedFilters.add(objectFilter); combinedFilters.add(additionalFilter); @@ -2591,20 +2636,20 @@ public class Scim2WebService extends AbstractModelWebService { * Retruns the configured additional mails attribute * @return configured mails attribute or null of not configured */ - protected QName getConfiguredAdditionalMailsAttribute() { - if (this.additionalMailsAttribute == null) { + protected QName getConfiguredAdditionalEMailAttribute() { + if (this.additionalEMailAttribute == null) { if (this.configuration != null) { Configuration config = configuration.getConfiguration("midpoint.scim2Service"); if (config == null) { LOGGER.warn("No configuration available."); } else { - String confUrn = config.getString("additionalMailsAttribute"); - additionalMailsAttribute = buildMapping(confUrn, ""); - LOGGER.info("Set additionalMailsAttribute to {}", additionalMailsAttribute); + String confUrn = config.getString("additionalEMailAttribute"); + additionalEMailAttribute = buildMapping(confUrn, ""); + LOGGER.info("Set additionalEMailAttribute to {}", additionalEMailAttribute); } } } - return this.additionalMailsAttribute; + return this.additionalEMailAttribute; } /** diff --git a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceBadRequestException.java b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceBadRequestException.java index f880783676a0dfaa7abd51ef6dfb1eb004f15ac6..d151ceca8afce0a9de37e63ef52f8c02607bc842 100644 --- a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceBadRequestException.java +++ b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceBadRequestException.java @@ -1,3 +1,12 @@ +/** + * Copyright: DAASI International GmbH 2020-2020. All rights reserved. + * + * This is Open Source Software + * License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + * + * Author: Tamim Ziai DAASI International GmbH, www.daasi.de + * For questions please mail to info@daasi.de + */ package de.daasi.midpoint.scim2.service.server; import javax.ws.rs.core.Response.Status; diff --git a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceException.java b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceException.java index 9d831eae5b497b6b832d4e7222ce4645dac3004d..38806fa3e1c666d9154a4a62dab06a041cdceb7a 100644 --- a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceException.java +++ b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceException.java @@ -1,3 +1,12 @@ +/** + * Copyright: DAASI International GmbH 2020-2020. All rights reserved. + * + * This is Open Source Software + * License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + * + * Author: Tamim Ziai DAASI International GmbH, www.daasi.de + * For questions please mail to info@daasi.de + */ package de.daasi.midpoint.scim2.service.server; import javax.ws.rs.core.Response.StatusType; @@ -32,7 +41,11 @@ public abstract class Scim2WebServiceException extends Exception { @Override public String getMessage() { - return new StringBuilder( getScimDetail() ).append( " : " ).append( super.getMessage() ).toString(); + StringBuilder sb = new StringBuilder(); + if( getScimDetail() != null ) { + sb.append( getScimDetail() ).append( " : " ); + } + return sb.append( super.getMessage() ).toString(); } @Override diff --git a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceInternalErrorException.java b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceInternalErrorException.java index f12fadba96992d51cb05e7f7abf8b83438f760c5..2d5c6b611aeff1bfaa9203ce115059f7e2fa127e 100644 --- a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceInternalErrorException.java +++ b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceInternalErrorException.java @@ -1,3 +1,12 @@ +/** + * Copyright: DAASI International GmbH 2020-2020. All rights reserved. + * + * This is Open Source Software + * License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + * + * Author: Tamim Ziai DAASI International GmbH, www.daasi.de + * For questions please mail to info@daasi.de + */ package de.daasi.midpoint.scim2.service.server; import javax.ws.rs.core.Response.Status; diff --git a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceNotSupportedException.java b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceNotSupportedException.java index d29c3d07db3ec2fcb352a24b82775688e31aa2da..67fcad7598e32e1fa6f3e4a38ab018e65db8c7c8 100644 --- a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceNotSupportedException.java +++ b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceNotSupportedException.java @@ -1,3 +1,12 @@ +/** + * Copyright: DAASI International GmbH 2020-2020. All rights reserved. + * + * This is Open Source Software + * License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + * + * Author: Tamim Ziai DAASI International GmbH, www.daasi.de + * For questions please mail to info@daasi.de + */ package de.daasi.midpoint.scim2.service.server; import javax.ws.rs.core.Response.Status; diff --git a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceNotUniqueException.java b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceNotUniqueException.java index 36e8cdd0fb5cec1ed6dbd34377a1974ad17752cb..c10c22039cd63a18d6681b5c505bddf4c4cfdf7f 100644 --- a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceNotUniqueException.java +++ b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceNotUniqueException.java @@ -1,3 +1,12 @@ +/** + * Copyright: DAASI International GmbH 2020-2020. All rights reserved. + * + * This is Open Source Software + * License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + * + * Author: Tamim Ziai DAASI International GmbH, www.daasi.de + * For questions please mail to info@daasi.de + */ package de.daasi.midpoint.scim2.service.server; import javax.ws.rs.core.Response.Status; diff --git a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceUnprocessableEntryException.java b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceUnprocessableEntryException.java index d7adcc1fc2b6c96ea8eaa51bd02aa98228834100..e0b3d8fb588f3f6ffd2ac244032fa39fdba5cbc0 100644 --- a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceUnprocessableEntryException.java +++ b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceUnprocessableEntryException.java @@ -1,3 +1,12 @@ +/** + * Copyright: DAASI International GmbH 2020-2020. All rights reserved. + * + * This is Open Source Software + * License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + * + * Author: Tamim Ziai DAASI International GmbH, www.daasi.de + * For questions please mail to info@daasi.de + */ package de.daasi.midpoint.scim2.service.server; public class Scim2WebServiceUnprocessableEntryException extends Scim2WebServiceException { diff --git a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/UnprocessableEntryStatus.java b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/UnprocessableEntryStatus.java index 3e0c7d7d128cb30c2b674c5747f817ac18a9bf05..935f49a62208262ab93902858092993be163becd 100644 --- a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/UnprocessableEntryStatus.java +++ b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/UnprocessableEntryStatus.java @@ -1,3 +1,12 @@ +/** + * Copyright: DAASI International GmbH 2020-2020. All rights reserved. + * + * This is Open Source Software + * License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + * + * Author: Tamim Ziai DAASI International GmbH, www.daasi.de + * For questions please mail to info@daasi.de + */ package de.daasi.midpoint.scim2.service.server; import javax.ws.rs.core.Response.Status.Family; diff --git a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/XMLGregorianCalendarMatchingRule.java b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/XMLGregorianCalendarMatchingRule.java index add9df478eec61fb6be0e63f176d9f5c14def0e7..e7baf3f5a629ec27ef91bda16c0c79a9b4376539 100644 --- a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/XMLGregorianCalendarMatchingRule.java +++ b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/server/XMLGregorianCalendarMatchingRule.java @@ -1,3 +1,12 @@ +/** + * Copyright: DAASI International GmbH 2020-2020. All rights reserved. + * + * This is Open Source Software + * License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + * + * Author: Tamim Ziai DAASI International GmbH, www.daasi.de + * For questions please mail to info@daasi.de + */ package de.daasi.midpoint.scim2.service.server; import java.util.regex.Pattern; diff --git a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/utils/ExtendedUserResource.java b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/utils/ExtendedUserResource.java index 7590bf0526bf9cda3cd7cee2dac31e923e7bcc27..9b7c7a3ac57e7e9723bb7d7a5a46a4eaf842ce75 100644 --- a/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/utils/ExtendedUserResource.java +++ b/midpoint-scim2-service-server/src/main/java/de/daasi/midpoint/scim2/service/utils/ExtendedUserResource.java @@ -1,3 +1,12 @@ +/** + * Copyright: DAASI International GmbH 2020-2020. All rights reserved. + * + * This is Open Source Software + * License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + * + * Author: Tamim Ziai DAASI International GmbH, www.daasi.de + * For questions please mail to info@daasi.de + */ package de.daasi.midpoint.scim2.service.utils; import java.util.List; diff --git a/midpoint-scim2-service-server/src/test/java/de/daasi/midpoint/scim2/service/server/MockTask.java b/midpoint-scim2-service-server/src/test/java/de/daasi/midpoint/scim2/service/server/MockTask.java index bc17a8432dd21d3d602b34fd34a41fa176a2e33f..74a038e193cea004ff9fd03987b0cfeae48dbea2 100644 --- a/midpoint-scim2-service-server/src/test/java/de/daasi/midpoint/scim2/service/server/MockTask.java +++ b/midpoint-scim2-service-server/src/test/java/de/daasi/midpoint/scim2/service/server/MockTask.java @@ -1,3 +1,12 @@ +/** + * Copyright: DAASI International GmbH 2020-2020. All rights reserved. + * + * This is Open Source Software + * License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + * + * Author: Tamim Ziai DAASI International GmbH, www.daasi.de + * For questions please mail to info@daasi.de + */ package de.daasi.midpoint.scim2.service.server; import java.util.Collection; diff --git a/midpoint-scim2-service-server/src/test/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceTest.java b/midpoint-scim2-service-server/src/test/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceTest.java index b27ab70818f2a93d0245bbc3e2ed6db0eb234125..b8a2b23b878317e85649ba7a935de55c9ffe156c 100644 --- a/midpoint-scim2-service-server/src/test/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceTest.java +++ b/midpoint-scim2-service-server/src/test/java/de/daasi/midpoint/scim2/service/server/Scim2WebServiceTest.java @@ -1,3 +1,12 @@ +/** + * Copyright: DAASI International GmbH 2020-2020. All rights reserved. + * + * This is Open Source Software + * License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + * + * Author: Tamim Ziai DAASI International GmbH, www.daasi.de + * For questions please mail to info@daasi.de + */ package de.daasi.midpoint.scim2.service.server; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -175,7 +184,7 @@ public class Scim2WebServiceTest { assertNotNull(response.getHeaders().get("Location")); assertEquals(service.getUserLocationUri(userType.getOid()), response.getHeaders().get("Location").get(0)); assertEquals(response.getEntity().toString(), - service.mapToUserResource(userType).toString()); + service.mapToUserResource(userType, null).toString()); } @Test @@ -231,19 +240,19 @@ public class Scim2WebServiceTest { @Test public void when_searchUser_filter_bad_attribute() throws ScimException, CommonException { - Response response = service.searchUser("blaBlub sw \"u\"", null, null, null, null, ui); + Response response = service.searchUser("blaBlub sw \"u\"", null, null, null, null, null, null, ui); assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus()); } @Test public void when_searchUser_filter_bad_operator() throws ScimException, CommonException { - Response response = service.searchUser("userName xx \"u\"", null, null, null, null, ui); + Response response = service.searchUser("userName xx \"u\"", null, null, null, null, null, null, ui); assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus()); } @Test public void when_searchUser_filter_no_operator() throws ScimException, CommonException { - Response response = service.searchUser("userName", null, null, null, null, ui); + Response response = service.searchUser("userName", null, null, null, null, null, null, ui); assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus()); } @@ -267,7 +276,7 @@ public class Scim2WebServiceTest { @Test public void when_createUser() throws ScimException, CommonException, Scim2WebServiceException { PrismObject<UserType> userType = buildUserType(1L, "user1"); - UserResource resource = service.mapToUserResource(userType); + UserResource resource = service.mapToUserResource(userType, null); Collection<ObjectDeltaOperation<? extends ObjectType>> results = new SearchResultList<ObjectDeltaOperation<? extends ObjectType>>(); ObjectDeltaOperation<UserType> deltaOperation = new ObjectDeltaOperation<UserType>(); ObjectDelta<UserType> delta = new ObjectDelta<UserType>(UserType.class, ChangeType.ADD, prismContext); @@ -288,7 +297,7 @@ public class Scim2WebServiceTest { @Test public void when_createUser_already_exists() throws ScimException, CommonException, Scim2WebServiceException { PrismObject<UserType> userType = buildUserType(1L, "user1"); - UserResource resource = service.mapToUserResource(userType); + UserResource resource = service.mapToUserResource(userType, null); Mockito.when(modelService.executeChanges(Mockito.any(), Mockito.any(), Mockito.any(), Mockito.any())).thenThrow(new ObjectAlreadyExistsException()); Mockito.when(service.getQName("emails")).thenReturn(new ExtendedQName("http://midpoint.evolveum.com/xml/ns/public/common/common-3", "emailAddress")); @@ -314,7 +323,7 @@ public class Scim2WebServiceTest { Mockito.doNothing().when(service).addDelta(Mockito.any(), Mockito.any(), Mockito.any()); Mockito.doNothing().when(service).addActivationModification(Mockito.any(), Mockito.any()); - UserResource resource = service.mapToUserResource(modifyUserType); + UserResource resource = service.mapToUserResource(modifyUserType, null); Collection<ObjectDeltaOperation<? extends ObjectType>> results = new SearchResultList<ObjectDeltaOperation<? extends ObjectType>>(); ObjectDeltaOperation<UserType> deltaOperation = new ObjectDeltaOperation<UserType>(); ObjectDelta<UserType> delta = new ObjectDelta<UserType>(UserType.class, ChangeType.ADD, prismContext); @@ -326,7 +335,7 @@ public class Scim2WebServiceTest { String payload = resource.toString(); Response response = service.modifyUser("1", payload , ui); - resource = service.mapToUserResource(userType); + resource = service.mapToUserResource(userType, null); payload = resource.toString(); assertEquals(Status.OK.getStatusCode(), response.getStatus()); assertNotNull(response.getHeaders().get("Location")); @@ -340,7 +349,7 @@ public class Scim2WebServiceTest { Mockito.when(modelService.getObject(Mockito.eq(UserType.class), Mockito.eq("1"), Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(null); - UserResource resource = service.mapToUserResource(modifyUserType); + UserResource resource = service.mapToUserResource(modifyUserType, null); String payload = resource.toString(); Response response = service.modifyUser("1", payload , ui); assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); @@ -371,7 +380,7 @@ public class Scim2WebServiceTest { Mockito.doReturn(objectDelta).when(service).createModificationReplaceProperty(Mockito.any(), Mockito.any(), Mockito.any()); Mockito.doReturn(objectDelta).when(service).createModificationDeleteProperty(Mockito.any(), Mockito.any(), Mockito.any()); - UserResource resource = service.mapToUserResource(modifyUserType); + UserResource resource = service.mapToUserResource(modifyUserType, null); Collection<ObjectDeltaOperation<? extends ObjectType>> results = new SearchResultList<ObjectDeltaOperation<? extends ObjectType>>(); ObjectDeltaOperation<UserType> deltaOperation = new ObjectDeltaOperation<UserType>(); ObjectDelta<UserType> delta = new ObjectDelta<UserType>(UserType.class, ChangeType.ADD, prismContext); @@ -383,7 +392,7 @@ public class Scim2WebServiceTest { String payload = patchRequest.toString(); Response response = service.patchUser("1", payload , ui); - resource = service.mapToUserResource(userType); + resource = service.mapToUserResource(userType, null); payload = resource.toString(); assertEquals(Status.NO_CONTENT.getStatusCode(), response.getStatus()); assertNotNull(response.getHeaders().get("Location")); @@ -428,7 +437,7 @@ public class Scim2WebServiceTest { Mockito.when(modelService.getObject(Mockito.eq(UserType.class), Mockito.eq("1"), Mockito.any(), Mockito.any(), Mockito.any())).thenReturn(null); - UserResource resource = service.mapToUserResource(modifyUserType); + UserResource resource = service.mapToUserResource(modifyUserType, null); String payload = resource.toString(); Response response = service.patchUser("1", payload , ui); assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus()); diff --git a/pom.xml b/pom.xml index 9e87ba7a58f404d6400d5f96afe9a95a9e654a57..5e9ce743656100f35c5e7017df59290a58b1b739 100644 --- a/pom.xml +++ b/pom.xml @@ -1,5 +1,15 @@ <?xml version="1.0"?> +<!-- + Copyright: DAASI International GmbH 2020-2020. All rights reserved. + + This is Open Source Software + License: Apache 2.0 (https://www.apache.org/licenses/LICENSE-2.0) + + Author: Tamim Ziai DAASI International GmbH, www.daasi.de + For questions please mail to info@daasi.de + +--> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> @@ -7,9 +17,15 @@ <name>midPoint scim2 Service</name> <groupId>de.daasi</groupId> <artifactId>midpoint-scim2-service</artifactId> - <version>1.3-PREVIEW.1</version> + <version>1.3.1</version> <packaging>pom</packaging> <description>A midPoint overlay project that implements a scim2 web service</description> + + <parent> + <groupId>de.daasi</groupId> + <artifactId>didmos2-maven-parent</artifactId> + <version>1.1.0</version> + </parent> <repositories> <repository> @@ -22,6 +38,11 @@ <name>Gluu repository</name> <url>http://ox.gluu.org/maven</url> </repository> + <repository> + <id>daasi</id> + <name>DAASI-Test-repo</name> + <url>https://nexus.daasi.de/repository/maven-public/</url> + </repository> </repositories> <properties>