Groups

A group associates a name to a list of principals. It is useful in order to handle permissions. Groups are defined in buckets.

A group is a mapping with the following attributes:

  • data: attributes of the group object
    • id: the group object id
    • last_modified: the timestamp of the last modification
    • members: a list of principals
  • permissions: the ACLs for the group object (e.g who is allowed to read or update the group object itself.)

When used in permissions definitions, the full group URI has to be used:

{
    "write": ["/buckets/blog/groups/authors", "github:lili"],
    "read": ["system.Everyone"]
}

Creating a group

POST /buckets/(bucket_id)/groups
Synopsis:Creates a new bucket group with a generated ID.

Requires authentication

Example Request

$ echo '{"data": {"members": ["basicauth:206691a25679e4e1135f16aa77ebcf211c767393c4306cfffe6cc228ac0886b6"]}}' | http POST http://localhost:8888/v1/buckets/blog/groups --auth="token:bob-token" --verbose
POST /v1/buckets/blog/groups HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
Authorization: Basic Ym9iOg==
Connection: keep-alive
Content-Length: 102
Content-Type: application/json
Host: localhost:8888
User-Agent: HTTPie/0.9.2

{
    "data": {
        "members": [
            "basicauth:206691a25679e4e1135f16aa77ebcf211c767393c4306cfffe6cc228ac0886b6"
        ]
    }
}

Example Response

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

{
    "data": {
        "id": "wZjuQfpS",
        "last_modified": 1434644222033,
        "members": [
            "basicauth:206691a25679e4e1135f16aa77ebcf211c767393c4306cfffe6cc228ac0886b6"
        ]
    },
    "permissions": {
        "write": [
            "basicauth:206691a25679e4e1135f16aa77ebcf211c767393c4306cfffe6cc228ac0886b6"
        ]
    }
}

HTTP Status Codes

  • 200 OK: This object already exists, the one stored on the database is returned
  • 201 Created: The object was created
  • 400 Bad Request: The request body is invalid
  • 401 Unauthorized: The request is missing authentication headers
  • 401 Forbidden: The user is not allowed to perform the operation, or the resource is not accessible
  • 406 Not Acceptable: The client doesn’t accept supported responses Content-Type
  • 412 Precondition Failed: List has changed since value in If-Match header
  • 415 Unsupported Media Type: The client request was not sent with a correct Content-Type

Replacing a group

PUT /buckets/(bucket_id)/groups/(group_id)
Synopsis:Creates or replaces a group with a chosen ID.

Requires authentication

Example Request

$ echo '{"data": {"members": ["basicauth:206691a25679e4e1135f16aa77ebcf211c767393c4306cfffe6cc228ac0886b6"]}}' | http put http://localhost:8888/v1/buckets/blog/groups/readers --auth="token:bob-token" --verbose
PUT /v1/buckets/blog/groups/readers HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
Authorization: Basic Ym9iOg==
Connection: keep-alive
Content-Length: 102
Content-Type: application/json
Host: localhost:8888
User-Agent: HTTPie/0.9.2

{
    "data": {
        "members": [
            "basicauth:206691a25679e4e1135f16aa77ebcf211c767393c4306cfffe6cc228ac0886b6"
        ]
    }
}

Example Response

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

{
    "data": {
        "id": "readers",
        "last_modified": 1434645661227,
        "members": [
            "basicauth:206691a25679e4e1135f16aa77ebcf211c767393c4306cfffe6cc228ac0886b6"
        ]
    },
    "permissions": {
        "write": [
            "basicauth:206691a25679e4e1135f16aa77ebcf211c767393c4306cfffe6cc228ac0886b6"
        ]
    }
}

Validation and conflicts behaviour is similar to creating objects (POST).

If the If-Match: "<timestamp>" request header is provided as described in the section about timestamps, and if the object has changed meanwhile, a 412 Precondition Failed error is returned.

If the If-None-Match: * request header is provided and if there is already an existing object with this id, a 412 Precondition Failed error is returned.

Permissions

In the JSON request payloads, at least one of data and permissions must be provided. Permissions can thus be replaced independently from data.

In the case of creation, if only permissions is provided, an empty object is created.

The current user id is always added among the write principals.

See Permissions request payload.

