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.utils;
20
21 import java.util.Map;
22 import java.util.Objects;
23 import java.util.Optional;
24 import org.apache.commons.jexl3.MapContext;
25 import org.apache.commons.lang3.StringUtils;
26 import org.apache.syncope.common.lib.Attr;
27 import org.apache.syncope.common.lib.EntityTOUtils;
28 import org.apache.syncope.common.lib.RealmMember;
29 import org.apache.syncope.common.lib.SyncopeClientException;
30 import org.apache.syncope.common.lib.request.GroupCR;
31 import org.apache.syncope.common.lib.request.UserCR;
32 import org.apache.syncope.common.lib.to.AnyObjectTO;
33 import org.apache.syncope.common.lib.to.AnyTO;
34 import org.apache.syncope.common.lib.to.GroupTO;
35 import org.apache.syncope.common.lib.to.GroupableRelatableTO;
36 import org.apache.syncope.common.lib.to.UserTO;
37 import org.apache.syncope.common.lib.types.ClientExceptionType;
38 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
39 import org.apache.syncope.core.persistence.api.dao.UserDAO;
40 import org.apache.syncope.core.persistence.api.entity.AnyTemplate;
41 import org.apache.syncope.core.provisioning.api.jexl.JexlUtils;
42 import org.springframework.transaction.annotation.Transactional;
43
44 public class TemplateUtils {
45
46 protected static Attr evaluateAttr(final Attr template, final MapContext jexlContext) {
47 Attr result = new Attr();
48 result.setSchema(template.getSchema());
49
50 if (template.getValues() != null && !template.getValues().isEmpty()) {
51 template.getValues().forEach(value -> {
52 String evaluated = JexlUtils.evaluate(value, jexlContext).toString();
53 if (StringUtils.isNotBlank(evaluated)) {
54 result.getValues().add(evaluated);
55 }
56 });
57 }
58
59 return result;
60 }
61
62 protected static void fill(final RealmMember realmMember, final RealmMember template) {
63 MapContext jexlContext = new MapContext();
64 JexlUtils.addFieldsToContext(realmMember, jexlContext);
65 JexlUtils.addAttrsToContext(realmMember.getPlainAttrs(), jexlContext);
66 JexlUtils.addAttrsToContext(realmMember.getDerAttrs(), jexlContext);
67 JexlUtils.addAttrsToContext(realmMember.getVirAttrs(), jexlContext);
68
69 if (template.getRealm() != null) {
70 String evaluated = JexlUtils.evaluate(template.getRealm(), jexlContext).toString();
71 if (StringUtils.isNotBlank(evaluated)) {
72 realmMember.setRealm(evaluated);
73 }
74 }
75
76 Map<String, Attr> currentAttrMap = EntityTOUtils.buildAttrMap(realmMember.getPlainAttrs());
77 for (Attr templatePlainAttr : template.getPlainAttrs()) {
78 if (!templatePlainAttr.getValues().isEmpty()
79 && (!currentAttrMap.containsKey(templatePlainAttr.getSchema())
80 || currentAttrMap.get(templatePlainAttr.getSchema()).getValues().isEmpty())) {
81
82 Attr evaluated = evaluateAttr(templatePlainAttr, jexlContext);
83 if (!evaluated.getValues().isEmpty()) {
84 realmMember.getPlainAttrs().add(evaluated);
85 jexlContext.set(evaluated.getSchema(), evaluated.getValues().get(0));
86 }
87 }
88 }
89
90 currentAttrMap = EntityTOUtils.buildAttrMap(realmMember.getDerAttrs());
91 for (Attr templateDerAttr : template.getDerAttrs()) {
92 if (!currentAttrMap.containsKey(templateDerAttr.getSchema())) {
93 realmMember.getDerAttrs().add(templateDerAttr);
94 }
95 }
96
97 currentAttrMap = EntityTOUtils.buildAttrMap(realmMember.getVirAttrs());
98 for (Attr templateVirAttr : template.getVirAttrs()) {
99 if (!templateVirAttr.getValues().isEmpty()
100 && (!currentAttrMap.containsKey(templateVirAttr.getSchema())
101 || currentAttrMap.get(templateVirAttr.getSchema()).getValues().isEmpty())) {
102
103 Attr evaluated = evaluateAttr(templateVirAttr, jexlContext);
104 if (!evaluated.getValues().isEmpty()) {
105 realmMember.getVirAttrs().add(evaluated);
106 jexlContext.set(evaluated.getSchema(), evaluated.getValues().get(0));
107 }
108 }
109 }
110
111 realmMember.getResources().addAll(template.getResources());
112
113 realmMember.getAuxClasses().addAll(template.getAuxClasses());
114 }
115
116 protected static void fillRelationships(final GroupableRelatableTO any, final GroupableRelatableTO template) {
117 template.getRelationships().stream().
118 filter(relationship -> any.getRelationship(
119 relationship.getOtherEndKey(), relationship.getOtherEndKey()).isEmpty()).
120 forEachOrdered(relationship -> any.getRelationships().add(relationship));
121 }
122
123 protected static void fillMemberships(final GroupableRelatableTO any, final GroupableRelatableTO template) {
124 template.getMemberships().stream().
125 filter(membership -> any.getMembership(membership.getGroupKey()).isEmpty()).
126 forEachOrdered(membership -> any.getMemberships().add(membership));
127 }
128
129 protected final UserDAO userDAO;
130
131 protected final GroupDAO groupDAO;
132
133 public TemplateUtils(final UserDAO userDAO, final GroupDAO groupDAO) {
134 this.userDAO = userDAO;
135 this.groupDAO = groupDAO;
136 }
137
138 @Transactional(readOnly = true)
139 public void apply(final RealmMember realmMember, final Optional<? extends AnyTemplate> template) {
140 template.ifPresent(anyTemplate -> apply(realmMember, anyTemplate.get()));
141 }
142
143 @Transactional(readOnly = true)
144 public void apply(final RealmMember realmMember, final AnyTO template) {
145 fill(realmMember, template);
146
147 MapContext jexlContext = new MapContext();
148 JexlUtils.addFieldsToContext(realmMember, jexlContext);
149 JexlUtils.addAttrsToContext(realmMember.getPlainAttrs(), jexlContext);
150 JexlUtils.addAttrsToContext(realmMember.getDerAttrs(), jexlContext);
151 JexlUtils.addAttrsToContext(realmMember.getVirAttrs(), jexlContext);
152
153 if (template instanceof AnyObjectTO) {
154 fillRelationships((GroupableRelatableTO) realmMember, ((GroupableRelatableTO) template));
155 fillMemberships((GroupableRelatableTO) realmMember, ((GroupableRelatableTO) template));
156 } else if (template instanceof UserTO) {
157 if (StringUtils.isNotBlank(((UserTO) template).getUsername())) {
158 String evaluated = JexlUtils.evaluate(((UserTO) template).getUsername(), jexlContext).toString();
159 if (StringUtils.isNotBlank(evaluated)) {
160 if (realmMember instanceof UserTO) {
161 ((UserTO) realmMember).setUsername(evaluated);
162 } else if (realmMember instanceof UserCR) {
163 ((UserCR) realmMember).setUsername(evaluated);
164 }
165 }
166 }
167
168 if (StringUtils.isNotBlank(((UserTO) template).getPassword())) {
169 String evaluated = JexlUtils.evaluate(((UserTO) template).getPassword(), jexlContext).toString();
170 if (StringUtils.isNotBlank(evaluated)) {
171 if (realmMember instanceof UserTO) {
172 ((UserTO) realmMember).setPassword(evaluated);
173 } else if (realmMember instanceof UserCR) {
174 ((UserCR) realmMember).setPassword(evaluated);
175 }
176 }
177 }
178
179 if (((UserTO) template).isMustChangePassword()) {
180 if (realmMember instanceof UserTO) {
181 ((UserTO) realmMember).setMustChangePassword(true);
182 } else if (realmMember instanceof UserCR) {
183 ((UserCR) realmMember).setMustChangePassword(true);
184 }
185 }
186
187 fillRelationships((GroupableRelatableTO) realmMember, ((GroupableRelatableTO) template));
188 fillMemberships((GroupableRelatableTO) realmMember, ((GroupableRelatableTO) template));
189
190 ((UserTO) template).getRoles().forEach(role -> {
191 if (realmMember instanceof UserTO
192 && !((UserTO) realmMember).getRoles().contains(role)) {
193
194 ((UserTO) realmMember).getRoles().add(role);
195 } else if (realmMember instanceof UserCR
196 && !((UserCR) realmMember).getRoles().contains(role)) {
197
198 ((UserCR) realmMember).getRoles().add(role);
199 }
200 });
201
202 ((UserTO) template).getLinkedAccounts().forEach(account -> {
203 if (realmMember instanceof UserTO && ((UserTO) realmMember).getLinkedAccounts().stream().
204 noneMatch(a -> Objects.equals(account.getConnObjectKeyValue(), a.getConnObjectKeyValue())
205 && Objects.equals(account.getResource(), a.getResource()))) {
206
207 ((UserTO) realmMember).getLinkedAccounts().add(account);
208 } else if (realmMember instanceof UserCR && ((UserCR) realmMember).getLinkedAccounts().stream().
209 noneMatch(a -> Objects.equals(account.getConnObjectKeyValue(), a.getConnObjectKeyValue())
210 && Objects.equals(account.getResource(), a.getResource()))) {
211
212 ((UserCR) realmMember).getLinkedAccounts().add(account);
213 }
214 });
215 } else if (template instanceof GroupTO) {
216 if (StringUtils.isNotBlank(((GroupTO) template).getName())) {
217 String evaluated = JexlUtils.evaluate(((GroupTO) template).getName(), jexlContext).toString();
218 if (StringUtils.isNotBlank(evaluated)) {
219 if (realmMember instanceof GroupTO) {
220 ((GroupTO) realmMember).setName(evaluated);
221 } else if (realmMember instanceof GroupCR) {
222 ((GroupCR) realmMember).setName(evaluated);
223 }
224 }
225 }
226
227 Optional.ofNullable(((GroupTO) template).getUserOwner()).map(userDAO::find).ifPresent(userOwner -> {
228 if (realmMember instanceof GroupTO) {
229 ((GroupTO) realmMember).setUserOwner(userOwner.getKey());
230 } else if (realmMember instanceof GroupCR) {
231 ((GroupCR) realmMember).setUserOwner(userOwner.getKey());
232 }
233 });
234 Optional.ofNullable(((GroupTO) template).getGroupOwner()).map(groupDAO::find).ifPresent(groupOwner -> {
235 if (realmMember instanceof GroupTO) {
236 ((GroupTO) realmMember).setGroupOwner(groupOwner.getKey());
237 } else if (realmMember instanceof GroupCR) {
238 ((GroupCR) realmMember).setGroupOwner(groupOwner.getKey());
239 }
240 });
241
242 Optional.ofNullable(((GroupTO) template).getUDynMembershipCond()).ifPresent(udynMembershipCond -> {
243 if (realmMember instanceof GroupTO) {
244 ((GroupTO) realmMember).setUDynMembershipCond(udynMembershipCond);
245 } else if (realmMember instanceof GroupCR) {
246 ((GroupCR) realmMember).setUDynMembershipCond(udynMembershipCond);
247 }
248 });
249
250 ((GroupTO) template).getADynMembershipConds().forEach((anyType, cond) -> {
251 if (realmMember instanceof GroupTO
252 && !((GroupTO) realmMember).getADynMembershipConds().containsKey(anyType)) {
253
254 ((GroupTO) realmMember).getADynMembershipConds().put(anyType, cond);
255 } else if (realmMember instanceof GroupCR
256 && !((GroupCR) realmMember).getADynMembershipConds().containsKey(anyType)) {
257
258 ((GroupCR) realmMember).getADynMembershipConds().put(anyType, cond);
259 }
260 });
261
262 ((GroupTO) template).getTypeExtensions().forEach(typeExt -> {
263 if (realmMember instanceof GroupTO
264 && !((GroupTO) realmMember).getTypeExtensions().contains(typeExt)) {
265
266 ((GroupTO) realmMember).getTypeExtensions().add(typeExt);
267 } else if (realmMember instanceof GroupCR
268 && !((GroupCR) realmMember).getTypeExtensions().contains(typeExt)) {
269
270 ((GroupCR) realmMember).getTypeExtensions().add(typeExt);
271 }
272 });
273 }
274 }
275
276 public static void check(final Map<String, AnyTO> templates, final ClientExceptionType clientExceptionType) {
277 SyncopeClientException sce = SyncopeClientException.build(clientExceptionType);
278
279 templates.values().forEach(value -> {
280 value.getPlainAttrs().stream().
281 filter(attrTO -> !attrTO.getValues().isEmpty()
282 && !JexlUtils.isExpressionValid(attrTO.getValues().get(0))).
283 forEachOrdered(attrTO -> sce.getElements().add("Invalid JEXL: " + attrTO.getValues().get(0)));
284
285 value.getVirAttrs().stream().
286 filter(attrTO -> !attrTO.getValues().isEmpty()
287 && !JexlUtils.isExpressionValid(attrTO.getValues().get(0))).
288 forEachOrdered((attrTO) -> sce.getElements().add("Invalid JEXL: " + attrTO.getValues().get(0)));
289
290 if (value instanceof UserTO) {
291 UserTO template = (UserTO) value;
292 if (StringUtils.isNotBlank(template.getUsername())
293 && !JexlUtils.isExpressionValid(template.getUsername())) {
294
295 sce.getElements().add("Invalid JEXL: " + template.getUsername());
296 }
297 if (StringUtils.isNotBlank(template.getPassword())
298 && !JexlUtils.isExpressionValid(template.getPassword())) {
299
300 sce.getElements().add("Invalid JEXL: " + template.getPassword());
301 }
302 } else if (value instanceof GroupTO) {
303 GroupTO template = (GroupTO) value;
304 if (StringUtils.isNotBlank(template.getName())
305 && !JexlUtils.isExpressionValid(template.getName())) {
306
307 sce.getElements().add("Invalid JEXL: " + template.getName());
308 }
309 }
310 });
311
312 if (!sce.isEmpty()) {
313 throw sce;
314 }
315 }
316 }