1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.core.provisioning.java.data;
20
21 import java.text.ParseException;
22 import java.util.Base64;
23 import java.util.stream.Collectors;
24 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
25 import org.apache.syncope.common.lib.SyncopeClientException;
26 import org.apache.syncope.common.lib.to.Item;
27 import org.apache.syncope.common.lib.to.SAML2SP4UIIdPTO;
28 import org.apache.syncope.common.lib.to.UserTO;
29 import org.apache.syncope.common.lib.types.AnyTypeKind;
30 import org.apache.syncope.common.lib.types.ClientExceptionType;
31 import org.apache.syncope.common.lib.types.MappingPurpose;
32 import org.apache.syncope.common.lib.types.SchemaType;
33 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
34 import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
35 import org.apache.syncope.core.persistence.api.dao.SAML2SP4UIIdPDAO;
36 import org.apache.syncope.core.persistence.api.entity.Entity;
37 import org.apache.syncope.core.persistence.api.entity.Implementation;
38 import org.apache.syncope.core.persistence.api.entity.SAML2SP4UIEntityFactory;
39 import org.apache.syncope.core.persistence.api.entity.SAML2SP4UIIdP;
40 import org.apache.syncope.core.persistence.api.entity.SAML2SP4UIUserTemplate;
41 import org.apache.syncope.core.provisioning.api.IntAttrName;
42 import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
43 import org.apache.syncope.core.provisioning.api.data.SAML2SP4UIIdPDataBinder;
44 import org.apache.syncope.core.provisioning.api.jexl.JexlUtils;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 public class SAML2SP4UIIdPDataBinderImpl implements SAML2SP4UIIdPDataBinder {
49
50 protected static final Logger LOG = LoggerFactory.getLogger(SAML2SP4UIIdPDataBinder.class);
51
52 protected final AnyTypeDAO anyTypeDAO;
53
54 protected final SAML2SP4UIIdPDAO idapDAO;
55
56 protected final ImplementationDAO implementationDAO;
57
58 protected final SAML2SP4UIEntityFactory entityFactory;
59
60 protected final IntAttrNameParser intAttrNameParser;
61
62 public SAML2SP4UIIdPDataBinderImpl(
63 final AnyTypeDAO anyTypeDAO,
64 final SAML2SP4UIIdPDAO idapDAO,
65 final ImplementationDAO implementationDAO,
66 final SAML2SP4UIEntityFactory entityFactory,
67 final IntAttrNameParser intAttrNameParser) {
68
69 this.anyTypeDAO = anyTypeDAO;
70 this.idapDAO = idapDAO;
71 this.implementationDAO = implementationDAO;
72 this.entityFactory = entityFactory;
73 this.intAttrNameParser = intAttrNameParser;
74 }
75
76 @Override
77 public SAML2SP4UIIdP create(final SAML2SP4UIIdPTO idpTO) {
78 return update(entityFactory.newEntity(SAML2SP4UIIdP.class), idpTO);
79 }
80
81 protected void populateItems(final SAML2SP4UIIdPTO idpTO, final SAML2SP4UIIdP idp) {
82 SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
83 SyncopeClientException invalidMapping =
84 SyncopeClientException.build(ClientExceptionType.InvalidMapping);
85 SyncopeClientException requiredValuesMissing =
86 SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
87
88 idpTO.getItems().forEach(itemTO -> {
89 if (itemTO == null) {
90 LOG.error("Null {}", Item.class.getSimpleName());
91 invalidMapping.getElements().add("Null " + Item.class.getSimpleName());
92 } else if (itemTO.getIntAttrName() == null) {
93 requiredValuesMissing.getElements().add("intAttrName");
94 scce.addException(requiredValuesMissing);
95 } else {
96 IntAttrName intAttrName = null;
97 try {
98 intAttrName = intAttrNameParser.parse(itemTO.getIntAttrName(), AnyTypeKind.USER);
99 } catch (ParseException e) {
100 LOG.error("Invalid intAttrName '{}' specified, ignoring", itemTO.getIntAttrName(), e);
101 }
102
103 if (intAttrName == null || intAttrName.getSchemaType() == null && intAttrName.getField() == null) {
104 LOG.error("'{}' not existing", itemTO.getIntAttrName());
105 invalidMapping.getElements().add('\'' + itemTO.getIntAttrName() + "' not existing");
106 } else {
107
108 if (!JexlUtils.isExpressionValid(itemTO.getMandatoryCondition() == null
109 ? "false" : itemTO.getMandatoryCondition())) {
110
111 SyncopeClientException invalidMandatoryCondition = SyncopeClientException.build(
112 ClientExceptionType.InvalidValues);
113 invalidMandatoryCondition.getElements().add(itemTO.getMandatoryCondition());
114 scce.addException(invalidMandatoryCondition);
115 }
116
117 Item item = new Item();
118 item.setIntAttrName(itemTO.getIntAttrName());
119 item.setExtAttrName(itemTO.getExtAttrName());
120 item.setMandatoryCondition(itemTO.getMandatoryCondition());
121 item.setConnObjectKey(itemTO.isConnObjectKey());
122 item.setPassword(itemTO.isPassword());
123 item.setPropagationJEXLTransformer(itemTO.getPropagationJEXLTransformer());
124 item.setPullJEXLTransformer(itemTO.getPullJEXLTransformer());
125 item.setPurpose(MappingPurpose.NONE);
126
127 itemTO.getTransformers().forEach(transformerKey -> {
128 Implementation transformer = implementationDAO.find(transformerKey);
129 if (transformer == null) {
130 LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...",
131 transformerKey);
132 } else {
133 item.getTransformers().add(transformer.getKey());
134 }
135
136 item.getTransformers().
137 removeIf(implementation -> !itemTO.getTransformers().contains(implementation));
138 });
139
140 if (item.isConnObjectKey()) {
141 if (intAttrName.getSchemaType() == SchemaType.VIRTUAL) {
142 invalidMapping.getElements().
143 add("Virtual attributes cannot be set as ConnObjectKey");
144 }
145 if ("password".equals(intAttrName.getField())) {
146 invalidMapping.getElements().add(
147 "Password attributes cannot be set as ConnObjectKey");
148 }
149
150 idp.setConnObjectKeyItem(item);
151 } else {
152 idp.getItems().add(item);
153 }
154 }
155 }
156 });
157
158 if (!invalidMapping.getElements().isEmpty()) {
159 scce.addException(invalidMapping);
160 }
161 if (scce.hasExceptions()) {
162 throw scce;
163 }
164 }
165
166 @Override
167 public SAML2SP4UIIdP update(final SAML2SP4UIIdP idp, final SAML2SP4UIIdPTO idpTO) {
168 idp.setEntityID(idpTO.getEntityID());
169 idp.setName(idpTO.getName());
170 idp.setMetadata(Base64.getMimeDecoder().decode(idpTO.getMetadata()));
171 idp.setLogoutSupported(idpTO.isLogoutSupported());
172 idp.setCreateUnmatching(idpTO.isCreateUnmatching());
173 idp.setSelfRegUnmatching(idpTO.isSelfRegUnmatching());
174 idp.setUpdateMatching(idpTO.isUpdateMatching());
175 idp.setBindingType(idpTO.getBindingType());
176
177 if (idpTO.getRequestedAuthnContextProvider() == null) {
178 idp.setRequestedAuthnContextProvider(null);
179 } else {
180 Implementation implementation = implementationDAO.find(idpTO.getRequestedAuthnContextProvider());
181 if (implementation == null) {
182 LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...",
183 idpTO.getRequestedAuthnContextProvider());
184 } else {
185 idp.setRequestedAuthnContextProvider(implementation);
186 }
187 }
188
189 if (idpTO.getUserTemplate() == null) {
190 idp.setUserTemplate(null);
191 } else {
192 SAML2SP4UIUserTemplate userTemplate = idp.getUserTemplate();
193 if (userTemplate == null) {
194 userTemplate = entityFactory.newEntity(SAML2SP4UIUserTemplate.class);
195 userTemplate.setAnyType(anyTypeDAO.findUser());
196 userTemplate.setIdP(idp);
197 idp.setUserTemplate(userTemplate);
198 }
199 userTemplate.set(idpTO.getUserTemplate());
200 }
201
202 idp.getItems().clear();
203 populateItems(idpTO, idp);
204
205 idpTO.getActions().forEach(action -> {
206 Implementation implementation = implementationDAO.find(action);
207 if (implementation == null) {
208 LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...", action);
209 } else {
210 idp.add(implementation);
211 }
212 });
213
214 idp.getActions().removeIf(impl -> !idpTO.getActions().contains(impl.getKey()));
215
216 return idapDAO.save(idp);
217 }
218
219 protected void populateItems(final SAML2SP4UIIdP idp, final SAML2SP4UIIdPTO idpTO) {
220 idp.getItems().forEach(item -> {
221 Item itemTO = new Item();
222 itemTO.setIntAttrName(item.getIntAttrName());
223 itemTO.setExtAttrName(item.getExtAttrName());
224 itemTO.setMandatoryCondition(item.getMandatoryCondition());
225 itemTO.setConnObjectKey(item.isConnObjectKey());
226 itemTO.setPassword(item.isPassword());
227 itemTO.setPropagationJEXLTransformer(item.getPropagationJEXLTransformer());
228 itemTO.setPullJEXLTransformer(item.getPullJEXLTransformer());
229 itemTO.getTransformers().addAll(item.getTransformers());
230 itemTO.setPurpose(MappingPurpose.NONE);
231
232 if (itemTO.isConnObjectKey()) {
233 idpTO.setConnObjectKeyItem(itemTO);
234 } else {
235 idpTO.add(itemTO);
236 }
237 });
238 }
239
240 @Override
241 public SAML2SP4UIIdPTO getIdPTO(final SAML2SP4UIIdP idp) {
242 SAML2SP4UIIdPTO idpTO = new SAML2SP4UIIdPTO();
243
244 idpTO.setKey(idp.getKey());
245 idpTO.setEntityID(idp.getEntityID());
246 idpTO.setName(idp.getName());
247 idpTO.setMetadata(Base64.getMimeEncoder().encodeToString(idp.getMetadata()));
248 idpTO.setLogoutSupported(idp.isLogoutSupported());
249 idpTO.setBindingType(idp.getBindingType());
250 idpTO.setCreateUnmatching(idp.isCreateUnmatching());
251 idpTO.setSelfRegUnmatching(idp.isSelfRegUnmatching());
252 idpTO.setUpdateMatching(idp.isUpdateMatching());
253
254 if (idp.getRequestedAuthnContextProvider() != null) {
255 idpTO.setRequestedAuthnContextProvider(idp.getRequestedAuthnContextProvider().getKey());
256 }
257
258 if (idp.getUserTemplate() != null) {
259 idpTO.setUserTemplate((UserTO) idp.getUserTemplate().get());
260 }
261
262 populateItems(idp, idpTO);
263
264 idpTO.getActions().addAll(idp.getActions().stream().map(Entity::getKey).collect(Collectors.toList()));
265
266 return idpTO;
267 }
268 }