Skip to content

Latest commit

 

History

History
823 lines (599 loc) · 21.3 KB

collections.rst

File metadata and controls

823 lines (599 loc) · 21.3 KB

Collections

A collection belongs to a bucket and stores records.

A collection is a mapping with the following attributes:

  • data: (optional) attributes of the collection object
    • id: the collection object id
    • last_modified: the timestamp of the last modification
    • schema: (optional) a JSON schema to validate the collection records
    • cache_expires: (optional, in seconds) add client cache headers on read-only requests. :ref:`More details...<collection-caching>`
    • and any field you might need
  • permissions: the :term:`ACLs <ACL>` for the collection object

Note

When the built-in plugin kinto.plugins.default_bucket is enabled in configuration, a bucket default is available.

Users are assigned to that bucket which can be used for their personal data.

When going through the default bucket, the collections are created silently upon first access.

Applications can use this default bucket (e.g. /buckets/default/collections/contacts will be the contacts of the current user.

Internally the user default bucket is assigned to an ID, and users can share data from their personnal bucket, by sharing :ref:`its URL using the full ID <buckets-default-id>`.

List bucket collections

.. http:get:: /buckets/(bucket_id)/collections

   :synopsis: List bucket's readable collections

   **Requires authentication**

   **Example Request**

   .. sourcecode:: bash

      $ http GET http://localhost:8888/v1/buckets/blog/collections --auth="bob:p4ssw0rd" --verbose

   .. sourcecode:: http

      GET /v1/buckets/blog/collections HTTP/1.1
      Accept: */*
      Accept-Encoding: gzip, deflate
      Authorization: Basic YWxpY2U6
      Connection: keep-alive
      Host: localhost:8888
      User-Agent: HTTPie/0.9.2

   .. sourcecode:: http

      HTTP/1.1 200 OK
      Access-Control-Expose-Headers: Content-Length, Expires, Alert, Retry-After, Last-Modified, ETag, Pragma, Cache-Control, Backoff, Next-Page
      Cache-Control: no-cache
      Content-Length: 144
      Content-Type: application/json; charset=UTF-8
      Date: Fri, 26 Feb 2016 14:14:40 GMT
      Etag: "1456496072475"
      Last-Modified: Fri, 26 Feb 2016 14:14:32 GMT
      Server: waitress

      {
          "data": [
              {
                  "id": "scores",
                  "last_modified": 1456496072475
              },
              {
                  "id": "game",
                  "last_modified": 1456496060675
              },
              {
                  "id": "articles",
                  "last_modified": 1456496056908
              }
          ]
      }

Delete bucket collections

.. http:delete:: /buckets/(bucket_id)/collections

    :synopsis: Delete every writable collections in this bucket

    **Requires authentication**

    **Example Request**

    .. sourcecode:: bash

        $ http delete http://localhost:8888/v1/buckets/blog/collections --auth="bob:p4ssw0rd" --verbose

    .. sourcecode:: http

        DELETE /v1/buckets/blog/collections HTTP/1.1
        Accept: */*
        Accept-Encoding: gzip, deflate
        Authorization: Basic YWxpY2U6
        Connection: keep-alive
        Content-Length: 0
        Host: localhost:8888
        User-Agent: HTTPie/0.9.2

    **Example Response**

    .. sourcecode:: http

        HTTP/1.1 200 OK
        Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff
        Content-Length: 189
        Content-Type: application/json; charset=UTF-8
        Date: Fri, 26 Feb 2016 14:19:21 GMT
        Server: waitress

        {
            "data": [
                {
                    "deleted": true,
                    "id": "articles",
                    "last_modified": 1456496361303
                },
                {
                    "deleted": true,
                    "id": "game",
                    "last_modified": 1456496361304
                },
                {
                    "deleted": true,
                    "id": "scores",
                    "last_modified": 1456496361305
                }
            ]
        }

Creating a collection

.. http:post:: /buckets/(bucket_id)/collections

   :synopsis: Creates a new collection. If ``id`` is not provided, it is automatically generated.

   **Requires authentication**

   **Example Request**

   .. sourcecode:: bash

      $ echo '{"data": {"id": "articles"}}' | http POST http://localhost:8888/v1/buckets/blog/collections --auth="bob:p4ssw0rd" --verbose

   .. sourcecode:: http

      POST /v1/buckets/blog/collections HTTP/1.1
      Accept: application/json
      Accept-Encoding: gzip, deflate
      Authorization: Basic Ym9iOg==
      Connection: keep-alive
      Content-Length: 29
      Content-Type: application/json
      Host: 127.0.0.1:8888
      User-Agent: HTTPie/0.9.2

      {
          "data": {
              "id": "articles"
          }
      }

   .. sourcecode:: http

      HTTP/1.1 201 Created
      Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff
      Content-Length: 159
      Content-Type: application/json; charset=UTF-8
      Date: Thu, 21 Jan 2016 00:41:25 GMT
      Server: waitress

      {
          "data": {
              "id": "articles",
              "last_modified": 1453336885287
          },
          "permissions": {
              "write": [
                  "account:bob"
              ]
          }
      }

Replacing a collection

.. http:put:: /buckets/(bucket_id)/collections/(collection_id)

    :synopsis: Creates or replaces a collection object.

    **Requires authentication**

    A collection is the parent object of records. It can be viewed as a container where records permissions are assigned globally.

    **Example Request**

    .. sourcecode:: bash

        $ http put http://localhost:8888/v1/buckets/blog/collections/articles --auth="bob:p4ssw0rd" --verbose

    .. sourcecode:: http

        PUT /v1/buckets/blog/collections/articles HTTP/1.1
        Accept: application/json
        Accept-Encoding: gzip, deflate
        Authorization: Basic Ym9iOg==
        Connection: keep-alive
        Content-Length: 0
        Host: localhost:8888
        User-Agent: HTTPie/0.9.2

    .. sourcecode:: http

        HTTP/1.1 201 Created
        Access-Control-Expose-Headers: Backoff, Retry-After, Alert
        Content-Length: 159
        Content-Type: application/json; charset=UTF-8
        Date: Thu, 18 Jun 2015 15:36:34 GMT
        Server: waitress

        {
            "data": {
                "id": "articles",
                "last_modified": 1434641794149
            },
            "permissions": {
                "write": [
                    "account:bob"
                ]
            }
        }

Updating a collection

.. http:patch:: /buckets/(bucket_id)/collections/(collection_id)

    :synopsis: Updates a collection object.

    **Requires authentication**

    A collection is the parent object of records. It can be viewed as
    a container where records permissions are assigned globally.

    **Example Request**

    .. sourcecode:: bash

        $ echo '{"data": {"fingerprint": "9cae1b2d0f2b7d09bcf5c1bf51544274"}}' | http patch http://localhost:8888/v1/buckets/blog/collections/articles --auth="bob:p4ssw0rd" --verbose

    .. sourcecode:: http

        PATCH /v1/buckets/blog/collections/articles HTTP/1.1
        Accept: application/json
        Accept-Encoding: gzip, deflate
        Authorization: Basic Ym9iOg==
        Connection: keep-alive
        Content-Length: 62
        Content-Type: application/json
        Host: localhost:8888
        User-Agent: HTTPie/0.9.2

        {
            "data": {
                "fingerprint": "9cae1b2d0f2b7d09bcf5c1bf51544274"
            }
        }

    .. sourcecode:: http

        HTTP/1.1 200 OK
        Access-Control-Expose-Headers: Backoff, Retry-After, Alert
        Content-Length: 208
        Content-Type: application/json; charset=UTF-8
        Date: Thu, 18 Jun 2015 15:36:34 GMT
        Server: waitress

        {
            "data": {
                "id": "articles",
                "last_modified": 1434641794149,
                "fingerprint": "9cae1b2d0f2b7d09bcf5c1bf51544274"
            },
            "permissions": {
                "write": [
                    "account:bob"
                ]
            }
        }

Retrieving an existing collection

.. http:get:: /buckets/(bucket_id)/collections/(collection_id)

    :synopsis: Returns the collection object.

    **Requires authentication**

    **Example Request**

    .. sourcecode:: bash

        $ http get http://localhost:8888/v1/buckets/blog/collections/articles --auth="bob:p4ssw0rd" --verbose

    .. sourcecode:: http

        GET /v1/buckets/blog/collections/articles HTTP/1.1
        Accept: */*
        Accept-Encoding: gzip, deflate
        Authorization: Basic Ym9iOg==
        Connection: keep-alive
        Host: localhost:8888
        User-Agent: HTTPie/0.9.2


    **Example Response**

    .. sourcecode:: http

        HTTP/1.1 200 OK
        Access-Control-Expose-Headers: Backoff, Retry-After, Alert, Last-Modified, ETag
        Content-Length: 159
        Content-Type: application/json; charset=UTF-8
        Date: Thu, 18 Jun 2015 15:52:31 GMT
        Etag: "1434642751314"
        Last-Modified: Thu, 18 Jun 2015 15:52:31 GMT
        Server: waitress

        {
            "data": {
                "id": "articles",
                "last_modified": 1434641794149
            },
            "permissions": {
                "write": [
                    "account:bob"
                ]
            }
        }

Deleting a collection

.. http:delete:: /buckets/(bucket_id)/collections/(collection_id)

    :synopsis: Deletes a specific collection and **everything under it**.

    **Requires authentication**

    **Example Request**

    .. sourcecode:: bash

        $ http delete http://localhost:8888/v1/buckets/blog/collections/articles --auth="bob:p4ssw0rd" --verbose

    .. sourcecode:: http

        DELETE /v1/buckets/blog/collections/articles HTTP/1.1
        Accept: */*
        Accept-Encoding: gzip, deflate
        Authorization: Basic Ym9iOg==
        Connection: keep-alive
        Content-Length: 0
        Host: localhost:8888
        User-Agent: HTTPie/0.9.2

    **Example Response**

    .. sourcecode:: http

        HTTP/1.1 200 OK
        Access-Control-Expose-Headers: Backoff, Retry-After, Alert
        Content-Length: 71
        Content-Type: application/json; charset=UTF-8
        Date: Thu, 18 Jun 2015 15:54:02 GMT
        Server: waitress

        {
            "data": {
                "deleted": true,
                "id": "articles",
                "last_modified": 1434642842010
            }
        }

Collection JSON schema

Requires setting kinto.experimental_collection_schema_validation to True.

A JSON schema can optionally be associated to a collection.

Once a schema is set, records will be validated during creation or update.

If the validation fails, a |status-400| error response will be returned.

Note

JSON schema is quite verbose and not an ideal solution for every use-case. However it is universal and supported by many programming languages and environments.

Set or replace a schema

Just modify the schema attribute of the collection object:

Example request

$ echo '{
  "data": {
    "schema": {
      "title": "Blog post schema",
      "type": "object",
      "properties": {
          "title": {"type": "string"},
          "body": {"type": "string"}
      },
      "required": ["title"]
    }
  }
}' | http PATCH "http://localhost:8888/v1/buckets/blog/collections/articles" --auth bob:p4ssw0rd --verbose
PATCH /v1/buckets/blog/collections/articles HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
Authorization: Basic YWRtaW46
Connection: keep-alive
Content-Length: 236
Content-Type: application/json; charset=utf-8
Host: localhost:8888
User-Agent: HTTPie/0.8.0

