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