HTTP Status Code

  • 201 Created: The object was created
  • 200 OK: The object was replaced
  • 400 Bad Request: The request body is invalid
  • 401 Unauthorized: The request is missing authentication headers
  • 401 Forbidden: The user is not allowed to perform the operation, or the resource is not accessible
  • 406 Not Acceptable: The client doesn’t accept supported responses Content-Type.
  • 412 Precondition Failed: Record was changed or deleted since value in If-Match header.
  • 415 Unsupported Media Type: The client request was not sent with a correct Content-Type.

Modify a group

PATCH /buckets/(bucket_id)/groups/(group_id)
Synopsis:Modifies an existing group.

Requires authentication

Example Request

$ echo '{"data": {"members": ["basicauth:206691a25679e4e1135f16aa77ebcf211c767393c4306cfffe6cc228ac0886b6"]}}' | http patch http://localhost:8888/v1/buckets/blog/groups/readers --auth="token:bob-token" --verbose
PATCH /v1/buckets/blog/groups/readers HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate
Authorization: Basic Ym9iOg==
Connection: keep-alive
Content-Length: 102
Content-Type: application/json
Host: localhost:8888
User-Agent: HTTPie/0.9.2

{
    "data": {
        "members": [
            "basicauth:206691a25679e4e1135f16aa77ebcf211c767393c4306cfffe6cc228ac0886b6"
        ]
    }
}

Example Response

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

{
    "data": {
        "id": "readers",
        "last_modified": 1434645661227,
        "members": [
            "basicauth:206691a25679e4e1135f16aa77ebcf211c767393c4306cfffe6cc228ac0886b6"
        ]
    },
    "permissions": {
        "write": [
            "basicauth:206691a25679e4e1135f16aa77ebcf211c767393c4306cfffe6cc228ac0886b6"
        ]
    }
}

If the object is missing (or already deleted), a 404 Not Found error is returned. The consumer might decide to ignore it.

If the If-Match: "<timestamp>" request header is provided as described in the section about timestamps, and if the object has changed meanwhile, a 412 Precondition Failed error is returned.

Note

last_modified is updated to the current server timestamp, only if a field value was changed.

Attributes merge

The provided values are merged with the existing object. For example:

  • {"a":"b"} + {"a":"c"}{"a":"c"}
  • {"a":"b"} + {"b":"c"}{"a":"b", "b":"c"}
  • {"a":"b"} + {"a":null}{"a":null} : attributes can’t be removed with patch
  • {"a": {"b":"c"}} + {"a":{"d":"e"}}{"a":{"d":"e"}} : sub-objects are replaced, not merged

Note

JSON-Patch or JSON merge are currently not supported. Any help is welcomed though! See https://github.com/Kinto/kinto/issues/623

Light response body

If a Response-Behavior request header is set to light, only the fields whose value was changed are returned. If set to diff, only the fields whose value became different than the one provided are returned.

Permissions

In the JSON request payloads, at least one of data and permissions must be provided. Permissions can thus be modified independently from data.

The current user id is always added among the write principals.

See Permissions request payload.

HTTP Status Codes

  • 200 OK: The object was modified
  • 400 Bad Request: The request body is invalid, or a read-only field was modified
  • 401 Unauthorized: The request is missing authentication headers
  • 401 Forbidden: The user is not allowed to perform the operation, or the resource is not accessible
  • 401 Forbidden: The object does not exist or was deleted
  • 406 Not Acceptable: The client doesn’t accept supported responses Content-Type.
  • 412 Precondition Failed: Record changed since value in If-Match header
  • 415 Unsupported Media Type: The client request was not sent with a correct Content-Type.

Retrieving a group

GET /buckets/(bucket_id)/groups/(group_id)
Synopsis:Returns the group object.

Requires authentication

Example Request

$ http get http://localhost:8888/v1/buckets/blog/groups/readers --auth="token:bob-token" --verbose
GET /v1/buckets/blog/groups/readers 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

HTTP/1.1 200 OK
Access-Control-Expose-Headers: Backoff, Retry-After, Alert, Last-Modified, ETag
Content-Length: 247
Content-Type: application/json; charset=UTF-8
Date: Thu, 18 Jun 2015 16:44:07 GMT
Etag: "1434645847532"
Last-Modified: Thu, 18 Jun 2015 16:44:07 GMT
Server: waitress

