Changes

stoney core: REST API

5,330 bytes added, 14:15, 7 September 2014
/* Mandatory headers */
= Overview =
 
= Entities, Roles and Relationships =
== Overview ==
Description, how everything works together.Entitlement, Access and Roles
 
== Entities ==
An Entity is always a company or a person.
 
=== Service Provider ===
A service provider is the owner of the stoney cloud installation. One or more employees of the the service provider must be [[#Super User | super users]].
 
=== Reseller(s) ===
A reseller sells services of the service provider as his own. He is responsible for the administration of his customers and their services.
 
=== Customers(s) ===
A customer subscribes to services that the reseller sells. The customer can administrate his own people, employees and services.
 
=== People ===
==== Person ====
A person belonging one or more resellers and one or more customers. Normally, a person would belong to one reseller and one customer.
 
==== Employee ====
A person, which is employed by one or more resellers and/or one or more customers.
 
==== Super User ====
A super user is a person which has the right to complete the REST API functionality. The stoney cloud is delivered with one active super user. See the [[stoney_core:_OpenLDAP_directory_data_organisation#People_.28Superuser.29 | People (Superuser)]] description in the [[stoney core: OpenLDAP directory data organisation]].
 
== Roles ==
The roles are not finalized yet.
 
== Relationships ==
The relationships are hierarchical:
 
'''Service Provider Person''' > '''Reseller Employee''' > '''Customer Employee''' > '''Reseller Person''' and '''Customer Person'''
 
The further down you go, the less rights a person has (this is currently independent from any existing roles, as these have not been finalized yet).
 
=== Service Provider Person (SPP) ===
Definition of a Service Provider Person:
{| border="1" class="wikitable sortable"
! API Attribute
! LDAP Attribute
! Example
! Description
|-
 
 
| id
| uid
| 4000002
| Unique id of the person.
|-
 
| -
| sstBelongsToUID
| 1
| Hidden (internal) attribute, that will lose it's meaning, when the roles are finalized. Makes a person a super user.
|-
 
| isActive
| sstIsActive
| true
| Is the person active or not. Only active people are allowed to authenticate themselves.
|-
 
| belongsToResellerId
| sstBelongsToResellerUID
| 4000000
| Shows the reseller, that the person belongs to (only one reseller possible, N:1 relation).
|-
 
| belongsToCustomerId
| sstBelongsToCustomerUID
| 4000001
| Shows the customer, that the person belongs to (only one customer possible, N:1 relation).
|-
 
| employeeOfId
| sstEmployeeOfUID
| 4000000
| Shows the reseller (in this case), that the person is an employee of (multiple resellers possible, N:M relation).
|-
 
| employeeOfId
| sstEmployeeOfUID
| 4000001
| Shows the customer (in this case), that the person is an employee of (multiple customers possible, N:M relation).
|-
 
|}
 
==== Service Provider Person (SPP) Rights ====
A Service Provider Person can just about do anything. The following rights are unique for a Service Provider Person (SPP):
* SPP.00: '''Create a reseller''': Can create a reseller.
* SPP.01: '''Retrieve all resellers''': Can retrieve all resellers.
* SPP.02: '''Retrieve a reseller''': Can retrieve a reseller.
* SPP.03: '''Update a reseller:''' Can update a reseller.
* SPP.04: '''Partly Update a reseller''': Can partly update a reseller.
* SPP.05: '''Delete reseller''': Can delete a reseller (if no customers, people or services are linked to the reseller).
* SPP.06: '''Create a person''': Can create a person (and make them a super user, an employee of one or more reseller(s) and an employee of one or more reseller(s)).
* SPP.07: '''Retrieve all people''': Can retrieve all people.
* SPP.08: '''Retrieve a person''': Can retrieve a person.
* SPP.09: '''Update a person:''' Can update a person (including making them a super user, an employee of one or more reseller(s) and an employee of one or more reseller(s)).
* SPP.10: '''Partly Update a person''': Can partly update a person.
* SPP.11: '''Delete person''': Can delete a person (if no services are linked to the person).
 
=== Reseller Employee (RE) ===
Definition of a Reseller Employee (RE):
{| border="1" class="wikitable sortable"
! API Attribute
! LDAP Attribute
! Example
! Description
|-
 
 
| id
| uid
| 4000003
| Unique id of the person.
|-
 
| isActive
| sstIsActive
| true
| Is the person active or not. Only active people are allowed to authenticate themselves.
|-
 
| belongsToResellerId
| sstBelongsToResellerUID
| 4000000
| Shows the reseller, that the person belongs to (only one reseller possible, N:1 relation).
|-
 
| belongsToCustomerId
| sstBelongsToCustomerUID
| 4000001
| Shows the customer, that the person belongs to (only one customer possible, N:1 relation).
|-
 
| employeeOfId
| sstEmployeeOfUID
| 4000000
| Shows the reseller (in this case), that the person is an employee of (multiple resellers possible, N:M relation).
|-
 
| employeeOfId
| sstEmployeeOfUID
| 4000001
| Shows the customer (in this case), that the person is an employee of (multiple customers possible, N:M relation).
|-
 
|}
 
==== Reseller Employee (RE) Rights ====
Sees the reseller they belong to, themselves, their own customers, people and their services. The following rights exist for a Reseller Employee (RE) and a Service Provider Person (SPP):
* RE.00: '''Retrieve some resellers''': Can retrieve the reseller(s) they are an employee of.
* RE.01: '''Retrieve a reseller''': Can retrieve one of the reseller(s) they are an employee of.
* RE.02: '''Update a reseller:''' Can update one of the reseller(s) they are an employee of.
* RE.03: '''Partly Update a reseller''': Can partly update one of the reseller(s) they are an employee of.
 
* RE.04: '''Create a customer''': Can create a customer.
* RE.05: '''Retrieve all customers''': Can retrieve all their customers.
* RE.06: '''Retrieve a customer''': Can retrieve one of their customers.
* RE.07: '''Update a customer:''' Can update one of their customers.
* RE.08: '''Partly Update a customer''': Can partly update one of their customers.
* RE.09: '''Delete customer''': Can delete one of their customers (if no people or services are linked to the customer).
 
* RE.10: '''Create a person''': Can create a person (including making them an employee of their reseller(s) and of their customer(s)).
* RE.11: '''Retrieve all people''': Can retrieve all their people (of their reseller(s) and their customer(s)).
* RE.12: '''Retrieve a person''': Can retrieve one of their people (of their reseller(s) and their customer(s)).
* RE.13: '''Update a person:''' Can update a person (including making them an employee of their reseller(s) and of their customer(s)).
* RE.14: '''Partly Update a person''': Can partly update a person.
* RE.15: '''Delete person''': Can delete a person (if no services are linked to the person).
 
=== Customer Employee (CE) ===
Definition of a Customer Employee (CE):
{| border="1" class="wikitable sortable"
! API Attribute
! LDAP Attribute
! Example
! Description
|-
 
 
| id
| uid
| 4000004
| Unique id of the person.
|-
 
| isActive
| sstIsActive
| true
| Is the person active or not. Only active people are allowed to authenticate themselves.
|-
 
| belongsToResellerId
| sstBelongsToResellerUID
| 4000000
| Shows the reseller, that the person belongs to (only one reseller possible, N:1 relation).
|-
 
| belongsToCustomerId
| sstBelongsToCustomerUID
| 4000002
| Shows the customer, that the person belongs to (only one customer possible, N:1 relation).
|-
 
| employeeOfId
| sstEmployeeOfUID
| 4000002
| Shows the customer (in this case), that the person is an employee of (multiple customers possible, N:M relation).
|-
 
|}
 
==== Customer Employee (CE) Rights ====
Sees the customer they belong to, themselves, their own people and their services. The following rights exist for a Customer Employee (CE), a Reseller Employee (RE) and a Service Provider Person (SPP):
* CE.00: '''Retrieve some customers''': Can retrieve the customer(s) they are an employee of.
* CE.01: '''Retrieve a customer''': Can retrieve one of the customer(s) they are an employee of.
* CE.02: '''Update a customer:''' Can update one of the customer(s) they are an employee of.
* CE.03: '''Partly Update a customer''': Can partly update one of the customer(s) they are an employee of.
 
* CE.04: '''Create a person''': Can create a person (including making them an employee of their customer(s)).
* CE.05: '''Retrieve all people''': Can retrieve all their people (of their customer(s)).
* CE.06: '''Retrieve a person''': Can retrieve one of their people (of their customer(s)).
* CE.07: '''Update a person:''' Can update a person (including making them an employee of their customer(s)).
* CE.08: '''Partly Update a person''': Can partly update a person.
* CE.09: '''Delete person''': Can delete a person (if no services are linked to the person).
 
=== Reseller Person (P) and Customer Person (P) ===
Definition of a Reseller Person (P) and Customer Person (P):
{| border="1" class="wikitable sortable"
! API Attribute
! LDAP Attribute
! Example
! Description
|-
 
 
| id
| uid
| 4000005
| Unique id of the person.
|-
 
| isActive
| sstIsActive
| true
| Is the person active or not. Only active people are allowed to authenticate themselves.
|-
 
| belongsToResellerId
| sstBelongsToResellerUID
| 4000000
| Shows the reseller, that the person belongs to (only one reseller possible, N:1 relation).
|-
 
| belongsToCustomerId
| sstBelongsToCustomerUID
| 4000002
| Shows the customer, that the person belongs to (only one customer possible, N:1 relation).
|-
 
|}
 
==== Reseller Person (P) and Customer Person (P) Rights ====
A Reseller Person (P) and Customer Person (P) act exactly the same. They see themselves and their own services.
Sees the customer they belong to, themselves, their own people and their services. The following rights exist for a Reseller Person (P), a Customer Person (P), a Customer Employee (CE), a Reseller Employee (RE) and a Service Provider Person (SPP):
* P.00: '''Retrieve a person''': Can retrieve themselves.
* P.01: '''Update a person:''' Can update themselves.
* P.02: '''Partly Update a person''': Can partly update themselves.
 
= REST API documentation =
=== Reserved Keywords ===
We have some special reserved keywords, which can no be used by the REST API:
* sort: Used for sorting.
* q: Full text search.
* page: Pagination.
 
=== Base URI ===
The RESTful web service has to be accessible via a secure HTTP (HTTPS) base URI, for instance <code>https://api.example.com/v1</code>.
The service needs to accept and send all data in the JSON data interchange format via HTTP, encoded as UTF-8. Thus a client needs to accept and use the [http://tools.ietf.org/html/rfc4627 <code>application/json</code>] media type. Further media types might be supported in the future.
This results in the following required request and respons response headers:
{| class="wikitable sortable"
|-
|-
| <codepre>Accept: application/jsonAccept-Charset: utf-8</codepre>| <codepre>Content-Type: application/json; charset=UTFutf-8</codepre>
|}
* If the client sends an <code>Accept</code> header with an unsupported value (at the moment only <code>application/json</code> is supported), the service will respond with a <code>406</code> (Not Acceptable) [[#Error codes and responses|error code]].
* If the client sends an <code>Accept-Charset</code> header with an unsupported value (at the moment only <code>utf-8</code> is supported), the service will respond with a <code>406</code> (Not Acceptable) [[#Error codes and responses|error code]].
* If no <code>Accept</code> header is sent, the server will use JSON, possibly pretty-printed and annotated.
* If no <code>Accept-Charset</code> header is sent, the server send the response with <code>utf-8</code> as charset.
* If the client sends a <code>Content-Type</code> other than <code>application/json</code> on a POST, PUT or PATCH request, the service will respond with a <code>415</code> (Unsupported Media Type) [[#Error codes and responses|error code]].
* If the client sends invalid JSON, the service will response with a <code>400</code> (Bad Request) HTTP [[#Error codes and responses|error code]] and a descriptive error message within the error object.
* When returning a <code>401</code>, a proper <code>WWW-Authenticate</code> header must be sent as well as documented in [http://tools.ietf.org/html/rfc7235#page-7 RFC7235 (or earlier HTTP 1.1/1.0 RFCs)].
 
Unless otherwise noted, the [http://tools.ietf.org/wg/httpbis/ HTTPbis RFCs] always apply.
Future extension:
| Bad Request
| The request was invalid. A descriptive error message will be sent within the response body.
 
|-
| 401
| Unauthorized
| The client has failed or not yet tried to authenticate.
 
|-
| 403
| Forbidden
| The client is not allowed to access the requested resource.
|-
|-
| 401409| UnauthorizedResource Conflict| The client has failed or not yet tried to authenticate. |-| 403| Forbidden| The client is not allowed to access State of the requested resourcedoesn't permit request.
|-
{
"error": {
"module": "core", "code": 123422, "message": "Validation failedThe request was well-formed but was unable to be followed due to semantic errors."
"details" : [
{
"module": "core", "code" : 54321006, "field" : "firstNameisCompany", "message" : "First name cannot is invalid, true or false will be longer than 35 charactersaccepted"
},
{
"module": "core",
"code" : 5123,
"field" : "password",
Besides the above mentioned headers, the following headers are mandatory.
* every answer to a GET reqest should always include <code>[http://en.wikipedia.org/wiki/HTTP_ETag ETag]</code> and <code>Last-Modified</code> header. This allows a proxy to cache requests and a client to revalidate already fetched data.
* the service must recognize <code>ETag</code>, <code>Last-Modified</code> and <code>Cache-Control: none</code> provided by the client and act accordingly.
* every answer to a GET request must include proper <code>Cache-Control</code> headers
* every PUT and PATCH request to update an object must include the <code>ETag</code> provided by the <code>GET</code> request to fetch the object initially. The API must respond with an <code>428 (Precondition Required)</code> if the ETag is missing.
''Implementation notes'':
=== Relations ===
If a Resources which stand in relation can only exist within another resource, it will be represent by its URI, for examplewith each other are represented as URIs (scoping): * <code>/threadsv1/123resellers/messages4000001/45customers</code>. This URI represents -> collection resource (all customers of reseller with uid=4000001)* <code>/v1/resellers/4000001/customers/4000002</code> -> resource (the message customer with ID #45 uid=4000002 of reseller with uid=4000001) The following queries have the forum thread same effect as the URIs from above:* <code>/v1/customers?belongsToResellerUID=4000001</code> -> collection resource (all customers of reseller with uid=4000001)* <code>/v1/customers/4000002</code> -> resource (the customer with uid=4000002 of reseller with ID #123.uid=4000001)
If a resources can stand by its own, such as users it won't be added as a sub-resource.
Relations are always returned as URIs, which the client can hit.
@TBDFuture possibilities (sub objects) which aren't currently implemented: Shall there be * If a functionality to request the embedding of elementsrelation can only exist within another resource, it will be represent by its URI, for relations that are commonly requested alongside example: <code>/threads/123/messages/45</code>. This URI represents the resource (to save requests)?message with ID #45 of the forum thread with ID #123.
=== Filtering, sorting and searching ===
Filter, sort and search requests are added as query parameters to the resource URI.
For '''filtering''' the objects returned by a resource URI, the name of an object's attribute is added as a query parameter with the required value.For example, get all active user elements: GET /v1/users?status=active
For example, get all active user elements <code>GET /v1/users?status=active</code>
For '''sorting''' the objects returned by a resource URI, the query parameter <code>sort</code> is added with the object's sort attribute(s) as the value. The following example will sort users by lastname and firstname in lexicographic ascending order:
GET /v1/users?sort=lastname,firstname
For '''sorting''' the objects returned by a resource URI, the query parameter <code>The following will sort<users by lastname in lexicographic descending and firstname in lexicographic ascending order: GET /code> is added with the object's v1/users?sort attribute(s) as the value. =-lastname,firstname
For example, The following will sort all users by their last lastname and first name <code>by firstname in lexicographic descending order: GET /v1/users?sort=-lastname,-firstname</code>
For '''full text search''' the objects returned by a resource URI, the query parameter <code>q</code> is added with the value to search for. For example, <code> GET /v1/users?q=Muell</code> will return users named <code>Mueller</code> as well as the ones living at <code>Muellhaldenstrasse</code>.
For full text search over all the available resources visit [[stoney core: Search Resource - REST API]].
For example, to request page number 3 with 40 items per page, a client would send the following GET request:
<pre>
GET /v1/userspeople?page=3&per_page=40
</pre>
=== Input validations ===
The service validates all input it receives from a client and returns a <code>422</code> (Unprocessable Entity) HTTP [[#Error_codes_and_responses|status code together with a descriptive error object]] in case of an input violation (but well-formed JSON). In case a client passes invalid JSON (a JSON parser is unable to parse the JSON string), the service returns a <code >400</code> (Bad Request) HTTP [[#Error_codes_and_responses|status code together with a descriptive error object]]containing the JSON parser error message.
= Notes =
* Sudo mechanism, via custom HTTP header, for example <code>X-USER</code>
=== Reseller resource ===Resource representing a collection of resellers or a specific reseller element. ==== Reseller creation (POST) ====To create a new reseller the client needs to send a HTTP <code>POST</code> request on the reseller collection resource URI <code>https://api.example.com/v1/resellers</code>, including the associated reseller informations.The service will generate a new reseller and responds with a HTTP status code <code>201</code> (Created) on success. The newly created reseller URI is returned within the HTTP location header, which can be used by the client to gather informations about the new reseller. TBD: Table of all attributes (including optional ones) ===== Reseller creation (POST) example ===== '''Request''':<pre>POST /v1/resellers/ HTTP 1.1HOST: api.example.com </pre><pre>Accept: application/jsonContent-Type: application/json</pre><source lang='javascript'>{ "isCompany": true, "billingAddress": { "organizationName": "Reseller Ltd.", "gender": 'm', "givenName": "Name", "surname": "Surname", "postalAddress": "Street Number", "countryCode": "CH", "postalCode": "Postal Code", "localityName": "Locality", "preferredLanguage": "en-GB", "mail": "name.surname@example.com", "telephoneNumber": "+41 00 000 00 00", "mobileTelephoneNumber": "+41 00 000 00 00", "websiteURL": "https://www.example.com/" }}</source> '''Answer''':<pre>HTTP/1.1 201 Created</pre><pre>Content-Type: application/json; charset=UTF-8 Location: https://api.example.com/v1/resellers/4000001</pre><source lang='javascript'>{ "id": 4000001, "location": "https://api.example.com/v1/resellers/4000001",}</source> ==== Reseller retrieval (GET) ==== ===== Reseller collection retrieval (GET) example =====To retrieve existing resellers, the client needs to send a HTTP <code>GET</code> request on the reseller's collection resource URI <code>https://api.example.com/v1/resellers</code>.The service responds with a HTTP status code 200 (OK) on success and returns the various resellers. '''Request''':<pre>GET /v1/resellers/ HTTP 1.1HOST: api.example.com </pre><pre>Accept: application/json</pre> '''Answer''':<pre>HTTP/1.1 200 OK</pre><pre>Content-Type: application/json; charset=UTF-8 </pre><source lang='javascript'>[ { "id": 4000000, "location": "https://api.example.com/v1/resellers/4000000", "isCompany": true, "descriptiveName": "stepping stone GmbH" }, { "id": 4000001, "location": "https://api.example.com/v1/resellers/4000001", "isCompany": true, "descriptiveName": "Company Name or Givenname Surname" }]</source> ===== Reseller element retrieval (GET) example =====To retrieve an existing reseller and fetch the informations associated with it, the client needs to send a HTTP <code>GET</code> request on the reseller's element resource URI (such as <code>https://api.example.com/v1/resellers/4000001</code>.The service responds with a HTTP status code 200 (OK) on success and returns the associated reseller informations. '''Request''':<pre>GET /v1/resellers/4000001 HTTP 1.1HOST: api.example.com </pre><pre>Accept: application/json</pre> '''Answer''':<pre>HTTP/1.1 200 OK</pre><pre>Content-Type: application/json; charset=UTF-8 </pre><source lang='javascript'>{ "id": 4000001, "isCompany": true, "billingAddress": { "organizationName": "Reseller Ltd.", "gender": 'm', "givenName": "Name", "surname": "Surname", "postalAddress": "Street Number", "countryCode": "CH", "postalCode": "Postal Code", "localityName": "Locality", "preferredLanguage": "en-GB", "mail": "name.surname@example.com", "telephoneNumber": "+41 00 000 00 00", "mobileTelephoneNumber": "+41 00 000 00 00", "websiteURL": "https://www.example.com/" } "shippingAddresses": [ TBD, ]}</source> ==== Reseller update (PUT) ====To updates an existing reseller, the client needs to send a HTTP <code>PUT</code> request on the reseller's element resource URI (such as, <code>httpsCategory://api.example.com/v1/resellers/4000001</code>). The service responds with a HTTP status code 200 (OK) on success and returns an empty body.  The <code>PUT</code> method requires one to sent the complete record, thus the work-flow is normally as follows:# A [[#Reseller_retrieval_.28GET.29|GETREST API]] request on the Reseller element URI will be made to fetch the whole document.# Update the fields which content has changed# Send a <code>PUT</code> request with all the reseller data'''Request''':<pre>PUT /v1/resellers/4000001 HTTP 1.1HOST: api.example.com</pre><pre>Accept: application/jsonContent-Type: application/json</pre><source lang='javascript'>{ "id": 4000001, "isCompany": true, "billingAddress": { "organizationName": "Reseller Ltd.", "gender": 'm', "givenName": "Name", "surname": "Surname", "postalAddress": "Street Number", "countryCode": "CH", "postalCode": "Postal Code", "localityName": "Locality", "preferredLanguage": "en-GB", "mail": "name.surname@example.com", "telephoneNumber": "+41 00 000 00 00", "mobileTelephoneNumber": "+41 00 000 00 00", "websiteURL": "https://www.example.com/" } "shippingAddresses": [ TBD, ]}</source> '''Answer''':<pre>HTTP/1.1 200 OK</pre><pre>Content-Type: application/json; charset=UTF-8 </pre><source lang='javascript'></source> ==== Reseller partly update (PATCH) ====To update fields of an existing reseller, the client needs to send a HTTP <code>PATCH</code> request on the reseller's element resource URI (such as, <code>https://api.example.com/v1/resellers/4000001</code>).The service responds with a HTTP status code 200 (OK) on success and returns an empty body.  In contrast to the [[#Reseller_update_.28PUT.29|<code>PUT</code>]] method, only the changed fields are to be included in the request. '''Request''':<pre>PATCH /v1/resellers/4000001 HTTP 1.1HOST: api.example.com</pre><pre>Accept: application/jsonContent-Type: application/json</pre><source lang='javascript'>{ "billingAddress": { "postalAddress": "New Street Number", "preferredLanguage": "de-CH" }}</source> '''Answer''':<pre>HTTP/1.1 200 OK</pre><pre>Content-Type: application/json; charset=UTF-8 </pre><source lang='javascript'></source> ==== Reseller deletion (DELETE) ====To delete an existing reseller, the client needs to send a HTTP <code>DELETE</code> request on the reseller's element resource URI (such as, <code>https://api.example.com/v1/resellers/4000001</code>). The service responds with a HTTP status code <code>200</code> (OK) on success and returns an empty body. '''Request''':<pre>DELETE /v1/resellers/4000001 HTTP 1.1HOST: api.example.com</pre><pre>Accept: application/json</pre><source lang='javascript'></source> '''Answer''':<pre>HTTP/1.1 200 OK</pre><pre>Content-Type: application/json; charset=UTF-8 </pre><source lang='javascript'></source> [[Category:REST APIstoney core]]
SLB, editor, reviewer
3,368
edits