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.ext.scimv2.api.data;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertNotNull;
23  import static org.junit.jupiter.api.Assertions.assertNull;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  
26  import com.fasterxml.jackson.core.JsonProcessingException;
27  import com.fasterxml.jackson.databind.SerializationFeature;
28  import com.fasterxml.jackson.databind.json.JsonMapper;
29  import java.util.List;
30  import org.apache.syncope.ext.scimv2.api.type.PatchOp;
31  import org.apache.syncope.ext.scimv2.api.type.Resource;
32  import org.junit.jupiter.api.Test;
33  
34  public class SCIMPatchOperationDeserializerTest {
35  
36      private static final JsonMapper MAPPER = JsonMapper.builder().
37              findAndAddModules().disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS).build();
38  
39      @Test
40      public void addMember() throws JsonProcessingException {
41          String input =
42                  "{ "
43                  + "\"schemas\":[\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"],"
44                  + "     \"Operations\":["
45                  + "       {"
46                  + "        \"op\":\"add\","
47                  + "        \"path\":\"members\","
48                  + "        \"value\":["
49                  + "         {"
50                  + "           \"display\": \"Babs Jensen\","
51                  + "           \"$ref\": \"https://example.com/v2/Users/2819c223...413861904646\","
52                  + "           \"value\": \"2819c223-7f76-453a-919d-413861904646\""
53                  + "         }"
54                  + "        ]"
55                  + "       }"
56                  + "     ]"
57                  + "   }";
58  
59          SCIMPatchOp scimPatchOp = MAPPER.readValue(input, SCIMPatchOp.class);
60          assertNotNull(scimPatchOp);
61          assertEquals(List.of(Resource.PatchOp.schema()), scimPatchOp.getSchemas());
62          assertEquals(1, scimPatchOp.getOperations().size());
63  
64          SCIMPatchOperation op = scimPatchOp.getOperations().get(0);
65          assertNotNull(op);
66          assertEquals(PatchOp.add, op.getOp());
67          assertEquals("members", op.getPath().getAttribute());
68  
69          assertEquals(1, op.getValue().size());
70  
71          Member member = (Member) op.getValue().get(0);
72          assertEquals("Babs Jensen", member.getDisplay());
73          assertEquals("https://example.com/v2/Users/2819c223...413861904646", member.getRef());
74          assertEquals("2819c223-7f76-453a-919d-413861904646", member.getValue());
75      }
76  
77      @Test
78      public void removeMembers() throws JsonProcessingException {
79          String input =
80                  "{"
81                  + "     \"schemas\":[\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"],"
82                  + "     \"Operations\":[{"
83                  + "       \"op\":\"remove\","
84                  + "       \"path\":\"members[value eq \\\"2819c223-7f76-...413861904646\\\"]\""
85                  + "     }]"
86                  + "   }";
87  
88          SCIMPatchOp scimPatchOp = MAPPER.readValue(input, SCIMPatchOp.class);
89          assertNotNull(scimPatchOp);
90          assertEquals(List.of(Resource.PatchOp.schema()), scimPatchOp.getSchemas());
91          assertEquals(1, scimPatchOp.getOperations().size());
92  
93          SCIMPatchOperation op = scimPatchOp.getOperations().get(0);
94          assertNotNull(op);
95          assertEquals(PatchOp.remove, op.getOp());
96          assertEquals("members", op.getPath().getAttribute());
97          assertEquals("value eq \"2819c223-7f76-...413861904646\"", op.getPath().getFilter());
98      }
99  
100     @Test
101     public void removeAndAddMembers() throws JsonProcessingException {
102         String input =
103                 "{ \"schemas\":[\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"],"
104                 + "     \"Operations\": ["
105                 + "       {"
106                 + "         \"op\":\"remove\","
107                 + "         \"path\":"
108                 + "           \"members[value eq \\\"2819c223...919d-413861904646\\\"]\""
109                 + "       },"
110                 + "       {"
111                 + "         \"op\":\"add\","
112                 + "         \"path\":\"members\","
113                 + "         \"value\": ["
114                 + "           {"
115                 + "            \"display\": \"Babs Jensen\","
116                 + "            \"$ref\":\"https://example.com/v2/Users/2819c223...413861904646\","
117                 + "            \"value\": \"2819c223-7f76-453a-919d-413861904646\""
118                 + "           },"
119                 + "           {"
120                 + "             \"display\": \"James Smith\","
121                 + "             \"$ref\":\"https://example.com/v2/Users/08e1d05d...473d93df9210\","
122                 + "             \"value\": \"08e1d05d...473d93df9210\""
123                 + "           }"
124                 + "         ]"
125                 + "       }"
126                 + "     ]"
127                 + "   }";
128 
129         SCIMPatchOp scimPatchOp = MAPPER.readValue(input, SCIMPatchOp.class);
130         assertNotNull(scimPatchOp);
131         assertEquals(List.of(Resource.PatchOp.schema()), scimPatchOp.getSchemas());
132         assertEquals(2, scimPatchOp.getOperations().size());
133 
134         SCIMPatchOperation op = scimPatchOp.getOperations().get(0);
135         assertNotNull(op);
136         assertEquals(PatchOp.remove, op.getOp());
137         assertEquals("members", op.getPath().getAttribute());
138         assertEquals("value eq \"2819c223...919d-413861904646\"", op.getPath().getFilter());
139 
140         op = scimPatchOp.getOperations().get(1);
141         assertNotNull(op);
142         assertEquals(PatchOp.add, op.getOp());
143         assertEquals("members", op.getPath().getAttribute());
144 
145         assertEquals(2, op.getValue().size());
146 
147         Member member = (Member) op.getValue().get(0);
148         assertEquals("Babs Jensen", member.getDisplay());
149         assertEquals("https://example.com/v2/Users/2819c223...413861904646", member.getRef());
150         assertEquals("2819c223-7f76-453a-919d-413861904646", member.getValue());
151 
152         member = (Member) op.getValue().get(1);
153         assertEquals("James Smith", member.getDisplay());
154         assertEquals("https://example.com/v2/Users/08e1d05d...473d93df9210", member.getRef());
155         assertEquals("08e1d05d...473d93df9210", member.getValue());
156     }
157 
158     @Test
159     public void addAttributes() throws JsonProcessingException {
160         String input =
161                 "{"
162                 + "  \"schemas\":[\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"],"
163                 + "  \"Operations\": ["
164                 + "    {"
165                 + "      \"op\": \"add\","
166                 + "      \"value\": {"
167                 + "        \"emails\": ["
168                 + "          {"
169                 + "            \"value\": \"babs@jensen.org\","
170                 + "            \"type\": \"home\""
171                 + "          }"
172                 + "        ],"
173                 + "        \"nickName\": \"Babs\""
174                 + "      }"
175                 + "    }"
176                 + "  ]"
177                 + "}";
178 
179         SCIMPatchOp scimPatchOp = MAPPER.readValue(input, SCIMPatchOp.class);
180         assertNotNull(scimPatchOp);
181         assertEquals(List.of(Resource.PatchOp.schema()), scimPatchOp.getSchemas());
182         assertEquals(1, scimPatchOp.getOperations().size());
183 
184         SCIMPatchOperation op = scimPatchOp.getOperations().get(0);
185         assertNotNull(op);
186         assertEquals(PatchOp.add, op.getOp());
187         assertNull(op.getPath());
188 
189         assertEquals(1, op.getValue().size());
190 
191         SCIMUser user = (SCIMUser) op.getValue().get(0);
192         assertEquals("Babs", user.getNickName());
193 
194         assertEquals(1, user.getEmails().size());
195 
196         SCIMComplexValue email = user.getEmails().get(0);
197         assertEquals("home", email.getType());
198         assertEquals("babs@jensen.org", email.getValue());
199     }
200 
201     @Test
202     public void replaceMembers() throws JsonProcessingException {
203         String input =
204                 " {"
205                 + "     \"schemas\":[\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"],"
206                 + "     \"Operations\": [{"
207                 + "       \"op\":\"replace\","
208                 + "       \"path\":\"members\","
209                 + "       \"value\":["
210                 + "         {"
211                 + "           \"display\": \"Babs Jensen\","
212                 + "           \"$ref\": \"https://example.com/v2/Users/2819c223...413861904646\","
213                 + "           \"value\": \"2819c223...413861904646\""
214                 + "         },"
215                 + "         {"
216                 + "           \"display\": \"James Smith\","
217                 + "           \"$ref\":\"https://example.com/v2/Users/08e1d05d...473d93df9210\","
218                 + "           \"value\": \"08e1d05d...473d93df9210\""
219                 + "         }"
220                 + "       ]"
221                 + "     }]"
222                 + "   }";
223 
224         SCIMPatchOp scimPatchOp = MAPPER.readValue(input, SCIMPatchOp.class);
225         assertNotNull(scimPatchOp);
226         assertEquals(List.of(Resource.PatchOp.schema()), scimPatchOp.getSchemas());
227         assertEquals(1, scimPatchOp.getOperations().size());
228 
229         SCIMPatchOperation op = scimPatchOp.getOperations().get(0);
230         assertNotNull(op);
231         assertEquals(PatchOp.replace, op.getOp());
232         assertEquals("members", op.getPath().getAttribute());
233 
234         assertEquals(2, op.getValue().size());
235 
236         Member member = (Member) op.getValue().get(0);
237         assertEquals("Babs Jensen", member.getDisplay());
238         assertEquals("https://example.com/v2/Users/2819c223...413861904646", member.getRef());
239         assertEquals("2819c223...413861904646", member.getValue());
240 
241         member = (Member) op.getValue().get(1);
242         assertEquals("James Smith", member.getDisplay());
243         assertEquals("https://example.com/v2/Users/08e1d05d...473d93df9210", member.getRef());
244         assertEquals("08e1d05d...473d93df9210", member.getValue());
245     }
246 
247     @Test
248     public void replaceAttribute() throws JsonProcessingException {
249         String input =
250                 "{"
251                 + "     \"schemas\": [\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"],"
252                 + "     \"Operations\": [{"
253                 + "       \"op\":\"replace\","
254                 + "       \"path\":\"addresses[type eq \\\"work\\\"]\","
255                 + "       \"value\":"
256                 + "       {"
257                 + "         \"type\": \"work\","
258                 + "         \"streetAddress\": \"911 Universal City Plaza\","
259                 + "         \"locality\": \"Hollywood\","
260                 + "         \"region\": \"CA\","
261                 + "         \"postalCode\": \"91608\","
262                 + "         \"country\": \"US\","
263                 + "         \"formatted\":\"911 Universal City Plaza\\nHollywood, CA 91608 US\","
264                 + "         \"primary\": true"
265                 + "       }"
266                 + "     }]"
267                 + "   }";
268 
269         SCIMPatchOp scimPatchOp = MAPPER.readValue(input, SCIMPatchOp.class);
270         assertNotNull(scimPatchOp);
271         assertEquals(List.of(Resource.PatchOp.schema()), scimPatchOp.getSchemas());
272         assertEquals(1, scimPatchOp.getOperations().size());
273 
274         SCIMPatchOperation op = scimPatchOp.getOperations().get(0);
275         assertNotNull(op);
276         assertEquals(PatchOp.replace, op.getOp());
277         assertEquals("addresses", op.getPath().getAttribute());
278         assertEquals("type eq \"work\"", op.getPath().getFilter());
279 
280         assertEquals(1, op.getValue().size());
281 
282         SCIMUser user = (SCIMUser) op.getValue().get(0);
283 
284         assertEquals(1, user.getAddresses().size());
285 
286         SCIMUserAddress address = user.getAddresses().get(0);
287         assertEquals("work", address.getType());
288         assertTrue(address.isPrimary());
289     }
290 
291     @Test
292     public void replaceAttributeValue() throws JsonProcessingException {
293         String input =
294                 "{"
295                 + "     \"schemas\": [\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"],"
296                 + "     \"Operations\": [{"
297                 + "       \"op\":\"replace\","
298                 + "       \"path\":\"addresses[type eq \\\"work\\\"].streetAddress\","
299                 + "       \"value\":\"1010 Broadway Ave\""
300                 + "     }]"
301                 + "   }";
302 
303         SCIMPatchOp scimPatchOp = MAPPER.readValue(input, SCIMPatchOp.class);
304         assertNotNull(scimPatchOp);
305         assertEquals(List.of(Resource.PatchOp.schema()), scimPatchOp.getSchemas());
306         assertEquals(1, scimPatchOp.getOperations().size());
307 
308         SCIMPatchOperation op = scimPatchOp.getOperations().get(0);
309         assertNotNull(op);
310         assertEquals(PatchOp.replace, op.getOp());
311         assertEquals("addresses", op.getPath().getAttribute());
312         assertEquals("type eq \"work\"", op.getPath().getFilter());
313         assertEquals("streetAddress", op.getPath().getSub());
314 
315         assertEquals(1, op.getValue().size());
316 
317         String value = (String) op.getValue().get(0);
318         assertEquals("1010 Broadway Ave", value);
319     }
320 
321     @Test
322     public void addAttributeValue() throws JsonProcessingException {
323         String input =
324                 "{"
325                 + "  \"schemas\": [\"urn:ietf:params:scim:api:messages:2.0:PatchOp\"],"
326                 + "  \"Operations\": [{"
327                 + "      \"op\": \"Add\","
328                 + "      \"path\": \"externalId\","
329                 + "      \"value\": \"da91cb5d-addb-424f-aa41-799fda8658c3\""
330                 + "    }"
331                 + "  ]"
332                 + "}";
333 
334         SCIMPatchOp scimPatchOp = MAPPER.readValue(input, SCIMPatchOp.class);
335         assertNotNull(scimPatchOp);
336         assertEquals(List.of(Resource.PatchOp.schema()), scimPatchOp.getSchemas());
337         assertEquals(1, scimPatchOp.getOperations().size());
338 
339         SCIMPatchOperation op = scimPatchOp.getOperations().get(0);
340         assertNotNull(op);
341         assertEquals(PatchOp.add, op.getOp());
342         assertEquals("externalId", op.getPath().getAttribute());
343 
344         assertEquals(1, op.getValue().size());
345 
346         String value = (String) op.getValue().get(0);
347         assertEquals("da91cb5d-addb-424f-aa41-799fda8658c3", value);
348     }
349 }