View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.fit.core;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertFalse;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertNull;
25  import static org.junit.jupiter.api.Assertions.assertTrue;
26  import static org.junit.jupiter.api.Assertions.fail;
27  
28  import java.io.IOException;
29  import java.util.Base64;
30  import java.util.List;
31  import java.util.Locale;
32  import javax.ws.rs.core.Response;
33  import org.apache.cxf.helpers.IOUtils;
34  import org.apache.syncope.common.lib.SyncopeClientException;
35  import org.apache.syncope.common.lib.request.AttrPatch;
36  import org.apache.syncope.common.lib.request.MembershipUR;
37  import org.apache.syncope.common.lib.request.UserCR;
38  import org.apache.syncope.common.lib.request.UserUR;
39  import org.apache.syncope.common.lib.to.AnyTypeClassTO;
40  import org.apache.syncope.common.lib.to.PlainSchemaTO;
41  import org.apache.syncope.common.lib.to.UserTO;
42  import org.apache.syncope.common.lib.types.AttrSchemaType;
43  import org.apache.syncope.common.lib.types.CipherAlgorithm;
44  import org.apache.syncope.common.lib.types.ClientExceptionType;
45  import org.apache.syncope.common.lib.types.EntityViolationType;
46  import org.apache.syncope.common.lib.types.PatchOperation;
47  import org.apache.syncope.common.lib.types.SchemaType;
48  import org.apache.syncope.common.rest.api.beans.SchemaQuery;
49  import org.apache.syncope.fit.AbstractITCase;
50  import org.junit.jupiter.api.Assertions;
51  import org.junit.jupiter.api.Test;
52  
53  public class PlainSchemaITCase extends AbstractITCase {
54  
55      private static PlainSchemaTO buildPlainSchemaTO(final String name, final AttrSchemaType type) {
56          PlainSchemaTO schemaTO = new PlainSchemaTO();
57          schemaTO.setKey(name + getUUIDString());
58          schemaTO.setType(type);
59          return schemaTO;
60      }
61  
62      @Test
63      public void create() {
64          PlainSchemaTO schemaTO = buildPlainSchemaTO("testAttribute", AttrSchemaType.String);
65          schemaTO.setMandatoryCondition("false");
66          schemaTO.getLabels().put(Locale.ENGLISH, "Test");
67          schemaTO.getLabels().put(Locale.ITALIAN, "Prova");
68  
69          PlainSchemaTO newPlainSchemaTO = createSchema(SchemaType.PLAIN, schemaTO);
70          assertEquals(schemaTO, newPlainSchemaTO);
71  
72          try {
73              createSchema(SchemaType.PLAIN, schemaTO);
74              fail("This should not happen");
75          } catch (SyncopeClientException e) {
76              assertEquals(ClientExceptionType.EntityExists, e.getType());
77          }
78      }
79  
80      @Test
81      public void createWithNotPermittedName() {
82          PlainSchemaTO schemaTO = new PlainSchemaTO();
83          schemaTO.setKey("failedLogins");
84          schemaTO.setType(AttrSchemaType.String);
85  
86          try {
87              createSchema(SchemaType.PLAIN, schemaTO);
88              fail("This should not be reacheable");
89          } catch (SyncopeClientException e) {
90              assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
91              boolean entityViolationTypeCheck = false;
92              for (String element : e.getElements()) {
93                  if (!entityViolationTypeCheck) {
94                      entityViolationTypeCheck = element.contains(EntityViolationType.InvalidKey.name());
95                  }
96              }
97              assertTrue(entityViolationTypeCheck);
98          }
99      }
100 
101     @Test
102     public void createEnumWithNoValues() {
103         PlainSchemaTO schemaTO = new PlainSchemaTO();
104         schemaTO.setKey("enumcheck");
105         schemaTO.setType(AttrSchemaType.Enum);
106 
107         try {
108             createSchema(SchemaType.PLAIN, schemaTO);
109             fail("This should not be reacheable");
110         } catch (SyncopeClientException e) {
111             assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
112             assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidSchemaEnum.name()));
113         }
114     }
115 
116     @Test
117     public void createUEnumWithoutEnumeration() {
118         PlainSchemaTO schemaTO = new PlainSchemaTO();
119         schemaTO.setKey("enumcheck");
120         schemaTO.setType(AttrSchemaType.Enum);
121 
122         try {
123             createSchema(SchemaType.PLAIN, schemaTO);
124             fail("This should not be reacheable");
125         } catch (SyncopeClientException e) {
126             assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
127             assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidSchemaEnum.name()));
128         }
129     }
130 
131     @Test
132     public void createEncrypted() {
133         PlainSchemaTO schemaTO = new PlainSchemaTO();
134         schemaTO.setKey("encrypted");
135         schemaTO.setType(AttrSchemaType.Encrypted);
136         schemaTO.setCipherAlgorithm(CipherAlgorithm.AES);
137         schemaTO.setSecretKey("huhadfhsjfsfsdkj!####");
138 
139         createSchema(SchemaType.PLAIN, schemaTO);
140     }
141 
142     @Test
143     public void createBinary() {
144         PlainSchemaTO schemaTO = new PlainSchemaTO();
145         schemaTO.setKey("x509certificate");
146         schemaTO.setType(AttrSchemaType.Binary);
147         schemaTO.setMimeType("application/x-x509-ca-cert");
148 
149         createSchema(SchemaType.PLAIN, schemaTO);
150     }
151 
152     @Test
153     public void binaryValidation() throws IOException {
154         // pdf - with validator
155         PlainSchemaTO schemaTOpdf = new PlainSchemaTO();
156         schemaTOpdf.setKey("BinaryPDF");
157         schemaTOpdf.setType(AttrSchemaType.Binary);
158         schemaTOpdf.setMimeType("application/pdf");
159         schemaTOpdf.setValidator("BinaryValidator");
160         schemaTOpdf.setAnyTypeClass("minimal user");
161 
162         createSchema(SchemaType.PLAIN, schemaTOpdf);
163 
164         // json - with validator
165         PlainSchemaTO schemaTOjson = new PlainSchemaTO();
166         schemaTOjson.setKey("BinaryJSON");
167         schemaTOjson.setType(AttrSchemaType.Binary);
168         schemaTOjson.setMimeType("application/json");
169         schemaTOjson.setValidator("BinaryValidator");
170         schemaTOjson.setAnyTypeClass("minimal user");
171 
172         createSchema(SchemaType.PLAIN, schemaTOjson);
173 
174         // json - no validator
175         PlainSchemaTO schemaTOjson2 = new PlainSchemaTO();
176         schemaTOjson2.setKey("BinaryJSON2");
177         schemaTOjson2.setType(AttrSchemaType.Binary);
178         schemaTOjson2.setMimeType("application/json");
179         schemaTOjson2.setAnyTypeClass("minimal user");
180 
181         createSchema(SchemaType.PLAIN, schemaTOjson2);
182 
183         UserCR userCR = UserITCase.getUniqueSample("test@syncope.apache.org");
184 
185         UserTO userTO = createUser(userCR).getEntity();
186         assertNotNull(userTO);
187         try {
188             UserUR userUR = new UserUR();
189             userUR.setKey(userTO.getKey());
190             // validation OK - application/pdf -> application/pdf
191             userUR.getPlainAttrs().add(new AttrPatch.Builder(attr("BinaryPDF",
192                     Base64.getEncoder().encodeToString(
193                             IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.pdf"))))).
194                     operation(PatchOperation.ADD_REPLACE).
195                     build());
196 
197             updateUser(userUR);
198             assertNotNull(USER_SERVICE.read(userTO.getKey()).getPlainAttr("BinaryPDF"));
199 
200             userUR = new UserUR();
201             userUR.setKey(userTO.getKey());
202             // validation KO - text/html -> application/pdf
203             try {
204                 userUR.getPlainAttrs().add(new AttrPatch.Builder(attr("BinaryPDF",
205                         Base64.getEncoder().encodeToString(
206                                 IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.html"))))).
207                         operation(PatchOperation.ADD_REPLACE).
208                         build());
209 
210                 updateUser(userUR);
211                 fail("This should not be reacheable");
212             } catch (SyncopeClientException e) {
213                 assertEquals(ClientExceptionType.InvalidValues, e.getType());
214             }
215 
216             userUR = new UserUR();
217             userUR.setKey(userTO.getKey());
218             // validation ok - application/json -> application/json
219             userUR.getPlainAttrs().add(new AttrPatch.Builder(attr("BinaryJSON",
220                     Base64.getEncoder().encodeToString(
221                             IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.json"))))).
222                     operation(PatchOperation.ADD_REPLACE).
223                     build());
224 
225             updateUser(userUR);
226             assertNotNull(USER_SERVICE.read(userTO.getKey()).getPlainAttr("BinaryJSON"));
227 
228             userUR = new UserUR();
229             userUR.setKey(userTO.getKey());
230             // no validation - application/xml -> application/json
231             userUR.getPlainAttrs().add(new AttrPatch.Builder(attr("BinaryJSON2",
232                     Base64.getEncoder().encodeToString(
233                             IOUtils.readBytesFromStream(getClass().getResourceAsStream("/test.xml"))))).
234                     operation(PatchOperation.ADD_REPLACE).
235                     build());
236 
237             updateUser(userUR);
238             assertNotNull(USER_SERVICE.read(userTO.getKey()).getPlainAttr("BinaryJSON2"));
239         } finally {
240             USER_SERVICE.delete(userTO.getKey());
241 
242             SCHEMA_SERVICE.delete(SchemaType.PLAIN, schemaTOpdf.getKey());
243             SCHEMA_SERVICE.delete(SchemaType.PLAIN, schemaTOjson.getKey());
244             SCHEMA_SERVICE.delete(SchemaType.PLAIN, schemaTOjson2.getKey());
245         }
246     }
247 
248     @Test
249     public void delete() {
250         PlainSchemaTO schemaTO = buildPlainSchemaTO("todelete", AttrSchemaType.String);
251         schemaTO.setMandatoryCondition("false");
252         createSchema(SchemaType.PLAIN, schemaTO);
253 
254         SCHEMA_SERVICE.delete(SchemaType.PLAIN, schemaTO.getKey());
255         PlainSchemaTO firstname = null;
256         try {
257             firstname = SCHEMA_SERVICE.read(SchemaType.PLAIN, schemaTO.getKey());
258         } catch (SyncopeClientException e) {
259             assertEquals(Response.Status.NOT_FOUND, e.getType().getResponseStatus());
260         }
261         assertNull(firstname);
262     }
263 
264     @Test
265     public void search() {
266         List<PlainSchemaTO> schemas = SCHEMA_SERVICE.search(new SchemaQuery.Builder().type(SchemaType.PLAIN).build());
267         assertFalse(schemas.isEmpty());
268         schemas.forEach(Assertions::assertNotNull);
269 
270         schemas = SCHEMA_SERVICE.search(new SchemaQuery.Builder().type(SchemaType.PLAIN).keyword("fullna*").build());
271         assertFalse(schemas.isEmpty());
272         schemas.forEach(Assertions::assertNotNull);
273     }
274 
275     @Test
276     public void searchByAnyTypeClass() {
277         List<PlainSchemaTO> userSchemas = SCHEMA_SERVICE.search(
278                 new SchemaQuery.Builder().type(SchemaType.PLAIN).anyTypeClass("minimal user").build());
279 
280         assertTrue(userSchemas.stream().anyMatch(object -> "fullname".equals(object.getKey())));
281 
282         assertFalse(userSchemas.stream().anyMatch(object -> "password.cipher.algorithm".equals(object.getKey())
283                 || "rderived_dx".equals(object.getKey())
284                 || "icon".equals(object.getKey())
285                 || "mderived_sx".equals(object.getKey())
286                 || "self.membership.layout".equals(object.getKey())));
287     }
288 
289     @Test
290     public void update() {
291         PlainSchemaTO schemaTO = SCHEMA_SERVICE.read(SchemaType.PLAIN, "icon");
292         assertNotNull(schemaTO);
293 
294         SCHEMA_SERVICE.update(SchemaType.PLAIN, schemaTO);
295         PlainSchemaTO updatedTO = SCHEMA_SERVICE.read(SchemaType.PLAIN, "icon");
296         assertEquals(schemaTO, updatedTO);
297 
298         updatedTO.setType(AttrSchemaType.Date);
299         try {
300             SCHEMA_SERVICE.update(SchemaType.PLAIN, updatedTO);
301             fail("This should not be reacheable");
302         } catch (SyncopeClientException e) {
303             assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
304         }
305     }
306 
307     @Test
308     public void issue258() {
309         PlainSchemaTO schemaTO = new PlainSchemaTO();
310         schemaTO.setKey("schema_issue258");
311         schemaTO.setType(AttrSchemaType.Double);
312 
313         schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
314         assertNotNull(schemaTO);
315 
316         AnyTypeClassTO typeClass = new AnyTypeClassTO();
317         typeClass.setKey("issue258");
318         typeClass.getPlainSchemas().add(schemaTO.getKey());
319         ANY_TYPE_CLASS_SERVICE.create(typeClass);
320 
321         UserCR userCR = UserITCase.getUniqueSample("issue258@syncope.apache.org");
322         userCR.getAuxClasses().add(typeClass.getKey());
323         userCR.getPlainAttrs().add(attr(schemaTO.getKey(), "1.2"));
324 
325         UserTO userTO = createUser(userCR).getEntity();
326         assertNotNull(userTO);
327 
328         schemaTO.setType(AttrSchemaType.Long);
329         try {
330             SCHEMA_SERVICE.update(SchemaType.PLAIN, schemaTO);
331             fail("This should not be reacheable");
332         } catch (SyncopeClientException e) {
333             assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
334         }
335     }
336 
337     @Test
338     public void issue259() {
339         PlainSchemaTO schemaTO = buildPlainSchemaTO("schema_issue259", AttrSchemaType.Double);
340         schemaTO.setUniqueConstraint(true);
341 
342         schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
343         assertNotNull(schemaTO);
344 
345         AnyTypeClassTO typeClass = new AnyTypeClassTO();
346         typeClass.setKey("issue259");
347         typeClass.getPlainSchemas().add(schemaTO.getKey());
348         ANY_TYPE_CLASS_SERVICE.create(typeClass);
349 
350         UserCR userCR = UserITCase.getUniqueSample("issue259@syncope.apache.org");
351         userCR.getAuxClasses().add(typeClass.getKey());
352         userCR.getPlainAttrs().add(attr(schemaTO.getKey(), "1"));
353         UserTO userTO = createUser(userCR).getEntity();
354         assertNotNull(userTO);
355 
356         UserUR req = new UserUR.Builder(userTO.getKey()).
357                 membership(new MembershipUR.Builder("b1f7c12d-ec83-441f-a50e-1691daaedf3b").build()).build();
358 
359         UserTO newUserTO = updateUser(req).getEntity();
360         assertNotNull(newUserTO);
361     }
362 
363     @Test
364     public void issue260() {
365         PlainSchemaTO schemaTO = buildPlainSchemaTO("schema_issue260", AttrSchemaType.Double);
366         schemaTO.setUniqueConstraint(true);
367 
368         schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
369         assertNotNull(schemaTO);
370 
371         AnyTypeClassTO typeClass = new AnyTypeClassTO();
372         typeClass.setKey("issue260");
373         typeClass.getPlainSchemas().add(schemaTO.getKey());
374         ANY_TYPE_CLASS_SERVICE.create(typeClass);
375 
376         UserCR userCR = UserITCase.getUniqueSample("issue260@syncope.apache.org");
377         userCR.getAuxClasses().add(typeClass.getKey());
378         userCR.getPlainAttrs().add(attr(schemaTO.getKey(), "1.2"));
379         UserTO userTO = createUser(userCR).getEntity();
380         assertNotNull(userTO);
381 
382         schemaTO.setUniqueConstraint(false);
383         try {
384             SCHEMA_SERVICE.update(SchemaType.PLAIN, schemaTO);
385             fail("This should not be reacheable");
386         } catch (SyncopeClientException e) {
387             assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
388         }
389     }
390 
391     @Test
392     public void issueSYNCOPE323() {
393         PlainSchemaTO actual = SCHEMA_SERVICE.read(SchemaType.PLAIN, "icon");
394         assertNotNull(actual);
395 
396         try {
397             createSchema(SchemaType.PLAIN, actual);
398             fail("This should not happen");
399         } catch (SyncopeClientException e) {
400             assertEquals(Response.Status.CONFLICT, e.getType().getResponseStatus());
401             assertEquals(ClientExceptionType.EntityExists, e.getType());
402         }
403 
404         actual.setKey(null);
405         try {
406             createSchema(SchemaType.PLAIN, actual);
407             fail("This should not happen");
408         } catch (SyncopeClientException e) {
409             assertEquals(Response.Status.BAD_REQUEST, e.getType().getResponseStatus());
410             assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
411         }
412     }
413 
414     @Test
415     public void issueSYNCOPE418() {
416         PlainSchemaTO schema = buildPlainSchemaTO("http://schemas.examples.org/security/authorization/organizationUnit",
417                 AttrSchemaType.Double);
418 
419         try {
420             createSchema(SchemaType.PLAIN, schema);
421             fail("This should not happen");
422         } catch (SyncopeClientException e) {
423             assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
424             assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidKey.name()));
425         }
426     }
427 }