{
    "data": {
        "id": "readers",
        "last_modified": 1434645661227,
        "members": [
            "basicauth:206691a25679e4e1135f16aa77ebcf211c767393c4306cfffe6cc228ac0886b6"
        ]
    },
    "permissions": {
        "write": [
            "basicauth:206691a25679e4e1135f16aa77ebcf211c767393c4306cfffe6cc228ac0886b6"
        ]
    }
}

If the If-None-Match: "<timestamp>" request header is provided, and if the object has not changed meanwhile, a 304 Not Modified is returned.

HTTP Status Codes

  • 200 OK: The request was processed
  • 304 Not Modified: Object did not change since value in If-None-Match header
  • 401 Unauthorized: The request is missing authentication headers
  • 401 Forbidden: The user is not allowed to perform the operation, or theresource is not accessible
  • 404 Not Found: The object does not exist or was deleted
  • 406 Not Acceptable: The client doesn’t accept supported responses Content-Type
  • 412 Precondition Failed: Object changed since value in If-Match header

Retrieving all groups

GET /buckets/(bucket_id)/groups
Synopsis:Returns the list of groups for the bucket.

Requires authentication

Example Request

$ http get http://localhost:8888/v1/buckets/blog/groups --auth="token:bob-token" --verbose
GET /v1/buckets/blog/groups 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

HTTP/1.1 200 OK
Access-Control-Expose-Headers: Backoff, Retry-After, Alert, Content-Length, Next-Page, Total-Records, Last-Modified, ETag
Content-Length: 147
Content-Type: application/json; charset=UTF-8
Date: Thu, 13 Aug 2015 12:16:05 GMT
Etag: "1439468156451"
Last-Modified: Thu, 13 Aug 2015 12:15:56 GMT
Server: waitress
Total-Records: 1

{
    "data": [
        {
            "id": "vAQSwSca",
            "last_modified": 1439468156451,
            "members": [
                "basicauth:206691a25679e4e1135f16aa77ebcf211c767393c4306cfffe6cc228ac0886b6"
            ]
        }
    ]
}

A Total-Records response header indicates the total number of objects of the list (not the response, since it can be paginated).

A Last-Modified response header provides a human-readable (rounded to second) of the current collection timestamp.

For cache and concurrency control, an ETag response header gives the value that consumers can provide in subsequent requests using If-Match and If-None-Match headers (see section about timestamps).

List of available URL parameters

Filtering, sorting, partial responses and paginating can all be combined together.

  • ?_sort=-last_modified&_limit=100&_fields=title

HTTP Status Codes

  • 200 OK: The request was processed
  • 304 Not Modified: List has not changed since value in If-None-Match header
  • 400 Bad Request: The request querystring is invalid
  • 401 Unauthorized: The request is missing authentication headers
  • 401 Forbidden: The user is not allowed to perform the operation, or the resource is not accessible
  • 406 Not Acceptable: The client doesn’t accept supported responses Content-Type
  • 412 Precondition Failed: List has changed since value in If-Match header

Deleting a group

DELETE /buckets/(bucket_id)/groups/(group_id)
Synopsis:Deletes a specific group.

Requires authentication

Example Request

$ http delete http://localhost:8888/v1/buckets/blog/groups/readers --auth="token:bob-token" --verbose
DELETE /v1/buckets/blog/groups/readers 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

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

{
    "data": {
        "deleted": true,
        "id": "readers",
        "last_modified": 1434646049488
    }
}

If the object is missing (or already deleted), a 404 Not Found is returned. The consumer might decide to ignore it.

If the If-Match request header is provided, and if the object has changed meanwhile, a 412 Precondition Failed error is returned.

Note

Once deleted, an object will appear in the list when polling for changes, with a deleted status (delete=true) and will have most of its fields empty.

HTTP Status Codes

  • 200 OK: The object was deleted
  • 401 Unauthorized: The request is missing authentication headers
  • 401 Forbidden: The user is not allowed to perform the operation, or the resource is not accessible
  • 404 Not Found: The object does not exist or was already deleted
  • 406 Not Acceptable: The client doesn’t accept supported responses Content-Type.
  • 412 Precondition Failed: Record changed since value in If-Match header