1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.core.logic;
20
21 import java.util.ArrayList;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.concurrent.ConcurrentHashMap;
25 import org.apache.commons.lang3.tuple.Pair;
26 import org.apache.syncope.common.lib.SyncopeClientException;
27 import org.apache.syncope.common.lib.request.AnyCR;
28 import org.apache.syncope.common.lib.request.AnyObjectCR;
29 import org.apache.syncope.common.lib.request.AnyUR;
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.AnyTO;
33 import org.apache.syncope.common.lib.to.PropagationStatus;
34 import org.apache.syncope.common.lib.to.ProvisioningResult;
35 import org.apache.syncope.common.lib.types.ClientExceptionType;
36 import org.apache.syncope.core.logic.api.LogicActions;
37 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
38 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
39 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
40 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
41 import org.apache.syncope.core.persistence.api.entity.AnyType;
42 import org.apache.syncope.core.persistence.api.entity.Realm;
43 import org.apache.syncope.core.provisioning.java.utils.TemplateUtils;
44 import org.apache.syncope.core.spring.implementation.ImplementationManager;
45
46 public abstract class AbstractAnyLogic<TO extends AnyTO, C extends AnyCR, U extends AnyUR>
47 extends AbstractResourceAssociator<TO> {
48
49 protected static final String REST_CONTEXT = "REST";
50
51 protected final RealmDAO realmDAO;
52
53 protected final AnyTypeDAO anyTypeDAO;
54
55 protected final TemplateUtils templateUtils;
56
57 protected final Map<String, LogicActions> perContextActions = new ConcurrentHashMap<>();
58
59 public AbstractAnyLogic(
60 final RealmDAO realmDAO,
61 final AnyTypeDAO anyTypeDAO,
62 final TemplateUtils templateUtils) {
63
64 this.realmDAO = realmDAO;
65 this.anyTypeDAO = anyTypeDAO;
66 this.templateUtils = templateUtils;
67 }
68
69 protected List<LogicActions> getActions(final Realm realm) {
70 List<LogicActions> result = new ArrayList<>();
71
72 realm.getActions().forEach(impl -> {
73 try {
74 result.add(ImplementationManager.build(
75 impl,
76 () -> perContextActions.get(impl.getKey()),
77 instance -> perContextActions.put(impl.getKey(), instance)));
78 } catch (Exception e) {
79 LOG.warn("While building {}", impl, e);
80 }
81 });
82
83 return result;
84 }
85
86 @SuppressWarnings("unchecked")
87 protected Pair<C, List<LogicActions>> beforeCreate(final C input) {
88 Realm realm = realmDAO.findByFullPath(input.getRealm());
89 if (realm == null) {
90 SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
91 sce.getElements().add(input.getRealm());
92 throw sce;
93 }
94
95 AnyType anyType = null;
96 if (input instanceof UserCR) {
97 anyType = anyTypeDAO.findUser();
98 } else if (input instanceof GroupCR) {
99 anyType = anyTypeDAO.findGroup();
100 } else if (input instanceof AnyObjectCR) {
101 anyType = anyTypeDAO.find(((AnyObjectCR) input).getType());
102 }
103 if (anyType == null) {
104 SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidAnyType);
105 throw sce;
106 }
107
108 C anyCR = input;
109
110 templateUtils.apply(anyCR, realm.getTemplate(anyType));
111
112 List<LogicActions> actions = getActions(realm);
113 for (LogicActions action : actions) {
114 anyCR = action.beforeCreate(anyCR);
115 }
116
117 LOG.debug("Input: {}\nOutput: {}\n", input, anyCR);
118
119 return Pair.of(anyCR, actions);
120 }
121
122 @SuppressWarnings("unchecked")
123 protected Pair<U, List<LogicActions>> beforeUpdate(final U input, final String realmPath) {
124 Realm realm = realmDAO.findByFullPath(realmPath);
125 if (realm == null) {
126 SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
127 sce.getElements().add(realmPath);
128 throw sce;
129 }
130
131 U update = input;
132
133 List<LogicActions> actions = getActions(realm);
134 for (LogicActions action : actions) {
135 update = action.beforeUpdate(update);
136 }
137
138 LOG.debug("Input: {}\nOutput: {}\n", input, update);
139
140 return Pair.of(update, actions);
141 }
142
143 @SuppressWarnings("unchecked")
144 protected Pair<TO, List<LogicActions>> beforeDelete(final TO input) {
145 Realm realm = realmDAO.findByFullPath(input.getRealm());
146 if (realm == null) {
147 SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
148 sce.getElements().add(input.getRealm());
149 throw sce;
150 }
151
152 TO any = input;
153
154 List<LogicActions> actions = getActions(realm);
155 for (LogicActions action : actions) {
156 any = action.beforeDelete(any);
157 }
158
159 LOG.debug("Input: {}\nOutput: {}\n", input, any);
160
161 return Pair.of(any, actions);
162 }
163
164 @SuppressWarnings("unchecked")
165 protected ProvisioningResult<TO> afterCreate(
166 final TO input, final List<PropagationStatus> statuses, final List<LogicActions> actions) {
167
168 TO any = input;
169
170 for (LogicActions action : actions) {
171 any = action.afterCreate(any, statuses);
172 }
173
174 ProvisioningResult<TO> result = new ProvisioningResult<>();
175 result.setEntity(any);
176 result.getPropagationStatuses().addAll(statuses);
177
178 return result;
179 }
180
181 protected ProvisioningResult<TO> afterUpdate(
182 final TO input,
183 final List<PropagationStatus> statuses,
184 final List<LogicActions> actions) {
185
186 TO any = input;
187
188 for (LogicActions action : actions) {
189 any = action.afterUpdate(any, statuses);
190 }
191
192 ProvisioningResult<TO> result = new ProvisioningResult<>();
193 result.setEntity(any);
194 result.getPropagationStatuses().addAll(statuses);
195
196 return result;
197 }
198
199 @SuppressWarnings("unchecked")
200 protected ProvisioningResult<TO> afterDelete(
201 final TO input, final List<PropagationStatus> statuses, final List<LogicActions> actions) {
202
203 TO any = input;
204
205 for (LogicActions action : actions) {
206 any = action.afterDelete(any, statuses);
207 }
208
209 ProvisioningResult<TO> result = new ProvisioningResult<>();
210 result.setEntity(any);
211 result.getPropagationStatuses().addAll(statuses);
212
213 return result;
214 }
215
216 public abstract TO read(String key);
217
218 public abstract Pair<Integer, List<TO>> search(
219 SearchCond searchCond,
220 int page, int size, List<OrderByClause> orderBy,
221 String realm,
222 boolean recursive,
223 boolean details);
224
225 public abstract ProvisioningResult<TO> update(U updateReq, boolean nullPriorityAsync);
226
227 public abstract ProvisioningResult<TO> delete(String key, boolean nullPriorityAsync);
228 }