http://git-wip-us.apache.org/repos/asf/syncope/blob/f1c004bf/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2EntityFactory.java ---------------------------------------------------------------------- diff --git a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2EntityFactory.java b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2EntityFactory.java index 2277c14..888e870 100644 --- a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2EntityFactory.java +++ b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2EntityFactory.java @@ -22,6 +22,7 @@ import org.apache.syncope.core.persistence.api.entity.Entity; import org.apache.syncope.core.persistence.api.entity.SAML2EntityFactory; import org.apache.syncope.core.persistence.api.entity.SAML2IdP; import org.apache.syncope.core.persistence.api.entity.SAML2IdPItem; +import org.apache.syncope.core.persistence.api.entity.SAML2UserTemplate; import org.springframework.stereotype.Component; @Component @@ -36,6 +37,8 @@ public class JPASAML2EntityFactory implements SAML2EntityFactory { result = (E) new JPASAML2IdP(); } else if (reference.equals(SAML2IdPItem.class)) { result = (E) new JPASAML2IdPItem(); + } else if (reference.equals(SAML2UserTemplate.class)) { + result = (E) new JPASAML2UserTemplate(); } else { throw new IllegalArgumentException("Could not find a JPA implementation of " + reference.getName()); }
http://git-wip-us.apache.org/repos/asf/syncope/blob/f1c004bf/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java ---------------------------------------------------------------------- diff --git a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java index cf1e3a8..d6df04d 100644 --- a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java +++ b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdP.java @@ -19,15 +19,21 @@ package org.apache.syncope.core.persistence.jpa.entity; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import javax.persistence.Basic; import javax.persistence.Cacheable; import javax.persistence.CascadeType; +import javax.persistence.CollectionTable; import javax.persistence.Column; +import javax.persistence.ElementCollection; import javax.persistence.Entity; import javax.persistence.FetchType; +import javax.persistence.JoinColumn; import javax.persistence.Lob; import javax.persistence.OneToMany; +import javax.persistence.OneToOne; import javax.persistence.Table; import javax.validation.constraints.Max; import javax.validation.constraints.Min; @@ -37,6 +43,7 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.syncope.common.lib.types.SAML2BindingType; import org.apache.syncope.core.persistence.api.entity.SAML2IdP; import org.apache.syncope.core.persistence.api.entity.SAML2IdPItem; +import org.apache.syncope.core.persistence.api.entity.SAML2UserTemplate; import org.apache.syncope.core.persistence.jpa.validation.entity.SAML2IdPCheck; @Entity @@ -65,11 +72,31 @@ public class JPASAML2IdP extends AbstractGeneratedKeyEntity implements SAML2IdP @Min(0) @Max(1) @Column(nullable = false) + private Integer createUnmatching; + + @Min(0) + @Max(1) + @Column(nullable = false) + private Integer updateMatching; + + @Min(0) + @Max(1) + @Column(nullable = false) private Integer useDeflateEncoding; @Column(nullable = false) private SAML2BindingType bindingType; + @OneToOne(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "idp") + private JPASAML2UserTemplate userTemplate; + + @ElementCollection(fetch = FetchType.EAGER) + @Column(name = "actionClassName") + @CollectionTable(name = TABLE + "_actionsClassNames", + joinColumns = + @JoinColumn(name = "saml2IdP_id", referencedColumnName = "id")) + private Set<String> actionsClassNames = new HashSet<>(); + @Override public String getEntityID() { return entityID; @@ -101,6 +128,26 @@ public class JPASAML2IdP extends AbstractGeneratedKeyEntity implements SAML2IdP } @Override + public boolean isCreateUnmatching() { + return isBooleanAsInteger(createUnmatching); + } + + @Override + public void setCreateUnmatching(final boolean createUnmatching) { + this.createUnmatching = getBooleanAsInteger(createUnmatching); + } + + @Override + public boolean isUpdateMatching() { + return isBooleanAsInteger(updateMatching); + } + + @Override + public void setUpdateMatching(final boolean updateMatching) { + this.updateMatching = getBooleanAsInteger(updateMatching); + } + + @Override public boolean isUseDeflateEncoding() { return isBooleanAsInteger(useDeflateEncoding); } @@ -121,6 +168,17 @@ public class JPASAML2IdP extends AbstractGeneratedKeyEntity implements SAML2IdP } @Override + public SAML2UserTemplate getUserTemplate() { + return userTemplate; + } + + @Override + public void setUserTemplate(final SAML2UserTemplate userTemplate) { + checkType(userTemplate, JPASAML2UserTemplate.class); + this.userTemplate = (JPASAML2UserTemplate) userTemplate; + } + + @Override public boolean add(final SAML2IdPItem item) { checkType(item, JPASAML2IdPItem.class); return items.contains((JPASAML2IdPItem) item) || items.add((JPASAML2IdPItem) item); @@ -148,4 +206,8 @@ public class JPASAML2IdP extends AbstractGeneratedKeyEntity implements SAML2IdP this.add(item); } + @Override + public Set<String> getActionsClassNames() { + return actionsClassNames; + } } http://git-wip-us.apache.org/repos/asf/syncope/blob/f1c004bf/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2UserTemplate.java ---------------------------------------------------------------------- diff --git a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2UserTemplate.java b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2UserTemplate.java new file mode 100644 index 0000000..538fa94 --- /dev/null +++ b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2UserTemplate.java @@ -0,0 +1,52 @@ +/* + * 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.persistence.jpa.entity; + +import javax.persistence.Entity; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.persistence.UniqueConstraint; +import org.apache.syncope.core.persistence.api.entity.SAML2IdP; +import org.apache.syncope.core.persistence.api.entity.SAML2UserTemplate; +import org.apache.syncope.core.persistence.jpa.entity.resource.AbstractAnyTemplate; + +@Entity +@Table(name = JPASAML2UserTemplate.TABLE, uniqueConstraints = + @UniqueConstraint(columnNames = { "idp_id" })) +public class JPASAML2UserTemplate extends AbstractAnyTemplate implements SAML2UserTemplate { + + private static final long serialVersionUID = -4575039890434426856L; + + public static final String TABLE = "SAML2UserTemplate"; + + @ManyToOne + private JPASAML2IdP idp; + + @Override + public SAML2IdP getIdP() { + return idp; + } + + @Override + public void setIdP(final SAML2IdP idp) { + checkType(idp, JPASAML2IdP.class); + this.idp = (JPASAML2IdP) idp; + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/f1c004bf/ext/saml2sp/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/SAML2IdPActions.java ---------------------------------------------------------------------- diff --git a/ext/saml2sp/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/SAML2IdPActions.java b/ext/saml2sp/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/SAML2IdPActions.java new file mode 100644 index 0000000..6f23804 --- /dev/null +++ b/ext/saml2sp/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/SAML2IdPActions.java @@ -0,0 +1,34 @@ +/* + * 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.provisioning.api; + +import org.apache.syncope.common.lib.patch.UserPatch; +import org.apache.syncope.common.lib.to.SAML2LoginResponseTO; +import org.apache.syncope.common.lib.to.UserTO; + +public interface SAML2IdPActions { + + UserTO beforeCreate(UserTO input, SAML2LoginResponseTO loginResponse); + + UserTO afterCreate(UserTO input, SAML2LoginResponseTO loginResponse); + + UserPatch beforeUpdate(UserPatch input, SAML2LoginResponseTO loginResponse); + + UserTO afterUpdate(UserTO input, SAML2LoginResponseTO loginResponse); +} http://git-wip-us.apache.org/repos/asf/syncope/blob/f1c004bf/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultSAML2IdPActions.java ---------------------------------------------------------------------- diff --git a/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultSAML2IdPActions.java b/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultSAML2IdPActions.java new file mode 100644 index 0000000..ba5fc40 --- /dev/null +++ b/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultSAML2IdPActions.java @@ -0,0 +1,48 @@ +/* + * 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.provisioning.java; + +import org.apache.syncope.common.lib.patch.UserPatch; +import org.apache.syncope.common.lib.to.SAML2LoginResponseTO; +import org.apache.syncope.common.lib.to.UserTO; +import org.apache.syncope.core.provisioning.api.SAML2IdPActions; + +public class DefaultSAML2IdPActions implements SAML2IdPActions { + + @Override + public UserTO beforeCreate(final UserTO input, final SAML2LoginResponseTO loginResponse) { + return input; + } + + @Override + public UserTO afterCreate(final UserTO input, final SAML2LoginResponseTO loginResponse) { + return input; + } + + @Override + public UserPatch beforeUpdate(final UserPatch input, final SAML2LoginResponseTO loginResponse) { + return input; + } + + @Override + public UserTO afterUpdate(final UserTO input, final SAML2LoginResponseTO loginResponse) { + return input; + } + +} http://git-wip-us.apache.org/repos/asf/syncope/blob/f1c004bf/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java ---------------------------------------------------------------------- diff --git a/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java b/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java index b2668c5..2f2f9d0 100644 --- a/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java +++ b/ext/saml2sp/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SAML2IdPDataBinderImpl.java @@ -24,6 +24,7 @@ import org.apache.syncope.common.lib.SyncopeClientException; import org.apache.syncope.common.lib.to.AnyTypeClassTO; import org.apache.syncope.common.lib.to.ItemTO; import org.apache.syncope.common.lib.to.SAML2IdPTO; +import org.apache.syncope.common.lib.to.UserTO; import org.apache.syncope.common.lib.types.AnyTypeKind; import org.apache.syncope.common.lib.types.ClientExceptionType; import org.apache.syncope.common.lib.types.MappingPurpose; @@ -36,6 +37,7 @@ import org.apache.syncope.core.persistence.api.entity.PlainSchema; import org.apache.syncope.core.persistence.api.entity.SAML2EntityFactory; import org.apache.syncope.core.persistence.api.entity.SAML2IdP; import org.apache.syncope.core.persistence.api.entity.SAML2IdPItem; +import org.apache.syncope.core.persistence.api.entity.SAML2UserTemplate; import org.apache.syncope.core.persistence.api.entity.VirSchema; import org.apache.syncope.core.provisioning.api.IntAttrName; import org.apache.syncope.core.provisioning.api.data.SAML2IdPDataBinder; @@ -168,9 +170,24 @@ public class SAML2IdPDataBinderImpl implements SAML2IdPDataBinder { idp.setEntityID(idpTO.getEntityID()); idp.setName(idpTO.getName()); idp.setMetadata(Base64.decode(idpTO.getMetadata())); + idp.setCreateUnmatching(idpTO.isCreateUnmatching()); + idp.setUpdateMatching(idpTO.isUpdateMatching()); idp.setUseDeflateEncoding(idpTO.isUseDeflateEncoding()); idp.setBindingType(idpTO.getBindingType()); + if (idpTO.getUserTemplate() == null) { + idp.setUserTemplate(null); + } else { + SAML2UserTemplate userTemplate = idp.getUserTemplate(); + if (userTemplate == null) { + userTemplate = entityFactory.newEntity(SAML2UserTemplate.class); + userTemplate.setAnyType(anyTypeDAO.findUser()); + userTemplate.setIdP(idp); + idp.setUserTemplate(userTemplate); + } + userTemplate.set(idpTO.getUserTemplate()); + } + idp.getItems().clear(); AnyTypeClassTO allowedSchemas = new AnyTypeClassTO(); for (AnyTypeClass anyTypeClass : anyTypeDAO.findUser().getClasses()) { @@ -186,6 +203,9 @@ public class SAML2IdPDataBinderImpl implements SAML2IdPDataBinder { } populateItems(idpTO, idp, allowedSchemas); + idp.getActionsClassNames().clear(); + idp.getActionsClassNames().addAll(idpTO.getActionsClassNames()); + return saml2IdPDAO.save(idp); } @@ -213,10 +233,18 @@ public class SAML2IdPDataBinderImpl implements SAML2IdPDataBinder { idpTO.setName(idp.getName()); idpTO.setUseDeflateEncoding(idp.isUseDeflateEncoding()); idpTO.setBindingType(idp.getBindingType()); + idpTO.setCreateUnmatching(idp.isCreateUnmatching()); + idpTO.setUpdateMatching(idp.isUpdateMatching()); idpTO.setMetadata(Base64.encode(idp.getMetadata())); + if (idp.getUserTemplate() != null) { + idpTO.setUserTemplate((UserTO) idp.getUserTemplate().get()); + } + populateItems(idp, idpTO); + idpTO.getActionsClassNames().addAll(idp.getActionsClassNames()); + return idpTO; } } http://git-wip-us.apache.org/repos/asf/syncope/blob/f1c004bf/ext/saml2sp/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2IdPService.java ---------------------------------------------------------------------- diff --git a/ext/saml2sp/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2IdPService.java b/ext/saml2sp/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2IdPService.java index 5761c01..0d528c3 100644 --- a/ext/saml2sp/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2IdPService.java +++ b/ext/saml2sp/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SAML2IdPService.java @@ -20,6 +20,7 @@ package org.apache.syncope.common.rest.api.service; import java.io.InputStream; import java.util.List; +import java.util.Set; import javax.validation.constraints.NotNull; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; @@ -40,6 +41,16 @@ import org.apache.syncope.common.lib.to.SAML2IdPTO; public interface SAML2IdPService extends JAXRSService { /** + * Returns the list of available SAML2IdPActions implementations. + * + * @return the list of available SAML2IdPActions implementations + */ + @GET + @Path("actionsClasses") + @Produces({ MediaType.APPLICATION_JSON }) + Set<String> getActionsClasses(); + + /** * Returns a list of all defined SAML 2.0 Identity Providers. * * @return list of all defined SAML 2.0 Identity Providers http://git-wip-us.apache.org/repos/asf/syncope/blob/f1c004bf/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2IdPServiceImpl.java ---------------------------------------------------------------------- diff --git a/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2IdPServiceImpl.java b/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2IdPServiceImpl.java index 1f2790f..ebda30d 100644 --- a/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2IdPServiceImpl.java +++ b/ext/saml2sp/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/SAML2IdPServiceImpl.java @@ -20,6 +20,7 @@ package org.apache.syncope.core.rest.cxf.service; import java.io.InputStream; import java.util.List; +import java.util.Set; import javax.ws.rs.core.Response; import org.apache.syncope.common.lib.to.SAML2IdPTO; import org.apache.syncope.common.rest.api.RESTHeaders; @@ -35,6 +36,11 @@ public class SAML2IdPServiceImpl extends AbstractServiceImpl implements SAML2IdP private SAML2IdPLogic logic; @Override + public Set<String> getActionsClasses() { + return logic.getActionsClasses(); + } + + @Override public List<SAML2IdPTO> list() { return logic.list(); } http://git-wip-us.apache.org/repos/asf/syncope/blob/f1c004bf/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SAML2ITCase.java ---------------------------------------------------------------------- diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SAML2ITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SAML2ITCase.java index f0cd386..b87db1b 100644 --- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SAML2ITCase.java +++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SAML2ITCase.java @@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -48,6 +49,7 @@ import org.apache.syncope.common.lib.to.SAML2IdPTO; import org.apache.syncope.common.lib.to.SAML2LoginResponseTO; import org.apache.syncope.common.lib.to.SAML2ReceivedResponseTO; import org.apache.syncope.common.lib.to.SAML2RequestTO; +import org.apache.syncope.common.lib.to.UserTO; import org.apache.syncope.common.rest.api.service.SAML2SPService; import org.apache.syncope.fit.AbstractITCase; import org.apache.syncope.fit.SAML2SPDetector; @@ -171,13 +173,20 @@ public class SAML2ITCase extends AbstractITCase { SAML2IdPTO ssoCircle = ssoCircleOpt.get(); assertNotNull(ssoCircle); + assertFalse(ssoCircle.isCreateUnmatching()); + assertNull(ssoCircle.getUserTemplate()); assertFalse(ssoCircle.getItems().isEmpty()); assertNotNull(ssoCircle.getConnObjectKeyItem()); assertNotEquals("email", ssoCircle.getConnObjectKeyItem().getIntAttrName()); assertNotEquals("EmailAddress", ssoCircle.getConnObjectKeyItem().getExtAttrName()); - ssoCircle.getItems().clear(); + ssoCircle.setCreateUnmatching(true); + + UserTO userTemplate = new UserTO(); + userTemplate.setRealm("'/'"); + ssoCircle.setUserTemplate(userTemplate); + ssoCircle.getItems().clear(); ItemTO keyMapping = new ItemTO(); keyMapping.setIntAttrName("email"); keyMapping.setExtAttrName("EmailAddress"); @@ -186,6 +195,8 @@ public class SAML2ITCase extends AbstractITCase { saml2IdPService.update(ssoCircle); ssoCircle = saml2IdPService.read(ssoCircle.getKey()); + assertTrue(ssoCircle.isCreateUnmatching()); + assertEquals(userTemplate, ssoCircle.getUserTemplate()); assertEquals("email", ssoCircle.getConnObjectKeyItem().getIntAttrName()); assertEquals("EmailAddress", ssoCircle.getConnObjectKeyItem().getExtAttrName()); }