{
    "data": {
        "schema": {
            "properties": {
                "body": {
                    "type": "string"
                },
                "title": {
                    "type": "string"
                }
            },
            "required": [
                "title"
            ],
            "title": "Blog post schema",
            "type": "object"
        }
    }
}

Example response

HTTP/1.1 200 OK
Access-Control-Expose-Headers: Backoff, Retry-After, Alert, Content-Length
Content-Length: 300
Content-Type: application/json; charset=UTF-8
Date: Fri, 21 Aug 2015 12:31:40 GMT
Etag: "1440160300818"
Last-Modified: Fri, 21 Aug 2015 12:31:40 GMT
Server: waitress

{
    "data": {
        "id": "articles",
        "last_modified": 1440160300818,
        "schema": {
            "properties": {
                "body": {
                    "type": "string"
                },
                "title": {
                    "type": "string"
                }
            },
            "required": [
                "title"
            ],
            "title": "Blog post schema",
            "type": "object"
        }
    },
    "permissions": {
        "write": [
            "account:bob"
        ]
    }
}

Records validation

Once a schema has been defined, the posted records must match it:

$ echo '{"data": {
    "body": "Fails if no title"
}}' | http POST http://localhost:8888/v1/buckets/blog/collections/articles/records --auth "bob:p4ssw0rd"
HTTP/1.1 400 Bad Request
Access-Control-Expose-Headers: Backoff, Retry-After, Alert
Content-Length: 192
Content-Type: application/json; charset=UTF-8
Date: Wed, 10 Jun 2015 10:17:01 GMT
Server: waitress

