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.common.rest.api.service;
20  
21  import io.swagger.v3.oas.annotations.Operation;
22  import io.swagger.v3.oas.annotations.Parameter;
23  import io.swagger.v3.oas.annotations.enums.ParameterIn;
24  import io.swagger.v3.oas.annotations.headers.Header;
25  import io.swagger.v3.oas.annotations.media.Content;
26  import io.swagger.v3.oas.annotations.media.Schema;
27  import io.swagger.v3.oas.annotations.responses.ApiResponse;
28  import io.swagger.v3.oas.annotations.responses.ApiResponses;
29  import java.util.Set;
30  import javax.validation.constraints.NotNull;
31  import javax.ws.rs.BeanParam;
32  import javax.ws.rs.Consumes;
33  import javax.ws.rs.DELETE;
34  import javax.ws.rs.GET;
35  import javax.ws.rs.POST;
36  import javax.ws.rs.PUT;
37  import javax.ws.rs.Path;
38  import javax.ws.rs.PathParam;
39  import javax.ws.rs.Produces;
40  import javax.ws.rs.core.HttpHeaders;
41  import javax.ws.rs.core.MediaType;
42  import javax.ws.rs.core.Response;
43  import org.apache.syncope.common.lib.Attr;
44  import org.apache.syncope.common.lib.request.ResourceAR;
45  import org.apache.syncope.common.lib.request.ResourceDR;
46  import org.apache.syncope.common.lib.to.AnyTO;
47  import org.apache.syncope.common.lib.to.PagedResult;
48  import org.apache.syncope.common.lib.to.ProvisioningResult;
49  import org.apache.syncope.common.lib.types.ResourceAssociationAction;
50  import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
51  import org.apache.syncope.common.lib.types.SchemaType;
52  import org.apache.syncope.common.rest.api.RESTHeaders;
53  import org.apache.syncope.common.rest.api.beans.AnyQuery;
54  
55  public interface AnyService<TO extends AnyTO> extends JAXRSService {
56  
57      /**
58       * Reads the list of attributes owned by the given any object for the given schema type.
59       *
60       * Note that for the UserService, GroupService and AnyObjectService subclasses, if the key parameter
61       * looks like a UUID then it is interpreted as as key, otherwise as a (user)name.
62       *
63       * @param key any object key or name
64       * @param schemaType schema type
65       * @return list of attributes, owned by the given any object, for the given schema type
66       */
67      @GET
68      @Path("{key}/{schemaType}")
69      @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
70      Set<Attr> read(@NotNull @PathParam("key") String key, @NotNull @PathParam("schemaType") SchemaType schemaType);
71  
72      /**
73       * Reads the attribute, owned by the given any object, for the given schema type and schema.
74       *
75       * Note that for the UserService, GroupService and AnyObjectService subclasses, if the key parameter
76       * looks like a UUID then it is interpreted as as key, otherwise as a (user)name.
77       *
78       * @param key any object key or name
79       * @param schemaType schema type
80       * @param schema schema
81       * @return attribute, owned by the given any object, for the given schema type and schema
82       */
83      @GET
84      @Path("{key}/{schemaType}/{schema}")
85      @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
86      Attr read(
87              @NotNull @PathParam("key") String key,
88              @NotNull @PathParam("schemaType") SchemaType schemaType,
89              @NotNull @PathParam("schema") String schema);
90  
91      /**
92       * Reads the any object matching the provided key.
93       *
94       * @param key if value looks like a UUID then it is interpreted as key, otherwise as a (user)name
95       * @return any object with matching key
96       */
97      @GET
98      @Path("{key}")
99      @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
100     TO read(@NotNull @PathParam("key") String key);
101 
102     /**
103      * Returns a paged list of any objects matching the given query.
104      *
105      * @param anyQuery query conditions
106      * @return paged list of any objects matching the given query
107      */
108     @GET
109     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
110     PagedResult<TO> search(@BeanParam AnyQuery anyQuery);
111 
112     /**
113      * Adds or replaces the attribute, owned by the given any object, for the given schema type and schema.
114      *
115      * @param key any object key or name
116      * @param schemaType schema type
117      * @param attrTO attribute
118      * @return Response object featuring the updated any object attribute - as Entity
119      */
120     @Parameter(name = "schema", description = "Attribute schema's key", in = ParameterIn.PATH, schema =
121             @Schema(type = "string"))
122     @PUT
123     @Path("{key}/{schemaType}/{schema}")
124     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
125     @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
126     Response update(
127             @NotNull @PathParam("key") String key,
128             @NotNull @PathParam("schemaType") SchemaType schemaType,
129             @NotNull Attr attrTO);
130 
131     /**
132      * Deletes the attribute, owned by the given any object, for the given schema type and schema.
133      *
134      * @param key any object key or name
135      * @param schemaType schema type
136      * @param schema schema
137      */
138     @Operation(operationId = "deleteAttr")
139     @ApiResponses(
140             @ApiResponse(responseCode = "204", description = "Operation was successful"))
141     @DELETE
142     @Path("{key}/{schemaType}/{schema}")
143     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
144     void delete(
145             @NotNull @PathParam("key") String key,
146             @NotNull @PathParam("schemaType") SchemaType schemaType,
147             @NotNull @PathParam("schema") String schema);
148 
149     /**
150      * Deletes any object matching provided key.
151      *
152      * @param key any object key or name
153      * @return Response object featuring the deleted any object enriched with propagation status information
154      */
155     @Operation(operationId = "deleteAny")
156     @Parameter(name = RESTHeaders.PREFER, in = ParameterIn.HEADER,
157             description = "Allows client to specify a preference for the result to be returned from the server",
158             allowEmptyValue = true, schema =
159             @Schema(defaultValue = "return-content", allowableValues = { "return-content", "return-no-content" }))
160     @Parameter(name = HttpHeaders.IF_MATCH, in = ParameterIn.HEADER,
161             description = "When the provided ETag value does not match the latest modification date of the entity, "
162             + "an error is reported and the requested operation is not performed.",
163             allowEmptyValue = true, schema =
164             @Schema(type = "string"))
165     @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
166             description = "If 'true', instructs the propagation process not to wait for completion when communicating"
167             + " with External Resources with no priority set",
168             allowEmptyValue = true, schema =
169             @Schema(type = "boolean", defaultValue = "false"))
170     @ApiResponses({
171         @ApiResponse(responseCode = "200",
172                 description = "User, Group or Any Object successfully deleted enriched with propagation status "
173                 + "information, as Entity", content =
174                 @Content(schema =
175                         @Schema(implementation = ProvisioningResult.class))),
176         @ApiResponse(responseCode = "204",
177                 description = "No content if 'Prefer: return-no-content' was specified", headers =
178                 @Header(name = RESTHeaders.PREFERENCE_APPLIED, schema =
179                         @Schema(type = "string"),
180                         description = "Allows the server to inform the "
181                         + "client about the fact that a specified preference was applied")),
182         @ApiResponse(responseCode = "412",
183                 description = "The ETag value provided via the 'If-Match' header does not match the latest modification"
184                 + " date of the entity") })
185     @DELETE
186     @Path("{key}")
187     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
188     Response delete(@NotNull @PathParam("key") String key);
189 
190     /**
191      * Executes resource-related operations on given entity.
192      *
193      * @param req external resources to be used for propagation-related operations
194      * @return batch results as Response entity
195      */
196     @Parameter(name = RESTHeaders.PREFER, in = ParameterIn.HEADER,
197             description = "Allows client to specify a preference for the result to be returned from the server",
198             allowEmptyValue = true, schema =
199             @Schema(defaultValue = "return-content", allowableValues = { "return-content", "return-no-content" }))
200     @Parameter(name = HttpHeaders.IF_MATCH, in = ParameterIn.HEADER,
201             description = "When the provided ETag value does not match the latest modification date of the entity, "
202             + "an error is reported and the requested operation is not performed.",
203             allowEmptyValue = true, schema =
204             @Schema(type = "string"))
205     @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
206             description = "If 'true', instructs the propagation process not to wait for completion when communicating"
207             + " with External Resources with no priority set",
208             allowEmptyValue = true, schema =
209             @Schema(type = "boolean", defaultValue = "false"))
210     @Parameter(name = "key", description = "Entity's key", in = ParameterIn.PATH, schema =
211             @Schema(type = "string"))
212     @Parameter(name = "action", description = "Deassociation action", in = ParameterIn.PATH, schema =
213             @Schema(implementation = ResourceDeassociationAction.class))
214     @ApiResponses({
215         @ApiResponse(responseCode = "200",
216                 description = "Batch results available, returned as Response entity"),
217         @ApiResponse(responseCode = "204",
218                 description = "No content if 'Prefer: return-no-content' was specified", headers =
219                 @Header(name = RESTHeaders.PREFERENCE_APPLIED, schema =
220                         @Schema(type = "string"),
221                         description = "Allows the server to inform the "
222                         + "client about the fact that a specified preference was applied")),
223         @ApiResponse(responseCode = "412",
224                 description = "The ETag value provided via the 'If-Match' header does not match the latest modification"
225                 + " date of the entity") })
226     @POST
227     @Path("{key}/deassociate/{action}")
228     @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
229     @Produces(RESTHeaders.MULTIPART_MIXED)
230     Response deassociate(@NotNull ResourceDR req);
231 
232     /**
233      * Executes resource-related operations on given entity.
234      *
235      * @param req external resources to be used for propagation-related operations
236      * @return batch results as Response entity
237      */
238     @Parameter(name = RESTHeaders.PREFER, in = ParameterIn.HEADER,
239             description = "Allows client to specify a preference for the result to be returned from the server",
240             allowEmptyValue = true, schema =
241             @Schema(defaultValue = "return-content", allowableValues = { "return-content", "return-no-content" }))
242     @Parameter(name = HttpHeaders.IF_MATCH, in = ParameterIn.HEADER,
243             description = "When the provided ETag value does not match the latest modification date of the entity, "
244             + "an error is reported and the requested operation is not performed.",
245             allowEmptyValue = true, schema =
246             @Schema(type = "string"))
247     @Parameter(name = RESTHeaders.NULL_PRIORITY_ASYNC, in = ParameterIn.HEADER,
248             description = "If 'true', instructs the propagation process not to wait for completion when communicating"
249             + " with External Resources with no priority set",
250             allowEmptyValue = true, schema =
251             @Schema(type = "boolean", defaultValue = "false"))
252     @Parameter(name = "key", description = "Entity's key", in = ParameterIn.PATH, schema =
253             @Schema(type = "string"))
254     @Parameter(name = "action", description = "Association action", in = ParameterIn.PATH, schema =
255             @Schema(implementation = ResourceAssociationAction.class))
256     @ApiResponses({
257         @ApiResponse(responseCode = "200",
258                 description = "Batch results available, returned as Response entity"),
259         @ApiResponse(responseCode = "204",
260                 description = "No content if 'Prefer: return-no-content' was specified", headers =
261                 @Header(name = RESTHeaders.PREFERENCE_APPLIED, schema =
262                         @Schema(type = "string"),
263                         description = "Allows the server to inform the "
264                         + "client about the fact that a specified preference was applied")),
265         @ApiResponse(responseCode = "412",
266                 description = "The ETag value provided via the 'If-Match' header does not match the latest modification"
267                 + " date of the entity") })
268     @POST
269     @Path("{key}/associate/{action}")
270     @Consumes({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
271     @Produces(RESTHeaders.MULTIPART_MIXED)
272     Response associate(@NotNull ResourceAR req);
273 }