| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| === RESTful services |
| |
| All the features provided by the <<core>> are available as RESTful services. |
| |
| The base URL for invoking such services is normally set as |
| |
| .... |
| protocol://host:port/syncope/rest/ |
| .... |
| |
| where `protocol`, `host` and `port` reflect your deployment. |
| |
| [NOTE] |
| .REST Reference |
| ==== |
| A complete REST reference generated from https://en.wikipedia.org/wiki/Web_Application_Description_Language[WADL^] is |
| http://syncope.apache.org/rest/2.1/index.html[published^] as well as made available with each deployment at |
| |
| .... |
| protocol://host:port/syncope/ |
| .... |
| |
| where `protocol`, `host` and `port` reflect your deployment. |
| ==== |
| |
| ==== REST Authentication and Authorization |
| |
| The <<core>> authentication and authorization is based on http://projects.spring.io/spring-security/[Spring Security^]. |
| |
| As an initial step, authentication is required to obtain, in the `X-Syncope-Token` HTTP header, the |
| unique signed https://en.wikipedia.org/wiki/JSON_Web_Token[JSON Web Token^] to include in all subsequent requests. |
| |
| By providing the token received in the initial exchange, the requester can be identified and checked for authorization, |
| based on owned <<entitlements,entitlements>>. |
| |
| [NOTE] |
| Users can examine their own entitlements looking at the `<<x-syncope-entitlements,X-Syncope-Entitlements>>` |
| header value, and their own privileges looking at the `<<x-syncope-privileges,X-Syncope-Privileges>>` header value. |
| |
| [TIP] |
| ==== |
| The relevant security configuration lies in |
| ifeval::["{snapshotOrRelease}" == "release"] |
| https://github.com/apache/syncope/blob/syncope-{docVersion}/core/spring/src/main/resources/securityContext.xml[securityContext.xml^]; |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| https://github.com/apache/syncope/blob/master/core/spring/src/main/resources/securityContext.xml[securityContext.xml^]; |
| endif::[] |
| while normally not needed, this configuration can be anyway customized via the <<override-behavior,override behavior>>. |
| |
| https://en.wikipedia.org/wiki/Basic_access_authentication[HTTP Basic Authentication] is set for use by default. |
| ==== |
| |
| ===== JWTSSOProvider |
| |
| Besides validating and accepting the JSON Web Tokens generated during the authentication process as sketched above, |
| Apache Syncope can be enabled to cope with tokens generated by third parties, by providing implementations of the |
| ifeval::["{snapshotOrRelease}" == "release"] |
| https://github.com/apache/syncope/blob/syncope-{docVersion}/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTSSOProvider.java[JWTSSOProvider^] |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| https://github.com/apache/syncope/tree/master/core/spring/src/main/java/org/apache/syncope/core/spring/security/JWTSSOProvider.java[JWTSSOProvider^] |
| endif::[] |
| interface. |
| |
| [[authorization-summary]] |
| .Authorization Summary |
| **** |
| The set of RESTful services provided by Apache Syncope can be divided as: |
| |
| . endpoints accessible without any sort of authentication (e.g. truly anonymous), for self-registration and |
| <<password-reset,password reset>>; |
| . endpoints disclosing information about the given Syncope deployment (available <<schema,schema>>, configured |
| <<extensions,extensions>>, Groups, ...), requiring some sort of shared authentication defined by the |
| `anonymousKey` value in the `security.properties` file - for more information, read about Spring Security's |
| http://docs.spring.io/spring-security/site/docs/4.2.x/reference/htmlsingle/#anonymous[Anonymous Authentication^]; |
| . endpoints for self-service (self-update, password change, ...), requiring user authentication and no entitlements; |
| . endpoints for administrative operations, requiring user authentication with authorization granted by the related |
| <<entitlements,entitlements>>, handed over to users via <<roles,roles>>. |
| **** |
| |
| ==== REST Headers |
| |
| Apache Syncope supports a number of HTTP headers as detailed below, in addition to the common HTTP headers such as |
| `Accept`, `Content-Type`, etc. |
| |
| [TIP] |
| It is possible to deal with the headers below when using the <<client-library>> via the `SyncopeClient` class methods. |
| |
| ===== X-Syncope-Token |
| |
| `X-Syncope-Token` is returned on response to <<rest-authentication-and-authorization,successful authentication>>, and |
| contains the unique signed https://en.wikipedia.org/wiki/JSON_Web_Token[JSON Web Token^] identifying the authenticated |
| user. |
| |
| The value returned for the `X-Syncope-Token` header must be included in all subsequent requests, in order for the |
| requester to be checked for authorization, as part of the standard https://tools.ietf.org/html/rfc6750[Bearer^] |
| `Authorization` header. |
| |
| .Obtaining JWT with http://curl.haxx.se/[curl^] |
| ==== |
| .... |
| curl -I -u admin:password -X POST http://localhost:9080/syncope/rest/accessTokens/login |
| .... |
| returns |
| .... |
| HTTP/1.1 204 |
| X-Syncope-Token: eyJ0e.. |
| .... |
| which can then be used to make a call to the REST API |
| ..... |
| curl -I -H "Authorization: Bearer eyJ0e.." http://localhost:9080/syncope/rest/users/self |
| ..... |
| ==== |
| |
| The token duration can be configured via the `jwt.lifetime.minutes` property - see |
| <<configuration-parameters, below>> for details. |
| |
| ===== X-Syncope-Domain |
| |
| `X-Syncope-Domain` can be optionally set for requests (when not set, `Master` is assumed) to select the target |
| <<domains,domain>>. + |
| The value for this header is provided in all responses. |
| |
| ===== X-Syncope-Key and Location |
| |
| When creating an entity (User, Group, Schema, External Resource, ...) these two headers are populated respectively with |
| the entity key (which may be auto-generated) and the absolute URI identifying the new REST resource. |
| |
| ===== X-Application-Error-Code and X-Application-Error-Info |
| |
| If the requested operation is in error, `X-Application-Error-Code` will contain the error code (mostly from |
| ifeval::["{snapshotOrRelease}" == "release"] |
| https://github.com/apache/syncope/blob/syncope-{docVersion}/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java[ClientExceptionType^]) |
| endif::[] |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| https://github.com/apache/syncope/blob/master/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java[ClientExceptionType^]) |
| endif::[] |
| and `X-Application-Error-Info` might be optionally populated with more details, if available. |
| |
| ===== X-Syncope-Delegated-By |
| |
| When requesting an operation under <<delegation,Delegation>>, this header must be provided to indicate the delegating |
| User, either by their username or key. |
| |
| ===== X-Syncope-Null-Priority-Async |
| |
| When set to `true`, this request header instructs the <<propagation,propagation process>> not to wait for completion |
| when communicating with <<external-resource-details,External Resources>> with no priority set. |
| |
| ===== Prefer and Preference-Applied |
| |
| Some REST endpoints allow the clients to request certain behavior; this is done via the `Prefer` header. |
| |
| When `Prefer` is specified in the request, the response will feature the `Preference-Applied` header, with value set |
| to the effective preference applied. |
| |
| ====== return-content / return-no-content |
| |
| REST endpoints for creating, updating or deleting Users, Groups or Any Objects return the entity in the response payload |
| by default. + |
| If this is not required, the `Prefer` request header can be set to `return-no-content` (`return-content` will instead |
| keep the default behavior). |
| |
| [TIP] |
| Use `Prefer: return-no-content` in scenarios where it is important to avoid unnecessary data in the response payload. |
| |
| ====== respond-async |
| |
| The <<batch>> endpoint can be requested for <<asynchronous-batch-processing,asynchronous processing>>. |
| |
| ===== ETag, If-Match and If-None-Match |
| |
| For each response containing Users, Groups or Any Objects, the https://en.wikipedia.org/wiki/HTTP_ETag[ETag^] header is |
| generated, which contains the latest modification date. |
| |
| This value can be passed, during subsequent requests to modify the same entity, via the `If-Match` or |
| `If-None-Match` headers. + |
| When the provided `If-Match` value does not match the latest modification date of the entity, an error is reported and |
| the requested operation is not performed. |
| |
| [TIP] |
| The combined usage of `ETag` and `If-Match` can be enforced to implement optimistic concurrency control over Users, |
| Groups and Any Objects operations. |
| |
| ===== X-Syncope-Entitlements |
| |
| When invoking the REST endpoint `/users/self` in `GET`, the `X-Syncope-Entitlements` response header will list all |
| the <<entitlements,entitlements>> owned by the requesting user. |
| |
| ===== X-Syncope-Delegations |
| |
| When invoking the REST endpoint `/users/self` in `GET`, the `X-Syncope-Delegations` response header will list all |
| delegating users for each <<delegation,Delegation>> for which the requesting user is delegated. |
| |
| ===== X-Syncope-Privileges |
| |
| When invoking the REST endpoint `/users/self` in `GET`, the `X-Syncope-Privileges` response header will list all |
| the <<privileges,privileges>> owned by the requesting user. |
| |
| ==== Batch |
| |
| Batch requests allow grouping multiple operations into a single HTTP request payload. + |
| A batch request is represented as a https://tools.ietf.org/html/rfc2046[Multipart MIME v1.0 message^], a standard format |
| allowing the representation of multiple parts, each of which may have a different content type (currently |
| JSON, YAML or XML), within a single request. |
| |
| Batch requests are handled by the `/batch` REST endpoint: via HTTP `POST` method to submit requests, via HTTP `GET` |
| method to fetch responses <<asynchronous-batch-processing,asynchronously>>. |
| |
| [NOTE] |
| The specification and implementation of batch processing in Apache Syncope is inspired by the standards defined |
| by http://docs.oasis-open.org/odata/odata/v4.0/os/part1-protocol/odata-v4.0-os-part1-protocol.html#_Toc372793748[OData 4.0^] |
| |
| ===== Batch requests |
| |
| The batch request must contain a `Content-Type` header specifying a content type of `multipart/mixed` and a boundary |
| specification as defined in https://tools.ietf.org/html/rfc2046[RFC2046^]. |
| |
| The body of a batch request is made up of a series of individual requests, each represented as a distinct MIME part |
| (i.e. separated by the boundary defined in the `Content-Type` header). |
| |
| Core will process the requests within a batch request sequentially. |
| |
| An individual request must include a `Content-Type` header with value `application/http` and a |
| `Content-Transfer-Encoding` header with value `binary`. |
| |
| .Sample batch request |
| ==== |
| ---- |
| --batch_61bfef8d-0a00-41aa-b775-7b6efff37652 // <1> |
| Content-Type: application/http |
| Content-Transfer-Encoding: binary |
| ^M // <2> |
| POST /users HTTP/1.1 // <3> |
| Accept: application/json |
| Content-Length: 1157 |
| Content-Type: application/json |
| ^M |
| {"@class":"org.apache.syncope.common.lib.to.UserTO","key":null,"type":"USER","realm":"/"} |
| --batch_61bfef8d-0a00-41aa-b775-7b6efff37652 |
| Content-Type: application/http |
| Content-Transfer-Encoding: binary |
| ^M |
| POST /groups HTTP/1.1 // <4> |
| Accept: application/xml |
| Content-Length: 628 |
| Content-Type: application/xml |
| ^M |
| <?xml version="1.0" encoding="UTF-8" standalone="yes"?><syncope30:group xmlns:syncope30="http://syncope.apache.org/3.0"> |
| </syncope30:group> |
| --batch_61bfef8d-0a00-41aa-b775-7b6efff37652 |
| Content-Type: application/http |
| Content-Transfer-Encoding: binary |
| ^M |
| PATCH /users/24eb15aebatch@syncope.apache.org HTTP/1.1 // <5> |
| Accept: application/json |
| Content-Length: 362 |
| Content-Type: application/json |
| Prefer: return-no-content |
| ^M |
| {"@class":"org.apache.syncope.common.lib.request.UserUR","key":"24eb15aebatch@syncope.apache.org"} |
| --batch_61bfef8d-0a00-41aa-b775-7b6efff37652 |
| Content-Type: application/http |
| Content-Transfer-Encoding: binary |
| ^M |
| DELETE /groups/287ede7c-98eb-44e8-979d-8777fa077e12 HTTP/1.1 // <6> |
| --batch_61bfef8d-0a00-41aa-b775-7b6efff37652-- |
| ---- |
| <1> message boundary |
| <2> represents CR LF |
| <3> user create, with JSON payload (shortened) |
| <4> group create, with XML payload (shortened) |
| <5> user update, with JSON payload (shortened) |
| <6> group delete |
| ==== |
| |
| ===== Batch responses |
| |
| Requests within a batch are evaluated according to the same semantics used when the request appears outside the context |
| of a batch. |
| |
| The order of individual requests in a batch request is significant. |
| |
| If the set of request headers of a batch request are valid (the `Content-Type` is set to `multipart/mixed`, etc.) |
| Core will return a `200 OK` HTTP response code to indicate that the request was accepted for processing, and the |
| related execution results. |
| |
| If Core receives a batch request with an invalid set of headers it will return a `400 Bad Request` code and perform no |
| further processing of the request. |
| |
| A response to a batch request must contain a `Content-Type` header with value `multipart/mixed`. |
| |
| Structurally, a batch response body must match one-to-one with the corresponding batch request body, such that the same |
| multipart MIME message structure defined for requests is used for responses |
| |
| .Sample batch response |
| ==== |
| ---- |
| --batch_61bfef8d-0a00-41aa-b775-7b6efff37652 // <1> |
| Content-Type: application/http |
| Content-Transfer-Encoding: binary |
| ^M // <2> |
| HTTP/1.1 201 Created // <3> |
| Content-Type: application/json |
| Date: Thu, 09 Aug 2018 09:55:46 GMT |
| ETag: "1533808545975" |
| Location: http://localhost:9080/syncope/rest/users/d399ba84-12e3-43d0-99ba-8412e303d083 |
| X-Syncope-Domain: Master |
| X-Syncope-Key: d399ba84-12e3-43d0-99ba-8412e303d083 |
| ^M |
| {"entity":{"@class":"org.apache.syncope.common.lib.to.UserTO"} |
| --batch_61bfef8d-0a00-41aa-b775-7b6efff37652 |
| Content-Type: application/http |
| Content-Transfer-Encoding: binary |
| ^M |
| HTTP/1.1 201 Created // <4> |
| Content-Type: application/xml |
| Date: Thu, 09 Aug 2018 09:55:46 GMT |
| ETag: "1533808546342" |
| Location: http://localhost:9080/syncope/rest/groups/843b2fc3-b8a8-4a8b-bb2f-c3b8a87a8b2e |
| X-Syncope-Domain: Master |
| X-Syncope-Key: 843b2fc3-b8a8-4a8b-bb2f-c3b8a87a8b2e |
| ^M |
| <?xml version="1.0" encoding="UTF-8" standalone="yes"?> |
| <syncope30:provisioningResult xmlns:syncope30="http://syncope.apache.org/3.0"></syncope30:provisioningResult> |
| --batch_61bfef8d-0a00-41aa-b775-7b6efff37652 |
| Content-Type: application/http |
| Content-Transfer-Encoding: binary |
| ^M |
| HTTP/1.1 204 No Content // <5> |
| Content-Length: 0 |
| Date: Thu, 09 Aug 2018 09:55:47 GMT |
| Preference-Applied: return-no-content |
| X-Syncope-Domain: Master |
| ^M |
| --batch_61bfef8d-0a00-41aa-b775-7b6efff37652 |
| Content-Type: application/http |
| Content-Transfer-Encoding: binary |
| ^M |
| HTTP/1.1 200 OK // <6> |
| Content-Type: application/json |
| Date: Thu, 09 Aug 2018 09:55:47 GMT |
| X-Syncope-Domain: Master |
| ^M |
| {"entity":{"@class":"org.apache.syncope.common.lib.to.GroupTO"} |
| --batch_61bfef8d-0a00-41aa-b775-7b6efff37652-- |
| ---- |
| <1> message boundary (same as request) |
| <2> represents CR LF |
| <3> user create response, with JSON payload (shortened) |
| <4> group create respose, with XML payload (shortened) |
| <5> user update, no content as `Prefer: return-no-content` <<return-content-return-no-content,was specified>> |
| <6> group delete response, with JSON payload (shortened) |
| ==== |
| |
| ===== Asynchronous Batch Processing |
| |
| Batch requests may be executed asynchronously by <<respond-async,including>> the `respond-async` preference in the |
| `Prefer` header. |
| |
| Core will return an empty response, with status `202 Accepted`. |
| |
| Clients can poll the `/batch` endpoint in `GET` by passing the same boundary used for request: if `202 Accepted` is |
| returned, then the request is still under processing; otherwise, `200 OK` will be returned, along with the full batch |
| response. + |
| Once retrieved, the batch response is not available any more from the `/batch` endpoint. |
| |
| ==== Search |
| |
| It is possible to search for Users, Groups and Any Objects matching a set of given conditions expressed through |
| https://cxf.apache.org/docs/jax-rs-search.html#JAX-RSSearch-FeedItemQueryLanguage[FIQL^]. |
| |
| The https://tools.ietf.org/html/draft-nottingham-atompub-fiql-00[Feed Item Query Language^] (FIQL, pronounced “fickle”) |
| is a simple but flexible, URI-friendly syntax for expressing filters across the entries in a syndicated feed. |
| |
| The FIQL queries can be passed (among other parameters) to the search endpoints available, e.g. |
| |
| * `GET /users?fiql=query` |
| * `GET /groups?fiql=query` |
| * `GET /anyObjects?fiql=query` |
| * `GET /resources/{resource}/{anytype}?fiql=query` |
| |
| where: |
| |
| * `query` is an URL-encoded string representation of the given FIQL query, as in the following examples; |
| * `resource` is one of defined <<external-resources,external resources>>; |
| * `anytype` is one of defined <<anytype,any types>>. |
| |
| .Simple attribute match |
| ==== |
| ---- |
| username==rossini |
| ---- |
| ==== |
| |
| .Wildcard attribute match |
| ==== |
| ---- |
| username==*ini |
| ---- |
| ==== |
| |
| .Case-insensitive attribute match |
| ==== |
| ---- |
| username=~rOsSiNi |
| ---- |
| ==== |
| |
| .Case-insensitive wildcard attribute match |
| ==== |
| ---- |
| username=~*iNi |
| ---- |
| ==== |
| |
| .Null attribute match |
| ==== |
| ---- |
| loginDate==$null |
| ---- |
| ==== |
| |
| .Date attribute comparison |
| ==== |
| ---- |
| lastLoginDate=ge=2016-03-02 15:21:22 |
| ---- |
| ==== |
| |
| .Resource assignment match |
| ==== |
| ---- |
| $resources==resource-ldap |
| ---- |
| ==== |
| |
| .Group membership match (only for Users and Any Objects) |
| ==== |
| ---- |
| $groups==root |
| ---- |
| ==== |
| .Wildcard group membership match (only for Users and Any Objects) |
| ==== |
| ---- |
| $groups==*child |
| ---- |
| ==== |
| |
| .Role membership match (only for Users) |
| ==== |
| ---- |
| $roles==Other |
| ---- |
| ==== |
| |
| .Type match (only for Any Objects) |
| ==== |
| ---- |
| $type==PRINTER |
| ---- |
| ==== |
| |
| .Complex match (featuring logical AND and OR) |
| ==== |
| ---- |
| username=~*iNi;(loginDate==$null,$roles==Other) |
| ---- |
| ==== |
| |
| ===== Sorting Search Results |
| |
| Search results can be requested for sorting by passing the optional `orderBy` query parameter to the search endpoints |
| available, e.g. |
| |
| * `GET /users?fiql=query&orderBy=sort` |
| * `GET /groups?fiql=query&orderBy=sort` |
| * `GET /anyObjects?fiql=query&orderBy=sort` |
| * `GET /resources/{resource}/{anytype}?orderBy=sort` |
| |
| where `sort` is an URL-encoded string representation of the sort request, as in the following examples. |
| |
| .Single attribute sort, default direction (`ASC`) |
| ==== |
| ---- |
| username |
| ---- |
| ==== |
| |
| .Single attribute sort, with direction |
| ==== |
| ---- |
| username DESC |
| ---- |
| ==== |
| |
| .Multiple attribute sort, with directions |
| ==== |
| ---- |
| email DESC, username ASC |
| ---- |
| ==== |
| |
| ==== Client Library |
| |
| The Java client library simplifies the interaction with the <<core>> by hiding the underlying HTTP |
| communication details and providing native methods and payload objects. |
| |
| The library is available as a Maven artifact: |
| |
| [source,xml,subs="verbatim,attributes"] |
| ---- |
| <dependency> |
| <groupId>org.apache.syncope.client.idm</groupId> |
| <artifactId>syncope-client-idm-lib</artifactId> |
| <version>{docVersion}</version> |
| </dependency> |
| ---- |
| |
| ifeval::["{snapshotOrRelease}" == "snapshot"] |
| |
| [WARNING] |
| ==== |
| Do not forget to add the following repository to your `pom.xml`: |
| |
| [source,xml] |
| ---- |
| <repository> |
| <id>ASF</id> |
| <url>https://repository.apache.org/content/repositories/snapshots/</url> |
| <snapshots> |
| <enabled>true</enabled> |
| </snapshots> |
| </repository> |
| ---- |
| ==== |
| |
| endif::[] |
| |
| [discrete] |
| ===== Initialization |
| |
| First you need to build an instance of `SyncopeClientFactoryBean` by providing the deployment base URL, as follows: |
| |
| [source,java] |
| ---- |
| SyncopeClientFactoryBean clientFactory = new SyncopeClientFactoryBean(). |
| setAddress("http://localhost:9080/syncope/rest/"); |
| ---- |
| |
| You might also select a specific <<domains,domain>> - other than `Master`, choose to exchange XML payloads - rather |
| than JSON (default), to select |
| https://en.wikipedia.org/wiki/HTTP_compression[HTTP compression^] or to set the |
| https://cxf.apache.org/javadoc/latest/org/apache/cxf/configuration/jsse/TLSClientParameters.html[TLS client configuration^] |
| (more options in the |
| http://syncope.apache.org/apidocs/2.1/org/apache/syncope/client/lib/SyncopeClientFactoryBean.html[Javadoc^]): |
| |
| [source,java] |
| ---- |
| TLSClientParameters tlsClientParameters = ...; |
| SyncopeClientFactoryBean clientFactory = new SyncopeClientFactoryBean(). |
| setAddress("http://localhost:9080/syncope/rest/"). |
| setDomain("Two"). |
| setContentType(SyncopeClientFactoryBean.ContentType.XML). |
| setUseCompression(true). |
| setTlsClientParameters(tlsClientParameters); |
| ---- |
| |
| At this point an instance of `SyncopeClient` can be obtained by passing the login credentials via: |
| |
| [source,java] |
| ---- |
| SyncopeClient client = clientFactory.create("admin", "password"); |
| ---- |
| |
| Or you can combine into a single statement as: |
| |
| [source,java] |
| ---- |
| SyncopeClient client = new SyncopeClientFactoryBean(). |
| setAddress("http://localhost:9080/syncope/rest/"). |
| create("admin", "password"); |
| ---- |
| |
| [discrete] |
| ===== Usage |
| |
| Select one of the |
| http://syncope.apache.org/apidocs/2.1/org/apache/syncope/common/rest/api/service/package-summary.html[RESTful services^] |
| and invoke one of the available methods: |
| |
| [source,java] |
| ---- |
| LoggerService loggerService = client.getService(LoggerService.class); |
| |
| LoggerTO loggerTO = loggerService.read(LoggerType.LOG, "org.apache.syncope.core.connid"); |
| loggerTO.setLevel(LoggerLevel.DEBUG); |
| |
| loggerService.update(LoggerType.LOG, loggerTO); |
| ---- |
| |
| [NOTE] |
| More RESTful services could be available besides the |
| http://syncope.apache.org/apidocs/2.1/org/apache/syncope/common/rest/api/service/package-summary.html[default set^], |
| as there might be <<extensions,extensions>> installed in the given deployment; the |
| <<apache-camel-provisioning-manager>> provides the |
| http://syncope.apache.org/apidocs/2.1/org/apache/syncope/common/rest/api/service/CamelRouteService.html[CamelRouteService^], |
| for instance. |
| |
| [TIP] |
| Advanced REST features are also available from `SyncopeClient` instances: check |
| http://syncope.apache.org/apidocs/2.1/org/apache/syncope/client/lib/SyncopeClient.html[the javadoc^] |
| for more information. |
| |
| .Search for Users, Groups or Any Objects |
| ==== |
| All search operations return |
| http://syncope.apache.org/apidocs/2.1/org/apache/syncope/common/lib/to/PagedResult.html[paged result handlers^] |
| which can be exploited both for getting the actual results and for extrapolating pagination coordinates. |
| |
| [source,java] |
| ---- |
| UserService userService = client.getService(UserService.class); |
| |
| int count = userService.search(new AnyQuery.Builder().page(0).size(0).build()).getTotalCount(); // <1> |
| |
| PagedResult<UserTO> matchingUsers = userService.search( |
| new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM). |
| fiql(SyncopeClient.getUserSearchConditionBuilder().is("username").equalTo("ros*ini").query()). |
| build()); // <2> |
| |
| PagedResult<UserTO> matchingUsers = userService.search( |
| new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM). |
| fiql(SyncopeClient.getUserSearchConditionBuilder().isNull("loginDate").query()). |
| build()); // <3> |
| |
| PagedResult<UserTO> matchingUsers = userService.search( |
| new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM). |
| fiql(SyncopeClient.getUserSearchConditionBuilder().inRoles("Other").query()). |
| build()); // <4> |
| |
| AnyObjectService anyObjectService = client.getService(AnyObjectService.class); |
| |
| PagedResult<AnyObjectTO> matchingAnyObjects = anyObjectService.search( |
| new AnyQuery.Builder().realm(SyncopeConstants.ROOT_REALM). |
| fiql(SyncopeClient.getAnyObjectSearchConditionBuilder("PRINTER").query()). |
| build()); // <5> |
| |
| GroupService groupService = client.getService(GroupService.class); |
| |
| PagedResult<GroupTO> matchingGroups = groupService.search( |
| new AnyQuery.Builder().realm("/even/two").page(3).size(150). |
| fiql(SyncopeClient.getGroupSearchConditionBuilder().isAssignable(). |
| and("name").equalTo("palo*").query()). |
| build()); // <6> |
| ---- |
| <1> get the total number of users available in the given deployment (and <<domains,domain>>) |
| <2> get users in the root realm with username matching the provided wildcard expression |
| <3> get users in the root realm with no values for `loginDate`, i.e. that have never authenticated to the |
| given deployment |
| <4> get users in the root realm with <<roles,role>> `Other` assigned |
| <5> get all any objects in the root realm with <<anytype,type>> `PRINTER` |
| <6> get all groups that can be assigned to users or any objects in the `/even/two` realm - third page of the result, |
| where each page contains 150 items |
| ==== |
| |
| .Delete several users at once |
| ==== |
| [source,java] |
| ---- |
| BatchRequest batchRequest = client.batch(); // <1> |
| |
| UserService batchUserService = batchRequest.getService(UserService.class); |
| |
| final int pageSize = 100; |
| final int count = userService.search( |
| new AnyQuery.Builder().page(0).size(0).build()).getTotalCount(); // <2> |
| for (int page = 1; page <= (count / pageSize) + 1; page++) { |
| for (UserTO user : userService.search( |
| new AnyQuery.Builder().page(page).size(pageSize).build()).getResult()) { // <3> |
| |
| batchUserService.delete(user.getKey()); // <4> |
| } |
| } |
| |
| BatchResponse batchResponse = batchRequest.commit(); // <5> |
| List<BatchResponseItem> batchResponseItems = batchResponse.getItems(); // <6> |
| ---- |
| <1> begin the batch request |
| <2> get the total number of users available in the given deployment (and <<domains,domain>>) |
| <3> loop through all users available, using paginated search |
| <4> add each user's deletion to the batch request |
| <5> send the batch request for processing |
| <6> examine the batch results |
| ==== |
| |
| .Self-read own profile information |
| ==== |
| [source,java] |
| ---- |
| Pair<Map<String, Set<String>>, UserTO> self = client.self(); |
| UserTO userTO = self.getRight(); // <1> |
| Map<String, Set<String>> realm2entitlements = self.getLeft(); // <2> |
| ---- |
| <1> http://syncope.apache.org/apidocs/2.1/org/apache/syncope/common/lib/to/UserTO.html[UserTO^] of the requesting user |
| <2> for each <<realms,realm>>, the owned <<entitlements,entitlements>> |
| ==== |
| |
| .Change user status |
| ==== |
| [source,java] |
| ---- |
| String key = ...; // <1> |
| StatusR statusR = new StatusR(); |
| statusR.setKey(key); |
| statusR.setType(StatusRType.SUSPEND); // <2> |
| UserTO userTO = userService.status(statusR). |
| readEntity(new GenericType<ProvisioningResult<UserTO>>() { |
| }).getEntity(); // <3> |
| ---- |
| <1> assume the key of the user to be suspended is known in advance |
| <2> `ACTIVATE`, `SUSPEND`, `REACTIVATE` values are accepted, and honoured depending on the actual status of the user |
| being updated |
| <3> request for user update and read back the updated entity |
| ==== |