http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java new file mode 100644 index 0000000..d15d30b --- /dev/null +++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMDataBinder.java @@ -0,0 +1,394 @@ +/* + * 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.core.logic; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.apache.commons.lang3.StringUtils; +import org.apache.syncope.common.lib.EntityTOUtils; +import org.apache.syncope.common.lib.SyncopeConstants; +import org.apache.syncope.common.lib.scim.SCIMComplexConf; +import org.apache.syncope.common.lib.scim.SCIMConf; +import org.apache.syncope.common.lib.to.AttrTO; +import org.apache.syncope.common.lib.to.GroupTO; +import org.apache.syncope.common.lib.to.UserTO; +import org.apache.syncope.core.logic.scim.SCIMConfManager; +import org.apache.syncope.core.persistence.api.dao.AnyDAO; +import org.apache.syncope.core.persistence.api.dao.search.MembershipCond; +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.spring.security.AuthDataAccessor; +import org.apache.syncope.ext.scimv2.api.data.Value; +import org.apache.syncope.ext.scimv2.api.data.Group; +import org.apache.syncope.ext.scimv2.api.data.Member; +import org.apache.syncope.ext.scimv2.api.data.Meta; +import org.apache.syncope.ext.scimv2.api.data.SCIMComplexValue; +import org.apache.syncope.ext.scimv2.api.data.SCIMEnterpriseInfo; +import org.apache.syncope.ext.scimv2.api.data.SCIMGroup; +import org.apache.syncope.ext.scimv2.api.data.SCIMUser; +import org.apache.syncope.ext.scimv2.api.data.SCIMUserAddress; +import org.apache.syncope.ext.scimv2.api.data.SCIMUserManager; +import org.apache.syncope.ext.scimv2.api.data.SCIMUserName; +import org.apache.syncope.ext.scimv2.api.type.Function; +import org.apache.syncope.ext.scimv2.api.type.Resource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +@Component +public class SCIMDataBinder { + + protected static final Logger LOG = LoggerFactory.getLogger(SCIMDataBinder.class); + + @Autowired + private SCIMConfManager confManager; + + @Autowired + private UserLogic userLogic; + + @Autowired + private AuthDataAccessor authDataAccessor; + + private <E extends Enum<?>> void fill( + final Map<String, AttrTO> attrs, + final List<SCIMComplexConf<E>> confs, + final List<SCIMComplexValue> values) { + + confs.forEach(conf -> { + SCIMComplexValue value = new SCIMComplexValue(); + + if (conf.getValue() != null && attrs.containsKey(conf.getValue())) { + value.setValue(attrs.get(conf.getValue()).getValues().get(0)); + } + if (conf.getDisplay() != null && attrs.containsKey(conf.getDisplay())) { + value.setDisplay(attrs.get(conf.getDisplay()).getValues().get(0)); + } + if (conf.getType() != null) { + value.setType(conf.getType().name()); + } + if (conf.isPrimary()) { + value.setPrimary(true); + } + + if (!value.isEmpty()) { + values.add(value); + } + }); + } + + public SCIMUser toSCIMUser(final UserTO userTO, final String location) { + SCIMConf conf = confManager.get(); + + SCIMUser user = new SCIMUser( + userTO.getKey(), + Collections.singletonList(Resource.User.schema()), + new Meta( + Resource.User, + userTO.getCreationDate(), + userTO.getLastChangeDate() == null + ? userTO.getCreationDate() : userTO.getLastChangeDate(), + userTO.getETagValue(), + location), + userTO.getUsername(), + !userTO.isSuspended()); + + Map<String, AttrTO> attrs = new HashMap<>(); + attrs.putAll(EntityTOUtils.buildAttrMap(userTO.getPlainAttrs())); + attrs.putAll(EntityTOUtils.buildAttrMap(userTO.getDerAttrs())); + attrs.putAll(EntityTOUtils.buildAttrMap(userTO.getVirAttrs())); + + if (conf.getUserConf() != null) { + if (conf.getUserConf().getName() != null) { + SCIMUserName name = new SCIMUserName(); + + if (conf.getUserConf().getName().getFamilyName() != null + && attrs.containsKey(conf.getUserConf().getName().getFamilyName())) { + + name.setFamilyName(attrs.get(conf.getUserConf().getName().getFamilyName()).getValues().get(0)); + } + if (conf.getUserConf().getName().getFormatted() != null + && attrs.containsKey(conf.getUserConf().getName().getFormatted())) { + + name.setFormatted(attrs.get(conf.getUserConf().getName().getFormatted()).getValues().get(0)); + } + if (conf.getUserConf().getName().getGivenName() != null + && attrs.containsKey(conf.getUserConf().getName().getGivenName())) { + + name.setGivenName(attrs.get(conf.getUserConf().getName().getGivenName()).getValues().get(0)); + } + if (conf.getUserConf().getName().getHonorificPrefix() != null + && attrs.containsKey(conf.getUserConf().getName().getHonorificPrefix())) { + + name.setHonorificPrefix( + attrs.get(conf.getUserConf().getName().getHonorificPrefix()).getValues().get(0)); + } + if (conf.getUserConf().getName().getHonorificSuffix() != null + && attrs.containsKey(conf.getUserConf().getName().getHonorificSuffix())) { + + name.setHonorificSuffix( + attrs.get(conf.getUserConf().getName().getHonorificSuffix()).getValues().get(0)); + } + if (conf.getUserConf().getName().getMiddleName() != null + && attrs.containsKey(conf.getUserConf().getName().getMiddleName())) { + + name.setMiddleName(attrs.get(conf.getUserConf().getName().getMiddleName()).getValues().get(0)); + } + + if (!name.isEmpty()) { + user.setName(name); + } + } + + if (conf.getUserConf().getDisplayName() != null + && attrs.containsKey(conf.getUserConf().getDisplayName())) { + + user.setDisplayName(attrs.get(conf.getUserConf().getDisplayName()).getValues().get(0)); + } + + if (conf.getUserConf().getNickName() != null + && attrs.containsKey(conf.getUserConf().getNickName())) { + + user.setNickName(attrs.get(conf.getUserConf().getNickName()).getValues().get(0)); + } + + if (conf.getUserConf().getProfileUrl() != null + && attrs.containsKey(conf.getUserConf().getProfileUrl())) { + + user.setProfileUrl(attrs.get(conf.getUserConf().getProfileUrl()).getValues().get(0)); + } + + if (conf.getUserConf().getTitle() != null + && attrs.containsKey(conf.getUserConf().getTitle())) { + + user.setTitle(attrs.get(conf.getUserConf().getTitle()).getValues().get(0)); + } + + if (conf.getUserConf().getUserType() != null + && attrs.containsKey(conf.getUserConf().getUserType())) { + + user.setUserType(attrs.get(conf.getUserConf().getUserType()).getValues().get(0)); + } + + if (conf.getUserConf().getPreferredLanguage() != null + && attrs.containsKey(conf.getUserConf().getPreferredLanguage())) { + + user.setPreferredLanguage(attrs.get(conf.getUserConf().getPreferredLanguage()).getValues().get(0)); + } + + if (conf.getUserConf().getLocale() != null + && attrs.containsKey(conf.getUserConf().getLocale())) { + + user.setLocale(attrs.get(conf.getUserConf().getLocale()).getValues().get(0)); + } + + if (conf.getUserConf().getTimezone() != null + && attrs.containsKey(conf.getUserConf().getTimezone())) { + + user.setTimezone(attrs.get(conf.getUserConf().getTimezone()).getValues().get(0)); + } + + fill(attrs, conf.getUserConf().getEmails(), user.getEmails()); + fill(attrs, conf.getUserConf().getPhoneNumbers(), user.getPhoneNumbers()); + fill(attrs, conf.getUserConf().getIms(), user.getIms()); + fill(attrs, conf.getUserConf().getPhotos(), user.getPhotos()); + conf.getUserConf().getAddresses().forEach(addressConf -> { + SCIMUserAddress address = new SCIMUserAddress(); + + if (addressConf.getFormatted() != null && attrs.containsKey(addressConf.getFormatted())) { + address.setFormatted(attrs.get(addressConf.getFormatted()).getValues().get(0)); + } + if (addressConf.getStreetAddress() != null && attrs.containsKey(addressConf.getStreetAddress())) { + address.setStreetAddress(attrs.get(addressConf.getStreetAddress()).getValues().get(0)); + } + if (addressConf.getLocality() != null && attrs.containsKey(addressConf.getLocality())) { + address.setLocality(attrs.get(addressConf.getLocality()).getValues().get(0)); + } + if (addressConf.getRegion() != null && attrs.containsKey(addressConf.getRegion())) { + address.setRegion(attrs.get(addressConf.getRegion()).getValues().get(0)); + } + if (addressConf.getCountry() != null && attrs.containsKey(addressConf.getCountry())) { + address.setCountry(attrs.get(addressConf.getCountry()).getValues().get(0)); + } + if (addressConf.getType() != null) { + address.setType(addressConf.getType().name()); + } + if (addressConf.isPrimary()) { + address.setPrimary(true); + } + + if (!address.isEmpty()) { + user.getAddresses().add(address); + } + }); + + conf.getUserConf().getX509Certificates().stream(). + filter(certificate -> attrs.containsKey(certificate)). + forEachOrdered(certificate -> { + user.getX509Certificates().add(new Value(attrs.get(certificate).getValues().get(0))); + }); + } + + if (conf.getEnterpriseUserConf() != null) { + SCIMEnterpriseInfo enterpriseInfo = new SCIMEnterpriseInfo(); + + if (conf.getEnterpriseUserConf().getEmployeeNumber() != null + && attrs.containsKey(conf.getEnterpriseUserConf().getEmployeeNumber())) { + + enterpriseInfo.setEmployeeNumber( + attrs.get(conf.getEnterpriseUserConf().getEmployeeNumber()).getValues().get(0)); + } + if (conf.getEnterpriseUserConf().getCostCenter() != null + && attrs.containsKey(conf.getEnterpriseUserConf().getCostCenter())) { + + enterpriseInfo.setCostCenter( + attrs.get(conf.getEnterpriseUserConf().getCostCenter()).getValues().get(0)); + } + if (conf.getEnterpriseUserConf().getOrganization() != null + && attrs.containsKey(conf.getEnterpriseUserConf().getOrganization())) { + + enterpriseInfo.setOrganization( + attrs.get(conf.getEnterpriseUserConf().getOrganization()).getValues().get(0)); + } + if (conf.getEnterpriseUserConf().getDivision() != null + && attrs.containsKey(conf.getEnterpriseUserConf().getDivision())) { + + enterpriseInfo.setDivision( + attrs.get(conf.getEnterpriseUserConf().getDivision()).getValues().get(0)); + } + if (conf.getEnterpriseUserConf().getDepartment() != null + && attrs.containsKey(conf.getEnterpriseUserConf().getDepartment())) { + + enterpriseInfo.setDepartment( + attrs.get(conf.getEnterpriseUserConf().getDepartment()).getValues().get(0)); + } + if (conf.getEnterpriseUserConf().getManager() != null) { + SCIMUserManager manager = new SCIMUserManager(); + + if (conf.getEnterpriseUserConf().getManager().getManager() != null + && attrs.containsKey(conf.getEnterpriseUserConf().getManager().getManager())) { + + try { + UserTO userManager = userLogic.read( + attrs.get(conf.getEnterpriseUserConf().getManager().getManager()).getValues().get(0)); + manager.setValue(userManager.getKey()); + manager.setRef( + StringUtils.substringBefore(location, "/Users") + "/Users/" + userManager.getKey()); + + if (conf.getEnterpriseUserConf().getManager().getDisplayName() != null) { + AttrTO displayName = userManager.getPlainAttr( + conf.getEnterpriseUserConf().getManager().getDisplayName()).orElse(null); + if (displayName == null) { + displayName = userManager.getDerAttr( + conf.getEnterpriseUserConf().getManager().getDisplayName()).orElse(null); + } + if (displayName == null) { + displayName = userManager.getVirAttr( + conf.getEnterpriseUserConf().getManager().getDisplayName()).orElse(null); + } + if (displayName != null) { + manager.setDisplayName(displayName.getValues().get(0)); + } + } + } catch (Exception e) { + LOG.error("Could not read attribute {}", + conf.getEnterpriseUserConf().getManager().getManager(), e); + } + } + + if (!manager.isEmpty()) { + enterpriseInfo.setManager(manager); + } + } + + if (!enterpriseInfo.isEmpty()) { + user.setEnterpriseInfo(enterpriseInfo); + } + } + + userTO.getMemberships().forEach(membership -> { + user.getGroups().add(new Group( + membership.getGroupKey(), + StringUtils.substringBefore(location, "/Users") + "/Groups/" + membership.getGroupKey(), + membership.getGroupName(), + Function.direct)); + }); + userTO.getDynMemberships().forEach(membership -> { + user.getGroups().add(new Group( + membership.getGroupKey(), + StringUtils.substringBefore(location, "/Users") + "/Groups/" + membership.getGroupKey(), + membership.getGroupName(), + Function.indirect)); + }); + + authDataAccessor.getAuthorities(userTO.getUsername()).forEach(authority -> { + user.getEntitlements().add(new Value(authority.getAuthority() + " on Realm(s) " + authority.getRealms())); + }); + + userTO.getRoles().forEach(role -> { + user.getRoles().add(new Value(role)); + }); + + return user; + } + + public SCIMGroup toSCIMGroup(final GroupTO groupTO, final String location) { + SCIMGroup group = new SCIMGroup( + groupTO.getKey(), + Collections.singletonList(Resource.Group.schema()), + new Meta( + Resource.Group, + groupTO.getCreationDate(), + groupTO.getLastChangeDate() == null + ? groupTO.getCreationDate() : groupTO.getLastChangeDate(), + groupTO.getETagValue(), + location), + groupTO.getName()); + + MembershipCond membCond = new MembershipCond(); + membCond.setGroup(groupTO.getKey()); + SearchCond searchCond = SearchCond.getLeafCond(membCond); + + int count = userLogic. + search(searchCond, 1, 1, Collections.<OrderByClause>emptyList(), SyncopeConstants.ROOT_REALM, false). + getLeft(); + + for (int page = 1; page <= (count / AnyDAO.DEFAULT_PAGE_SIZE) + 1; page++) { + List<UserTO> users = userLogic.search( + searchCond, + page, + AnyDAO.DEFAULT_PAGE_SIZE, + Collections.<OrderByClause>emptyList(), + SyncopeConstants.ROOT_REALM, + false). + getRight(); + users.forEach(userTO -> { + group.getMembers().add(new Member( + userTO.getKey(), + StringUtils.substringBefore(location, "/Groups") + "/Users/" + userTO.getKey(), + userTO.getUsername(), + Resource.User)); + }); + } + + return group; + } +}
http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogic.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogic.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogic.java new file mode 100644 index 0000000..11085fb --- /dev/null +++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/SCIMLogic.java @@ -0,0 +1,198 @@ +/* + * 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.core.logic; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ArrayNode; +import java.io.IOException; +import java.lang.reflect.Method; +import java.net.URI; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.ws.rs.NotFoundException; +import javax.ws.rs.core.UriBuilder; +import org.apache.syncope.common.lib.AbstractBaseBean; +import org.apache.syncope.common.lib.scim.SCIMConf; +import org.apache.syncope.core.logic.scim.SCIMConfManager; +import org.apache.syncope.ext.scimv2.api.data.AuthenticationScheme; +import org.apache.syncope.ext.scimv2.api.data.BulkConfigurationOption; +import org.apache.syncope.ext.scimv2.api.data.ConfigurationOption; +import org.apache.syncope.ext.scimv2.api.data.FilterConfigurationOption; +import org.apache.syncope.ext.scimv2.api.data.Meta; +import org.apache.syncope.ext.scimv2.api.data.ResourceType; +import org.apache.syncope.ext.scimv2.api.data.SchemaExtension; +import org.apache.syncope.ext.scimv2.api.data.ServiceProviderConfig; +import org.apache.syncope.ext.scimv2.api.type.Resource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Component; + +@Component +public class SCIMLogic extends AbstractLogic<AbstractBaseBean> { + + private static final String SCHEMAS_JSON = "schemas.json"; + + private static final Object MONITOR = new Object(); + + private static ServiceProviderConfig SERVICE_PROVIDER_CONFIG; + + private static ResourceType USER; + + private static ResourceType GROUP; + + private static String SCHEMAS; + + private static final Map<String, String> SCHEMA_MAP = new HashMap<>(); + + @Autowired + private SCIMConfManager confManager; + + private void init() { + try { + ObjectMapper mapper = new ObjectMapper(); + JsonNode tree = mapper.readTree(getClass().getResourceAsStream("/" + SCHEMAS_JSON)); + if (!tree.isArray()) { + throw new IOException("JSON node is not a tree"); + } + + ArrayNode schemaArray = (ArrayNode) tree; + SCHEMAS = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(tree); + + for (JsonNode schema : schemaArray) { + SCHEMA_MAP.put(schema.get("id").asText(), mapper.writeValueAsString(schema)); + } + } catch (IOException e) { + LOG.error("Could not parse the default schema definitions", e); + } + } + + @PreAuthorize("isAuthenticated()") + public ServiceProviderConfig serviceProviderConfig(final UriBuilder uriBuilder) { + synchronized (MONITOR) { + if (SCHEMAS == null) { + init(); + } + + if (SERVICE_PROVIDER_CONFIG == null) { + SCIMConf conf = confManager.get(); + + SERVICE_PROVIDER_CONFIG = new ServiceProviderConfig( + new Meta( + Resource.ServiceProviderConfig, + conf.getCreationDate(), + conf.getLastChangeDate(), + conf.getETagValue(), + uriBuilder.build().toASCIIString()), + new ConfigurationOption(true), + new BulkConfigurationOption(true, conf.getBulkMaxOperations(), conf.getBulkMaxPayloadSize()), + new FilterConfigurationOption(true, conf.getFilterMaxResults()), + new ConfigurationOption(true), + new ConfigurationOption(true), + new ConfigurationOption(true)); + SERVICE_PROVIDER_CONFIG.getAuthenticationSchemes().add(new AuthenticationScheme( + "JSON Web Token", + "Apache Syncope JWT authentication", + URI.create("http://www.rfc-editor.org/info/rfc6750"), + URI.create("https://syncope.apache.org/docs/" + + "reference-guide.html#rest-authentication-and-authorization"), + "oauthbearertoken", + true)); + SERVICE_PROVIDER_CONFIG.getAuthenticationSchemes().add(new AuthenticationScheme( + "HTTP Basic", + "Apache Syncope HTTP Basic authentication", + URI.create("http://www.rfc-editor.org/info/rfc2617"), + URI.create("https://syncope.apache.org/docs/" + + "reference-guide.html#rest-authentication-and-authorization"), + "httpbasic", + false)); + } + } + return SERVICE_PROVIDER_CONFIG; + } + + @PreAuthorize("isAuthenticated()") + public List<ResourceType> resourceTypes(final UriBuilder uriBuilder) { + synchronized (MONITOR) { + if (USER == null) { + USER = new ResourceType("User", "User", "/Users", "User Account", Resource.User.schema(), + new Meta(Resource.ResourceType, + null, null, null, uriBuilder.path("User").build().toASCIIString())); + USER.getSchemaExtensions().add(new SchemaExtension(Resource.EnterpriseUser.schema(), true)); + } + if (GROUP == null) { + GROUP = new ResourceType("Group", "Group", "/Groups", "Group", Resource.Group.schema(), + new Meta(Resource.ResourceType, + null, null, null, uriBuilder.path("Group").build().toASCIIString())); + } + } + + return Arrays.asList(USER, GROUP); + } + + @PreAuthorize("isAuthenticated()") + public ResourceType resourceType(final UriBuilder uriBuilder, final String type) { + if (Resource.User.name().equals(type)) { + resourceTypes(uriBuilder); + return USER; + } else if (Resource.Group.name().equals(type)) { + resourceTypes(uriBuilder); + return GROUP; + } else { + throw new IllegalArgumentException("Unsupported resource type: " + type); + } + } + + @PreAuthorize("isAuthenticated()") + public String schemas() { + synchronized (MONITOR) { + if (SCHEMAS == null) { + init(); + } + } + + return SCHEMAS; + } + + @PreAuthorize("isAuthenticated()") + public String schema(final String schema) { + synchronized (MONITOR) { + if (SCHEMAS == null) { + init(); + } + } + + String found = SCHEMA_MAP.get(schema); + if (found == null) { + throw new NotFoundException("Schema " + schema); + } + + return found; + } + + @Override + protected AbstractBaseBean resolveReference(final Method method, final Object... args) + throws UnresolvedReferenceException { + + throw new UnresolvedReferenceException(); + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java index 894ba24..a5a1733 100644 --- a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java +++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java @@ -18,39 +18,14 @@ */ package org.apache.syncope.core.logic.init; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; -import org.apache.commons.lang3.tuple.Pair; -import org.apache.syncope.common.lib.PropertyUtils; +import org.apache.syncope.common.lib.scim.types.SCIMEntitlement; import org.apache.syncope.core.persistence.api.SyncopeLoader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.apache.syncope.core.provisioning.api.EntitlementsHolder; import org.springframework.stereotype.Component; @Component public class SCIMLoader implements SyncopeLoader { - private static final Logger LOG = LoggerFactory.getLogger(SCIMLoader.class); - - private static final String SCIMV2_LOGIC_PROPERTIES = "scimv2-logic.properties"; - - private static final String SCHEMAS = "schemas.json"; - - private int bulkMaxOperations = 0; - - private int bulkMaxPayloadSize = 0; - - private int filterMaxResults = 0; - - private String schemas; - - private final Map<String, String> schemaMap = new HashMap<>(); - @Override public Integer getPriority() { return 1000; @@ -58,49 +33,7 @@ public class SCIMLoader implements SyncopeLoader { @Override public void load() { - Pair<Properties, String> init = PropertyUtils.read(getClass(), SCIMV2_LOGIC_PROPERTIES, "conf.directory"); - Properties props = init.getLeft(); - - bulkMaxOperations = Integer.valueOf(props.getProperty("bulk.maxOperations")); - bulkMaxPayloadSize = Integer.valueOf(props.getProperty("bulk.maxPayloadSize")); - filterMaxResults = Integer.valueOf(props.getProperty("filter.maxResults")); - - try { - ObjectMapper mapper = new ObjectMapper(); - JsonNode tree = mapper.readTree(getClass().getResourceAsStream("/" + SCHEMAS)); - if (!tree.isArray()) { - throw new IOException("JSON node is not a tree"); - } - - ArrayNode schemaArray = (ArrayNode) tree; - schemas = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(tree); - - for (JsonNode schema : schemaArray) { - schemaMap.put(schema.get("id").asText(), mapper.writeValueAsString(schema)); - } - } catch (IOException e) { - LOG.error("Could not parse the default schema definitions", e); - } - } - - public int getBulkMaxOperations() { - return bulkMaxOperations; - } - - public int getBulkMaxPayloadSize() { - return bulkMaxPayloadSize; - } - - public int getFilterMaxResults() { - return filterMaxResults; - } - - public String getSchemas() { - return schemas; - } - - public String getSchema(final String schema) { - return schemaMap.get(schema); + EntitlementsHolder.getInstance().init(SCIMEntitlement.values()); } } http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMConfManager.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMConfManager.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMConfManager.java new file mode 100644 index 0000000..ede870b --- /dev/null +++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/scim/SCIMConfManager.java @@ -0,0 +1,93 @@ +/* + * 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.core.logic.scim; + +import java.util.Date; +import javax.ws.rs.core.MediaType; +import org.apache.syncope.common.lib.scim.SCIMConf; +import org.apache.syncope.common.lib.scim.types.SCIMEntitlement; +import org.apache.syncope.common.lib.to.AttrTO; +import org.apache.syncope.common.lib.to.PlainSchemaTO; +import org.apache.syncope.common.lib.types.AttrSchemaType; +import org.apache.syncope.common.lib.types.SchemaType; +import org.apache.syncope.core.logic.ConfigurationLogic; +import org.apache.syncope.core.logic.SchemaLogic; +import org.apache.syncope.core.persistence.api.dao.NotFoundException; +import org.apache.syncope.core.provisioning.api.serialization.POJOHelper; +import org.identityconnectors.common.Base64; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Component; + +@Component +public class SCIMConfManager { + + protected static final Logger LOG = LoggerFactory.getLogger(SCIMConfManager.class); + + @Autowired + private ConfigurationLogic configurationLogic; + + @Autowired + private SchemaLogic schemaLogic; + + @PreAuthorize("hasRole('" + SCIMEntitlement.SCIM_CONF_GET + "')") + public SCIMConf get() { + AttrTO confTO = null; + try { + confTO = configurationLogic.get(SCIMConf.KEY); + } catch (Exception e) { + LOG.error("{} not found, reverting to default", SCIMConf.KEY); + } + + SCIMConf conf = null; + if (confTO != null) { + try { + conf = POJOHelper.deserialize(new String(Base64.decode(confTO.getValues().get(0))), SCIMConf.class); + } catch (Exception e) { + LOG.error("Could not deserialize, reverting to default", e); + } + } + if (conf == null) { + conf = new SCIMConf(); + set(conf); + } + + return conf; + } + + @PreAuthorize("hasRole('" + SCIMEntitlement.SCIM_CONF_SET + "')") + public void set(final SCIMConf conf) { + try { + schemaLogic.read(SchemaType.PLAIN, SCIMConf.KEY); + } catch (NotFoundException e) { + PlainSchemaTO scimConf = new PlainSchemaTO(); + scimConf.setKey(SCIMConf.KEY); + scimConf.setType(AttrSchemaType.Binary); + scimConf.setMimeType(MediaType.APPLICATION_JSON); + schemaLogic.create(SchemaType.PLAIN, scimConf); + } + conf.setLastChangeDate(new Date()); + + configurationLogic.set(new AttrTO.Builder(). + schema(SCIMConf.KEY).value(Base64.encode(POJOHelper.serialize(conf).getBytes())).build()); + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/logic/src/main/resources/scimv2-logic.properties ---------------------------------------------------------------------- diff --git a/ext/scimv2/logic/src/main/resources/scimv2-logic.properties b/ext/scimv2/logic/src/main/resources/scimv2-logic.properties deleted file mode 100644 index 2d85a37..0000000 --- a/ext/scimv2/logic/src/main/resources/scimv2-logic.properties +++ /dev/null @@ -1,21 +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. -conf.directory=${conf.directory} - -bulk.maxOperations=1000 -bulk.maxPayloadSize=1048576 -filter.maxResults=200 http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/pom.xml ---------------------------------------------------------------------- diff --git a/ext/scimv2/pom.xml b/ext/scimv2/pom.xml index bc62e00..5a55f49 100644 --- a/ext/scimv2/pom.xml +++ b/ext/scimv2/pom.xml @@ -38,9 +38,13 @@ under the License. </properties> <modules> + <module>common-lib</module> + <module>rest-api</module> + <module>rest-cxf</module> <module>scim-rest-api</module> <module>scim-rest-cxf</module> <module>logic</module> + <module>client-console</module> </modules> </project> http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/rest-api/pom.xml ---------------------------------------------------------------------- diff --git a/ext/scimv2/rest-api/pom.xml b/ext/scimv2/rest-api/pom.xml new file mode 100644 index 0000000..7010846 --- /dev/null +++ b/ext/scimv2/rest-api/pom.xml @@ -0,0 +1,77 @@ +<?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. +--> +<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"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.syncope.ext</groupId> + <artifactId>syncope-ext-scimv2</artifactId> + <version>2.1.0-SNAPSHOT</version> + </parent> + + <name>Apache Syncope Ext: SCIMv2 REST API</name> + <description>Apache Syncope Ext: SCIMv2 REST API</description> + <groupId>org.apache.syncope.ext.scimv2</groupId> + <artifactId>syncope-ext-scimv2-rest-api</artifactId> + <packaging>jar</packaging> + + <properties> + <rootpom.basedir>${basedir}/../../..</rootpom.basedir> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.syncope.common</groupId> + <artifactId>syncope-common-rest-api</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>org.apache.syncope.ext.scimv2</groupId> + <artifactId>syncope-ext-scimv2-common-lib</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <!-- Generating javadoc JAR artifact for usage with CXF's WADL generator (for core) --> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <inherited>true</inherited> + <executions> + <execution> + <id>attach-javadocs</id> + <goals> + <goal>jar</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-checkstyle-plugin</artifactId> + </plugin> + </plugins> + </build> +</project> http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SCIMConfService.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SCIMConfService.java b/ext/scimv2/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SCIMConfService.java new file mode 100644 index 0000000..fdc4da3 --- /dev/null +++ b/ext/scimv2/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SCIMConfService.java @@ -0,0 +1,53 @@ +/* + * 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.service; + +import javax.validation.constraints.NotNull; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import org.apache.syncope.common.lib.scim.SCIMConf; + +/** + * REST operations for SCIM 2.0 configuration. + */ +@Path("scimv2conf") +public interface SCIMConfService extends JAXRSService { + + /** + * Reads SCIM configuration, generates empty if missing. + * + * @return SCIM configuration + */ + @GET + @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + SCIMConf get(); + + /** + * Sets SCIM configuration. + * + * @param conf SCIM configuration + */ + @PUT + @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML }) + void set(@NotNull SCIMConf conf); +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/rest-cxf/pom.xml ---------------------------------------------------------------------- diff --git a/ext/scimv2/rest-cxf/pom.xml b/ext/scimv2/rest-cxf/pom.xml new file mode 100644 index 0000000..403f430 --- /dev/null +++ b/ext/scimv2/rest-cxf/pom.xml @@ -0,0 +1,72 @@ +<?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. +--> +<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"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.syncope.ext</groupId> + <artifactId>syncope-ext-scimv2</artifactId> + <version>2.1.0-SNAPSHOT</version> + </parent> + + <name>Apache Syncope Ext: SCIMv2 REST CXF</name> + <description>Apache Syncope Ext: SCIMv2 REST CXF</description> + <groupId>org.apache.syncope.ext.scimv2</groupId> + <artifactId>syncope-ext-scimv2-rest-cxf</artifactId> + <packaging>jar</packaging> + + <properties> + <rootpom.basedir>${basedir}/../../..</rootpom.basedir> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.syncope.core</groupId> + <artifactId>syncope-core-rest-cxf</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.syncope.ext.scimv2</groupId> + <artifactId>syncope-ext-scimv2-rest-api</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.syncope.ext.scimv2</groupId> + <artifactId>syncope-ext-scimv2-rest-api</artifactId> + <version>${project.version}</version> + <classifier>javadoc</classifier> + </dependency> + <dependency> + <groupId>org.apache.syncope.ext.scimv2</groupId> + <artifactId>syncope-ext-scimv2-logic</artifactId> + <version>${project.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-checkstyle-plugin</artifactId> + </plugin> + </plugins> + </build> +</project> http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SCIMConfServiceImpl.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SCIMConfServiceImpl.java b/ext/scimv2/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SCIMConfServiceImpl.java new file mode 100644 index 0000000..223aca7 --- /dev/null +++ b/ext/scimv2/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SCIMConfServiceImpl.java @@ -0,0 +1,41 @@ +/* + * 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.core.rest.cxf.service; + +import org.apache.syncope.common.lib.scim.SCIMConf; +import org.apache.syncope.common.rest.api.service.SCIMConfService; +import org.apache.syncope.core.logic.scim.SCIMConfManager; +import org.springframework.beans.factory.annotation.Autowired; + +public class SCIMConfServiceImpl extends AbstractServiceImpl implements SCIMConfService { + + @Autowired + private SCIMConfManager manager; + + @Override + public SCIMConf get() { + return manager.get(); + } + + @Override + public void set(final SCIMConf conf) { + manager.set(conf); + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Display.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Display.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Display.java deleted file mode 100644 index f79796c..0000000 --- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Display.java +++ /dev/null @@ -1,46 +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.ext.scimv2.api.data; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; - -public class Display extends SCIMBean { - - private static final long serialVersionUID = 5337055958765320091L; - - private final String value; - - private final String display; - - @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) - public Display(@JsonProperty("value") final String value, @JsonProperty("display") final String display) { - this.value = value; - this.display = display; - } - - public String getValue() { - return value; - } - - public String getDisplay() { - return display; - } - -} http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Reference.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Reference.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Reference.java index d65f5e8..a00c793 100644 --- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Reference.java +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Reference.java @@ -20,18 +20,25 @@ package org.apache.syncope.ext.scimv2.api.data; import com.fasterxml.jackson.annotation.JsonProperty; -abstract class Reference extends Display { +abstract class Reference extends Value { private static final long serialVersionUID = -6190164044699376089L; + private final String display; + @JsonProperty("$ref") private final String ref; Reference(final String value, final String display, final String ref) { - super(value, display); + super(value); + this.display = display; this.ref = ref; } + public String getDisplay() { + return display; + } + public String getRef() { return ref; } http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMBean.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMBean.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMBean.java index 95334cf..ca191be 100644 --- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMBean.java +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMBean.java @@ -21,7 +21,7 @@ package org.apache.syncope.ext.scimv2.api.data; import com.fasterxml.jackson.annotation.JsonInclude; import java.io.Serializable; -@JsonInclude(JsonInclude.Include.NON_NULL) +@JsonInclude(JsonInclude.Include.NON_EMPTY) abstract class SCIMBean implements Serializable { private static final long serialVersionUID = 7604407251038024743L; http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMComplexValue.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMComplexValue.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMComplexValue.java new file mode 100644 index 0000000..94c4320 --- /dev/null +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMComplexValue.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.ext.scimv2.api.data; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class SCIMComplexValue extends SCIMBean { + + private static final long serialVersionUID = -3887211468327809832L; + + private String value; + + private String display; + + private String type; + + private boolean primary; + + public String getValue() { + return value; + } + + public void setValue(final String value) { + this.value = value; + } + + public String getDisplay() { + return display; + } + + public void setDisplay(final String display) { + this.display = display; + } + + public String getType() { + return type; + } + + public void setType(final String type) { + this.type = type; + } + + public boolean isPrimary() { + return primary; + } + + public void setPrimary(final boolean primary) { + this.primary = primary; + } + + @JsonIgnore + public boolean isEmpty() { + return value == null && display == null && type == null; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMEnterpriseInfo.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMEnterpriseInfo.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMEnterpriseInfo.java new file mode 100644 index 0000000..d419c09 --- /dev/null +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMEnterpriseInfo.java @@ -0,0 +1,96 @@ +/* + * 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.ext.scimv2.api.data; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class SCIMEnterpriseInfo extends SCIMBean { + + private static final long serialVersionUID = 5745005071861557082L; + + private String employeeNumber; + + private String costCenter; + + private String organization; + + private String division; + + private String department; + + private SCIMUserManager manager; + + public String getEmployeeNumber() { + return employeeNumber; + } + + public void setEmployeeNumber(final String employeeNumber) { + this.employeeNumber = employeeNumber; + } + + public String getCostCenter() { + return costCenter; + } + + public void setCostCenter(final String costCenter) { + this.costCenter = costCenter; + } + + public String getOrganization() { + return organization; + } + + public void setOrganization(final String organization) { + this.organization = organization; + } + + public String getDivision() { + return division; + } + + public void setDivision(final String division) { + this.division = division; + } + + public String getDepartment() { + return department; + } + + public void setDepartment(final String department) { + this.department = department; + } + + public SCIMUserManager getManager() { + return manager; + } + + public void setManager(final SCIMUserManager manager) { + this.manager = manager; + } + + @JsonIgnore + public boolean isEmpty() { + return employeeNumber == null + && costCenter == null + && organization == null + && division == null + && department == null + && manager == null; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUser.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUser.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUser.java index c76c0f0..775b1ad 100644 --- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUser.java +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUser.java @@ -24,18 +24,61 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder; import java.util.ArrayList; import java.util.List; -@JsonPropertyOrder({ "schemas", "id", "externalId", "userName", "active", "groups", "roles", "meta" }) +@JsonPropertyOrder({ "schemas", "id", "externalId", + "userName", "password", "active", + "name", "displayName", "nickName", "profileUrl", "title", "userType", "preferredLanguage", "locale", "timezone", + "emails", "phoneNumbers", "ims", "photos", "addresses", "x509Certificates", + "groups", "entitlements", "roles", + "enterpriseInfo", + "meta" }) public class SCIMUser extends SCIMResource { private static final long serialVersionUID = -2935466041674390279L; private final String userName; + private String password; + private final boolean active; + private SCIMUserName name; + + private String displayName; + + private String nickName; + + private String profileUrl; + + private String title; + + private String userType; + + private String preferredLanguage; + + private String locale; + + private String timezone; + + private final List<SCIMComplexValue> emails = new ArrayList<>(); + + private final List<SCIMComplexValue> phoneNumbers = new ArrayList<>(); + + private final List<SCIMComplexValue> ims = new ArrayList<>(); + + private final List<SCIMComplexValue> photos = new ArrayList<>(); + + private final List<SCIMUserAddress> addresses = new ArrayList<>(); + + private final List<Value> x509Certificates = new ArrayList<>(); + private final List<Group> groups = new ArrayList<>(); - private final List<Display> roles = new ArrayList<>(); + private final List<Value> entitlements = new ArrayList<>(); + + private final List<Value> roles = new ArrayList<>(); + + @JsonProperty("urn:ietf:params:scim:schemas:extension:enterprise:2.0:User") + private SCIMEnterpriseInfo enterpriseInfo; @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) public SCIMUser( @@ -54,16 +97,132 @@ public class SCIMUser extends SCIMResource { return userName; } + public void setPassword(final String password) { + this.password = password; + } + + public String getPassword() { + return password; + } + public boolean isActive() { return active; } + public SCIMUserName getName() { + return name; + } + + public void setName(final SCIMUserName name) { + this.name = name; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(final String displayName) { + this.displayName = displayName; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(final String nickName) { + this.nickName = nickName; + } + + public String getProfileUrl() { + return profileUrl; + } + + public void setProfileUrl(final String profileUrl) { + this.profileUrl = profileUrl; + } + + public String getTitle() { + return title; + } + + public void setTitle(final String title) { + this.title = title; + } + + public String getUserType() { + return userType; + } + + public void setUserType(final String userType) { + this.userType = userType; + } + + public String getPreferredLanguage() { + return preferredLanguage; + } + + public void setPreferredLanguage(final String preferredLanguage) { + this.preferredLanguage = preferredLanguage; + } + + public String getLocale() { + return locale; + } + + public void setLocale(final String locale) { + this.locale = locale; + } + + public String getTimezone() { + return timezone; + } + + public void setTimezone(final String timezone) { + this.timezone = timezone; + } + + public List<SCIMComplexValue> getEmails() { + return emails; + } + + public List<SCIMComplexValue> getPhoneNumbers() { + return phoneNumbers; + } + + public List<SCIMComplexValue> getIms() { + return ims; + } + + public List<SCIMComplexValue> getPhotos() { + return photos; + } + + public List<SCIMUserAddress> getAddresses() { + return addresses; + } + + public List<Value> getX509Certificates() { + return x509Certificates; + } + public List<Group> getGroups() { return groups; } - public List<Display> getRoles() { + public List<Value> getEntitlements() { + return entitlements; + } + + public List<Value> getRoles() { return roles; } + public SCIMEnterpriseInfo getEnterpriseInfo() { + return enterpriseInfo; + } + + public void setEnterpriseInfo(final SCIMEnterpriseInfo enterpriseInfo) { + this.enterpriseInfo = enterpriseInfo; + } + } http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserAddress.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserAddress.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserAddress.java new file mode 100644 index 0000000..3c1f0d9 --- /dev/null +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserAddress.java @@ -0,0 +1,117 @@ +/* + * 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.ext.scimv2.api.data; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class SCIMUserAddress extends SCIMBean { + + private static final long serialVersionUID = -7936040729842689890L; + + private String formatted; + + private String streetAddress; + + private String locality; + + private String region; + + private String postalCode; + + private String country; + + private String type; + + private boolean primary; + + public String getFormatted() { + return formatted; + } + + public void setFormatted(final String formatted) { + this.formatted = formatted; + } + + public String getStreetAddress() { + return streetAddress; + } + + public void setStreetAddress(final String streetAddress) { + this.streetAddress = streetAddress; + } + + public String getLocality() { + return locality; + } + + public void setLocality(final String locality) { + this.locality = locality; + } + + public String getRegion() { + return region; + } + + public void setRegion(final String region) { + this.region = region; + } + + public String getPostalCode() { + return postalCode; + } + + public void setPostalCode(final String postalCode) { + this.postalCode = postalCode; + } + + public String getCountry() { + return country; + } + + public void setCountry(final String country) { + this.country = country; + } + + public String getType() { + return type; + } + + public void setType(final String type) { + this.type = type; + } + + public boolean isPrimary() { + return primary; + } + + public void setPrimary(final boolean primary) { + this.primary = primary; + } + + @JsonIgnore + public boolean isEmpty() { + return formatted == null + && streetAddress == null + && locality == null + && region == null + && postalCode == null + && country == null + && type == null; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserManager.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserManager.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserManager.java new file mode 100644 index 0000000..c1294e9 --- /dev/null +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserManager.java @@ -0,0 +1,63 @@ +/* + * 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.ext.scimv2.api.data; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class SCIMUserManager extends SCIMBean { + + private static final long serialVersionUID = -4193118676994783252L; + + private String value; + + @JsonProperty("$ref") + private String ref; + + private String displayName; + + public String getValue() { + return value; + } + + public void setValue(final String value) { + this.value = value; + } + + public String getRef() { + return ref; + } + + public void setRef(final String ref) { + this.ref = ref; + } + + public String getDisplayName() { + return displayName; + } + + public void setDisplayName(final String displayName) { + this.displayName = displayName; + } + + @JsonIgnore + public boolean isEmpty() { + return value == null && ref == null && displayName == null; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserName.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserName.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserName.java new file mode 100644 index 0000000..0293e95 --- /dev/null +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/SCIMUserName.java @@ -0,0 +1,96 @@ +/* + * 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.ext.scimv2.api.data; + +import com.fasterxml.jackson.annotation.JsonIgnore; + +public class SCIMUserName extends SCIMBean { + + private static final long serialVersionUID = 5492302691746462480L; + + private String formatted; + + private String familyName; + + private String givenName; + + private String middleName; + + private String honorificPrefix; + + private String honorificSuffix; + + public String getFormatted() { + return formatted; + } + + public void setFormatted(final String formatted) { + this.formatted = formatted; + } + + public String getFamilyName() { + return familyName; + } + + public void setFamilyName(final String familyName) { + this.familyName = familyName; + } + + public String getGivenName() { + return givenName; + } + + public void setGivenName(final String givenName) { + this.givenName = givenName; + } + + public String getMiddleName() { + return middleName; + } + + public void setMiddleName(final String middleName) { + this.middleName = middleName; + } + + public String getHonorificPrefix() { + return honorificPrefix; + } + + public void setHonorificPrefix(final String honorificPrefix) { + this.honorificPrefix = honorificPrefix; + } + + public String getHonorificSuffix() { + return honorificSuffix; + } + + public void setHonorificSuffix(final String honorificSuffix) { + this.honorificSuffix = honorificSuffix; + } + + @JsonIgnore + public boolean isEmpty() { + return formatted == null + && familyName == null + && givenName == null + && middleName == null + && honorificPrefix == null + && honorificSuffix == null; + } +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/ServiceProviderConfig.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/ServiceProviderConfig.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/ServiceProviderConfig.java index 3014a6c..75eec0a 100644 --- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/ServiceProviderConfig.java +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/ServiceProviderConfig.java @@ -20,17 +20,22 @@ package org.apache.syncope.ext.scimv2.api.data; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.syncope.ext.scimv2.api.type.Resource; +@JsonPropertyOrder( + { "schemas", "patch", "bulk", "filter", "changePassword", "sort", "etag", "authenticationSchemes", "meta" }) public class ServiceProviderConfig extends SCIMBean { private static final long serialVersionUID = 1027738509789460252L; private final List<String> schemas = Arrays.asList(Resource.ServiceProviderConfig.schema()); + private final Meta meta; + private final ConfigurationOption patch; private final BulkConfigurationOption bulk; @@ -47,6 +52,7 @@ public class ServiceProviderConfig extends SCIMBean { @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) public ServiceProviderConfig( + @JsonProperty("meta") final Meta meta, @JsonProperty("patch") final ConfigurationOption patch, @JsonProperty("bulk") final BulkConfigurationOption bulk, @JsonProperty("filter") final FilterConfigurationOption filter, @@ -54,6 +60,7 @@ public class ServiceProviderConfig extends SCIMBean { @JsonProperty("sort") final ConfigurationOption sort, @JsonProperty("etag") final ConfigurationOption etag) { + this.meta = meta; this.patch = patch; this.bulk = bulk; this.filter = filter; @@ -66,6 +73,10 @@ public class ServiceProviderConfig extends SCIMBean { return schemas; } + public Meta getMeta() { + return meta; + } + public ConfigurationOption getPatch() { return patch; } http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Value.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Value.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Value.java new file mode 100644 index 0000000..543f000 --- /dev/null +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/data/Value.java @@ -0,0 +1,39 @@ +/* + * 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.ext.scimv2.api.data; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class Value extends SCIMBean { + + private static final long serialVersionUID = 5337055958765320091L; + + private final String value; + + @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) + public Value(@JsonProperty("value") final String value) { + this.value = value; + } + + public String getValue() { + return value; + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/GroupService.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/GroupService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/GroupService.java index 8881ec8..196572e 100644 --- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/GroupService.java +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/GroupService.java @@ -33,7 +33,7 @@ import org.apache.syncope.ext.scimv2.api.SCIMConstants; import org.apache.syncope.ext.scimv2.api.data.SCIMGroup; @Path("v2/Groups") -public interface GroupService extends SCIMService<SCIMGroup> { +public interface GroupService extends SearchService<SCIMGroup> { @POST @Produces({ SCIMConstants.APPLICATION_SCIM_JSON }) http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/RootService.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/RootService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/RootService.java deleted file mode 100644 index 6e9b201..0000000 --- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/RootService.java +++ /dev/null @@ -1,59 +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.ext.scimv2.api.service; - -import java.util.List; -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.Response; -import org.apache.syncope.ext.scimv2.api.SCIMConstants; -import org.apache.syncope.ext.scimv2.api.data.ResourceType; -import org.apache.syncope.ext.scimv2.api.data.SCIMResource; -import org.apache.syncope.ext.scimv2.api.data.ServiceProviderConfig; - -@Path("v2") -public interface RootService extends SCIMService<SCIMResource> { - - @GET - @Path("ServiceProviderConfig") - @Produces({ SCIMConstants.APPLICATION_SCIM_JSON }) - ServiceProviderConfig serviceProviderConfig(); - - @GET - @Path("ResourceTypes") - @Produces({ SCIMConstants.APPLICATION_SCIM_JSON }) - List<ResourceType> resourceTypes(); - - @GET - @Path("ResourceTypes/{type}") - @Produces({ SCIMConstants.APPLICATION_SCIM_JSON }) - ResourceType resourceType(@PathParam("type") String type); - - @GET - @Path("Schemas") - @Produces({ SCIMConstants.APPLICATION_SCIM_JSON }) - Response schemas(); - - @GET - @Path("Schemas/{schema}") - @Produces({ SCIMConstants.APPLICATION_SCIM_JSON }) - Response schema(@PathParam("schema") String schema); -} http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SCIMService.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SCIMService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SCIMService.java index 1b2fd3f..6064747 100644 --- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SCIMService.java +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SCIMService.java @@ -20,22 +20,40 @@ package org.apache.syncope.ext.scimv2.api.service; import java.util.List; import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; import javax.ws.rs.Produces; -import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Response; import org.apache.syncope.ext.scimv2.api.SCIMConstants; -import org.apache.syncope.ext.scimv2.api.data.ListResponse; +import org.apache.syncope.ext.scimv2.api.data.ResourceType; import org.apache.syncope.ext.scimv2.api.data.SCIMResource; -import org.apache.syncope.ext.scimv2.api.type.SortOrder; +import org.apache.syncope.ext.scimv2.api.data.ServiceProviderConfig; -public interface SCIMService<R extends SCIMResource> { +@Path("v2") +public interface SCIMService extends SearchService<SCIMResource> { @GET + @Path("ServiceProviderConfig") @Produces({ SCIMConstants.APPLICATION_SCIM_JSON }) - ListResponse<R> search( - @QueryParam("startIndex") Integer startIndex, - @QueryParam("count") Integer count, - @QueryParam("filter") String filter, - @QueryParam("sortBy") String sortBy, - @QueryParam("sortOrder") SortOrder sortOrder, - @QueryParam("attributes") List<String> attributes); + ServiceProviderConfig serviceProviderConfig(); + + @GET + @Path("ResourceTypes") + @Produces({ SCIMConstants.APPLICATION_SCIM_JSON }) + List<ResourceType> resourceTypes(); + + @GET + @Path("ResourceTypes/{type}") + @Produces({ SCIMConstants.APPLICATION_SCIM_JSON }) + ResourceType resourceType(@PathParam("type") String type); + + @GET + @Path("Schemas") + @Produces({ SCIMConstants.APPLICATION_SCIM_JSON }) + Response schemas(); + + @GET + @Path("Schemas/{schema}") + @Produces({ SCIMConstants.APPLICATION_SCIM_JSON }) + Response schema(@PathParam("schema") String schema); } http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.java new file mode 100644 index 0000000..fcd4789 --- /dev/null +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/SearchService.java @@ -0,0 +1,41 @@ +/* + * 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.ext.scimv2.api.service; + +import java.util.List; +import javax.ws.rs.GET; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import org.apache.syncope.ext.scimv2.api.SCIMConstants; +import org.apache.syncope.ext.scimv2.api.data.ListResponse; +import org.apache.syncope.ext.scimv2.api.data.SCIMResource; +import org.apache.syncope.ext.scimv2.api.type.SortOrder; + +public interface SearchService<R extends SCIMResource> { + + @GET + @Produces({ SCIMConstants.APPLICATION_SCIM_JSON }) + ListResponse<R> search( + @QueryParam("startIndex") Integer startIndex, + @QueryParam("count") Integer count, + @QueryParam("filter") String filter, + @QueryParam("sortBy") String sortBy, + @QueryParam("sortOrder") SortOrder sortOrder, + @QueryParam("attributes") List<String> attributes); +} http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/UserService.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/UserService.java b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/UserService.java index 8003b66..1135650 100644 --- a/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/UserService.java +++ b/ext/scimv2/scim-rest-api/src/main/java/org/apache/syncope/ext/scimv2/api/service/UserService.java @@ -33,7 +33,7 @@ import org.apache.syncope.ext.scimv2.api.SCIMConstants; import org.apache.syncope.ext.scimv2.api.data.SCIMUser; @Path("v2/Users") -public interface UserService extends SCIMService<SCIMUser> { +public interface UserService extends SearchService<SCIMUser> { @POST @Produces({ SCIMConstants.APPLICATION_SCIM_JSON }) http://git-wip-us.apache.org/repos/asf/syncope/blob/7cd22892/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/AddETagFilter.java ---------------------------------------------------------------------- diff --git a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/AddETagFilter.java b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/AddETagFilter.java index 498ea95..d2c76a8 100644 --- a/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/AddETagFilter.java +++ b/ext/scimv2/scim-rest-cxf/src/main/java/org/apache/syncope/ext/scimv2/cxf/AddETagFilter.java @@ -46,7 +46,7 @@ public class AddETagFilter implements ContainerResponseFilter { if (lastModified != null) { String etagValue = String.valueOf(lastModified.getTime()); if (StringUtils.isNotBlank(etagValue)) { - resCtx.getHeaders().add(HttpHeaders.ETAG, new EntityTag(etagValue).toString()); + resCtx.getHeaders().add(HttpHeaders.ETAG, new EntityTag(etagValue, true).toString()); } } }