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.lang.reflect.Method;
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.Optional;
25 import java.util.stream.Collectors;
26 import org.apache.commons.lang3.ArrayUtils;
27 import org.apache.commons.lang3.StringUtils;
28 import org.apache.syncope.common.lib.SyncopeClientException;
29 import org.apache.syncope.common.lib.to.DerSchemaTO;
30 import org.apache.syncope.common.lib.to.PlainSchemaTO;
31 import org.apache.syncope.common.lib.to.SchemaTO;
32 import org.apache.syncope.common.lib.to.VirSchemaTO;
33 import org.apache.syncope.common.lib.types.AnyTypeKind;
34 import org.apache.syncope.common.lib.types.ClientExceptionType;
35 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
36 import org.apache.syncope.common.lib.types.SchemaType;
37 import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
38 import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
39 import org.apache.syncope.core.persistence.api.dao.DuplicateException;
40 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
41 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
42 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
43 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
44 import org.apache.syncope.core.persistence.api.entity.DerSchema;
45 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
46 import org.apache.syncope.core.persistence.api.entity.VirSchema;
47 import org.apache.syncope.core.provisioning.api.data.SchemaDataBinder;
48 import org.springframework.security.access.prepost.PreAuthorize;
49 import org.springframework.transaction.annotation.Transactional;
50
51 public class SchemaLogic extends AbstractTransactionalLogic<SchemaTO> {
52
53 protected final PlainSchemaDAO plainSchemaDAO;
54
55 protected final DerSchemaDAO derSchemaDAO;
56
57 protected final VirSchemaDAO virSchemaDAO;
58
59 protected final AnyTypeClassDAO anyTypeClassDAO;
60
61 protected final SchemaDataBinder binder;
62
63 public SchemaLogic(
64 final PlainSchemaDAO plainSchemaDAO,
65 final DerSchemaDAO derSchemaDAO,
66 final VirSchemaDAO virSchemaDAO,
67 final AnyTypeClassDAO anyTypeClassDAO,
68 final SchemaDataBinder binder) {
69
70 this.plainSchemaDAO = plainSchemaDAO;
71 this.derSchemaDAO = derSchemaDAO;
72 this.virSchemaDAO = virSchemaDAO;
73 this.anyTypeClassDAO = anyTypeClassDAO;
74 this.binder = binder;
75 }
76
77 protected boolean doesSchemaExist(final SchemaType schemaType, final String name) {
78 boolean found;
79
80 switch (schemaType) {
81 case VIRTUAL:
82 found = virSchemaDAO.find(name) != null;
83 break;
84
85 case DERIVED:
86 found = derSchemaDAO.find(name) != null;
87 break;
88
89 case PLAIN:
90 found = plainSchemaDAO.find(name) != null;
91 break;
92
93 default:
94 found = false;
95 }
96
97 return found;
98 }
99
100 @PreAuthorize("hasRole('" + IdRepoEntitlement.SCHEMA_CREATE + "')")
101 @SuppressWarnings("unchecked")
102 public <T extends SchemaTO> T create(final SchemaType schemaType, final T schemaTO) {
103 if (StringUtils.isBlank(schemaTO.getKey())) {
104 SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
105 sce.getElements().add("Schema key");
106 throw sce;
107 }
108
109 if (doesSchemaExist(schemaType, schemaTO.getKey())) {
110 throw new DuplicateException(schemaType + "/" + schemaTO.getKey());
111 }
112
113 T created;
114 switch (schemaType) {
115 case VIRTUAL:
116 created = (T) binder.getVirSchemaTO(binder.create((VirSchemaTO) schemaTO).getKey());
117 break;
118
119 case DERIVED:
120 created = (T) binder.getDerSchemaTO(binder.create((DerSchemaTO) schemaTO).getKey());
121 break;
122
123 case PLAIN:
124 default:
125 created = (T) binder.getPlainSchemaTO(binder.create((PlainSchemaTO) schemaTO).getKey());
126 }
127 return created;
128 }
129
130 @PreAuthorize("hasRole('" + IdRepoEntitlement.SCHEMA_DELETE + "')")
131 public void delete(final SchemaType schemaType, final String schemaKey) {
132 if (!doesSchemaExist(schemaType, schemaKey)) {
133 throw new NotFoundException(schemaType + "/" + schemaKey);
134 }
135
136 switch (schemaType) {
137 case VIRTUAL:
138 virSchemaDAO.delete(schemaKey);
139 break;
140
141 case DERIVED:
142 derSchemaDAO.delete(schemaKey);
143 break;
144
145 case PLAIN:
146 default:
147 plainSchemaDAO.delete(schemaKey);
148 }
149 }
150
151 @PreAuthorize("isAuthenticated()")
152 @Transactional(readOnly = true)
153 @SuppressWarnings("unchecked")
154 public <T extends SchemaTO> List<T> search(
155 final SchemaType schemaType, final List<String> anyTypeClasses, final String keyword) {
156
157 List<AnyTypeClass> classes = new ArrayList<>(Optional.ofNullable(anyTypeClasses).map(List::size).orElse(0));
158 if (anyTypeClasses != null) {
159 anyTypeClasses.remove(AnyTypeKind.USER.name());
160 anyTypeClasses.remove(AnyTypeKind.GROUP.name());
161 anyTypeClasses.forEach(anyTypeClass -> {
162 AnyTypeClass clazz = anyTypeClassDAO.find(anyTypeClass);
163 if (clazz == null) {
164 LOG.warn("Ignoring invalid {}: {}", AnyTypeClass.class.getSimpleName(), anyTypeClass);
165 } else {
166 classes.add(clazz);
167 }
168 });
169 }
170
171 List<T> result;
172 switch (schemaType) {
173 case VIRTUAL:
174 result = (classes.isEmpty()
175 ? Optional.ofNullable(keyword).
176 map(k -> virSchemaDAO.findByKeyword(k)).
177 orElseGet(() -> virSchemaDAO.findAll())
178 : virSchemaDAO.findByAnyTypeClasses(classes)).stream().
179 map(schema -> (T) binder.getVirSchemaTO(schema.getKey())).collect(Collectors.toList());
180 break;
181
182 case DERIVED:
183 result = (classes.isEmpty()
184 ? Optional.ofNullable(keyword).
185 map(k -> derSchemaDAO.findByKeyword(k)).
186 orElseGet(() -> derSchemaDAO.findAll())
187 : derSchemaDAO.findByAnyTypeClasses(classes)).stream().
188 map(schema -> (T) binder.getDerSchemaTO(schema.getKey())).collect(Collectors.toList());
189 break;
190
191 case PLAIN:
192 default:
193 result = (classes.isEmpty()
194 ? Optional.ofNullable(keyword).
195 map(k -> plainSchemaDAO.findByKeyword(k)).
196 orElseGet(() -> plainSchemaDAO.findAll())
197 : plainSchemaDAO.findByAnyTypeClasses(classes)).stream().
198 map(schema -> (T) binder.getPlainSchemaTO(schema.getKey())).collect(Collectors.toList());
199 }
200
201 return result;
202 }
203
204 @PreAuthorize("isAuthenticated()")
205 @SuppressWarnings("unchecked")
206 public <T extends SchemaTO> T read(final SchemaType schemaType, final String schemaKey) {
207 T read;
208 switch (schemaType) {
209 case VIRTUAL:
210 read = (T) binder.getVirSchemaTO(schemaKey);
211 break;
212
213 case DERIVED:
214 read = (T) binder.getDerSchemaTO(schemaKey);
215 break;
216
217 case PLAIN:
218 default:
219 read = (T) binder.getPlainSchemaTO(schemaKey);
220 }
221
222 return read;
223 }
224
225 @PreAuthorize("hasRole('" + IdRepoEntitlement.SCHEMA_UPDATE + "')")
226 public <T extends SchemaTO> void update(final SchemaType schemaType, final T schemaTO) {
227 if (!doesSchemaExist(schemaType, schemaTO.getKey())) {
228 throw new NotFoundException(schemaType + "/" + schemaTO.getKey());
229 }
230
231 switch (schemaType) {
232 case VIRTUAL:
233 VirSchema virSchema = Optional.ofNullable(virSchemaDAO.find(schemaTO.getKey())).
234 orElseThrow(() -> new NotFoundException("Virtual Schema '" + schemaTO.getKey() + '\''));
235
236 binder.update((VirSchemaTO) schemaTO, virSchema);
237 break;
238
239 case DERIVED:
240 DerSchema derSchema = Optional.ofNullable(derSchemaDAO.find(schemaTO.getKey())).
241 orElseThrow(() -> new NotFoundException("Derived Schema '" + schemaTO.getKey() + '\''));
242
243 binder.update((DerSchemaTO) schemaTO, derSchema);
244 break;
245
246 case PLAIN:
247 default:
248 PlainSchema plainSchema = Optional.ofNullable(plainSchemaDAO.find(schemaTO.getKey())).
249 orElseThrow(() -> new NotFoundException("Plain Schema '" + schemaTO.getKey() + '\''));
250
251 binder.update((PlainSchemaTO) schemaTO, plainSchema);
252 }
253 }
254
255 @Override
256 protected SchemaTO resolveReference(final Method method, final Object... args)
257 throws UnresolvedReferenceException {
258
259 String key = null;
260 if (ArrayUtils.isNotEmpty(args)) {
261 for (int i = 0; key == null && i < args.length; i++) {
262 if (args[i] instanceof String) {
263 key = (String) args[i];
264 } else if (args[i] instanceof SchemaTO) {
265 key = ((SchemaTO) args[i]).getKey();
266 }
267 }
268 }
269
270 if (key != null) {
271 try {
272 SchemaTO result = null;
273
274 PlainSchema plainSchema = plainSchemaDAO.find(key);
275 if (plainSchema == null) {
276 DerSchema derSchema = derSchemaDAO.find(key);
277 if (derSchema == null) {
278 VirSchema virSchema = virSchemaDAO.find(key);
279 if (virSchema != null) {
280 result = binder.getVirSchemaTO(key);
281 }
282 } else {
283 result = binder.getDerSchemaTO(key);
284 }
285 } else {
286 result = binder.getPlainSchemaTO(key);
287 }
288
289 return result;
290 } catch (Throwable ignore) {
291 LOG.debug("Unresolved reference", ignore);
292 throw new UnresolvedReferenceException(ignore);
293 }
294 }
295
296 throw new UnresolvedReferenceException();
297 }
298 }