{
    "code": 400,
    "details": [
        {
            "description": "'title' is a required property",
            "location": "body",
            "name": "title"
        }
    ],
    "errno": 107,
    "error": "Invalid parameters",
    "message": "'title' is a required property"
}

Schema migrations

Kinto does not take care of schema migrations. But it gives the basics for clients to manage it.

If the validation succeeds, the record will receive a schema field with the schema version (i.e. the collection current last_modified timestamp).

It becomes possible to use this schema field as a filter on the collection records endpoint in order to obtain the records that were not validated against a particular version of the schema.

For example, GET /buckets/blog/collections/articles/records?min_schema=123456.

Remove a schema

In order to remove the schema of a collection, just modify the schema field to an empty mapping.

Example request

echo '{"data": {"schema": {}} }' | http PATCH "http://localhost:8888/v1/buckets/blog/collections/articles" --auth bob:p4ssw0rd --verbose
PATCH /v1/buckets/blog/collections/articles HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
Authorization: Basic YWRtaW46
Connection: keep-alive
Content-Length: 26
Content-Type: application/json; charset=utf-8
Host: localhost:8888
User-Agent: HTTPie/0.8.0

{
    "data": {
        "schema": {}
    }
}

Example response

HTTP/1.1 200 OK
Access-Control-Expose-Headers: Backoff, Retry-After, Alert, Content-Length
Content-Length: 171
Content-Type: application/json; charset=UTF-8
Date: Fri, 21 Aug 2015 12:27:04 GMT
Etag: "1440159981842"
Last-Modified: Fri, 21 Aug 2015 12:26:21 GMT
Server: waitress

{
    "data": {
        "id": "articles",
        "last_modified": 1440159981842,
        "schema": {}
    },
    "permissions": {
        "write": [
            "account:bob"
        ]
    }
}

Same schema for every collection

It is possible to define a JSON schema that will apply to every collections records inside a bucket.

This can be useful when a particular application creates collections whose records should all be validated against the same schema.

To achieve that, instead of storing the definition in the schema field in the metadata of a particular collection, the definition can be stored in the record:schema field in the metadata of the bucket.

PATCH /v1/buckets/blog HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
Authorization: Basic YWRtaW46
Connection: keep-alive
Content-Length: 236
Content-Type: application/json; charset=utf-8
Host: localhost:8888
User-Agent: HTTPie/0.8.0

{
    "data": {
        "record:schema": {
            "properties": {
                "body": {
                    "type": "string"
                },
                "title": {
                    "type": "string"
                }
            },
            "required": [
                "title"
            ],
            "title": "Blog post schema",
            "type": "object"
        }
    }
}

Collection metadata validation

By default, only a few fields in the collection metadata must respect a particular schema (eg. schema, cache_expires...), and metadata will accept any kind of additional fields.

In order to validate the additional fields, it is possible to define a schema on the parent bucket metadata.

To achieve that, just modify the collection:schema attribute of the parent bucket object:

Example request

$ echo '{
  "data": {
    "collection:schema": {
      "title": "Admin Collection",
      "type": "object",
      "properties": {
          "uiSchema": {"type": "object"},
      }
    }
  }
}' | http PATCH "http://localhost:8888/v1/buckets/blog" --auth bob:p4ssw0rd --verbose

Collection caching

With the cache_expires attribute on a collection, it is possible to add client cache control response headers for read-only requests. The client (or cache server or proxy) will use them to cache the collection records for a certain amount of time, in seconds.

For example, set it to 3600 (1 hour):

echo '{"data": {"cache_expires": 3600} }' | http PATCH "http://localhost:8888/v1/buckets/blog/collections/articles" --auth bob:p4ssw0rd

From now on, the cache control headers are set for the GET requests:

http  "http://localhost:8888/v1/buckets/blog/collections/articles/records" --auth bob:p4ssw0rd
HTTP/1.1 200 OK
Access-Control-Expose-Headers: Backoff, Retry-After, Alert, Content-Length, Next-Page, Last-Modified, ETag, Cache-Control, Expires, Pragma
Cache-Control: max-age=3600
Content-Length: 11
Content-Type: application/json; charset=UTF-8
Date: Mon, 14 Sep 2015 13:51:47 GMT
Etag: "1442238450779"
Expires: Mon, 14 Sep 2015 14:51:47 GMT
Last-Modified: Mon, 14 Sep 2015 13:47:30 GMT
Server: waitress

{
    "data": [{}]
}

If set to 0, the collection records become explicitly uncacheable (no-cache).

echo '{"data": {"cache_expires": 0} }' | http PATCH "http://localhost:8888/v1/buckets/blog/collections/articles" --auth bob:p4ssw0rd
HTTP/1.1 200 OK
Access-Control-Expose-Headers: Backoff, Retry-After, Alert, Content-Length, Next-Page, Last-Modified, ETag, Cache-Control, Expires, Pragma
Cache-Control: max-age=0, must-revalidate, no-cache, no-store
Content-Length: 11
Content-Type: application/json; charset=UTF-8
Date: Mon, 14 Sep 2015 13:54:51 GMT
Etag: "1442238450779"
Expires: Mon, 14 Sep 2015 13:54:51 GMT
Last-Modified: Mon, 14 Sep 2015 13:47:30 GMT
Pragma: no-cache
Server: waitress

{
    "data": []
}

Note

This can also be forced from settings, see :ref:`configuration section <configuration-client-caching>`.