Merge branch 'master' into appservice-swagger
Conflicts: specification/application_service_api.rst
This commit is contained in:
commit
f95d19cecd
24 changed files with 914 additions and 392 deletions
148
api/client-server/v1/create_room.yaml
Normal file
148
api/client-server/v1/create_room.yaml
Normal file
|
@ -0,0 +1,148 @@
|
|||
swagger: '2.0'
|
||||
info:
|
||||
title: "Matrix Client-Server v1 Room Creation API"
|
||||
version: "1.0.0"
|
||||
host: localhost:8008
|
||||
schemes:
|
||||
- https
|
||||
- http
|
||||
basePath: /_matrix/client/api/v1
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
securityDefinitions:
|
||||
accessToken:
|
||||
type: apiKey
|
||||
description: The user_id or application service access_token
|
||||
name: access_token
|
||||
in: query
|
||||
paths:
|
||||
"/createRoom":
|
||||
post:
|
||||
summary: Create a new room
|
||||
description: |-
|
||||
Create a new room with various configuration options.
|
||||
security:
|
||||
- accessToken: []
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
description: The desired room configuration.
|
||||
schema:
|
||||
type: object
|
||||
example: |-
|
||||
{
|
||||
"preset": "public_chat",
|
||||
"room_alias_name": "thepub",
|
||||
"name": "The Grand Duke Pub",
|
||||
"topic": "All about happy hour",
|
||||
"creation_content": {
|
||||
"m.federate": false
|
||||
}
|
||||
}
|
||||
properties:
|
||||
visibility:
|
||||
type: string
|
||||
enum: ["public", "private"]
|
||||
description: |-
|
||||
A ``public`` visibility indicates that the room will be shown
|
||||
in the published room list. A ``private`` visibility will hide
|
||||
the room from the published room list. Rooms default to
|
||||
``private`` visibility if this key is not included. NB: This
|
||||
should not be confused with ``join_rules`` which also uses the
|
||||
word ``public``.
|
||||
room_alias_name:
|
||||
type: string
|
||||
description: |-
|
||||
The desired room alias **local part**. If this is included, a
|
||||
room alias will be created and mapped to the newly created
|
||||
room. The alias will belong on the *same* home server which
|
||||
created the room. For example, if this was set to "foo" and
|
||||
sent to the homeserver "example.com" the complete room alias
|
||||
would be ``#foo:example.com``.
|
||||
name:
|
||||
type: string
|
||||
description: |-
|
||||
If this is included, an ``m.room.name`` event will be sent
|
||||
into the room to indicate the name of the room. See Room
|
||||
Events for more information on ``m.room.name``.
|
||||
topic:
|
||||
type: string
|
||||
description: |-
|
||||
If this is included, an ``m.room.topic`` event will be sent
|
||||
into the room to indicate the topic for the room. See Room
|
||||
Events for more information on ``m.room.topic``.
|
||||
invite:
|
||||
type: array
|
||||
description: |-
|
||||
A list of user IDs to invite to the room. This will tell the
|
||||
server to invite everyone in the list to the newly created room.
|
||||
items:
|
||||
type: string
|
||||
creation_content:
|
||||
title: CreationContent
|
||||
type: object
|
||||
description: |-
|
||||
Extra keys to be added to the content of the ``m.room.create``.
|
||||
The server will clober the following keys: ``creator``. Future
|
||||
versions of the specification may allow the server to clobber
|
||||
other keys.
|
||||
initial_state:
|
||||
type: array
|
||||
description: |-
|
||||
A list of state events to set in the new room. This allows
|
||||
the user to override the default state events set in the new
|
||||
room. The expected format of the state events are an object
|
||||
with type, state_key and content keys set.
|
||||
Takes precedence over events set by ``presets``, but gets
|
||||
overriden by ``name`` and ``topic`` keys.
|
||||
items:
|
||||
type: object
|
||||
title: StateEvent
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
state_key:
|
||||
type: string
|
||||
content:
|
||||
type: string
|
||||
preset:
|
||||
type: string
|
||||
enum: ["private_chat", "public_chat", "trusted_private_chat"]
|
||||
description: |-
|
||||
Convenience parameter for setting various default state events
|
||||
based on a preset. Must be either:
|
||||
|
||||
``private_chat`` =>
|
||||
``join_rules`` is set to ``invite``.
|
||||
``history_visibility`` is set to ``shared``.
|
||||
|
||||
``trusted_private_chat`` =>
|
||||
``join_rules`` is set to ``invite``.
|
||||
``history_visibility`` is set to ``shared``.
|
||||
All invitees are given the same power level as the room creator.
|
||||
|
||||
``public_chat``: =>
|
||||
``join_rules`` is set to ``public``.
|
||||
``history_visibility`` is set to ``shared``.
|
||||
|
||||
responses:
|
||||
200:
|
||||
description: Information about the newly created room.
|
||||
schema:
|
||||
type: object
|
||||
description: Information about the newly created room.
|
||||
properties:
|
||||
room_id:
|
||||
type: string
|
||||
description: |-
|
||||
The created room's ID.
|
||||
examples:
|
||||
application/json: |-
|
||||
{
|
||||
"room_id": "!sefiuhWgwghwWgh:example.com"
|
||||
}
|
||||
400:
|
||||
description: >
|
||||
The request body is malformed or the room alias specified is already taken.
|
131
api/client-server/v1/message_pagination.yaml
Normal file
131
api/client-server/v1/message_pagination.yaml
Normal file
|
@ -0,0 +1,131 @@
|
|||
swagger: '2.0'
|
||||
info:
|
||||
title: "Matrix Client-Server v1 Rooms API"
|
||||
version: "1.0.0"
|
||||
host: localhost:8008
|
||||
schemes:
|
||||
- https
|
||||
- http
|
||||
basePath: /_matrix/client/api/v1
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
securityDefinitions:
|
||||
accessToken:
|
||||
type: apiKey
|
||||
description: The user_id or application service access_token
|
||||
name: access_token
|
||||
in: query
|
||||
paths:
|
||||
"/rooms/{roomId}/messages":
|
||||
get:
|
||||
summary: Get a list of events for this room
|
||||
description: |-
|
||||
This API returns a list of message and state events for a room. It uses
|
||||
pagination query parameters to paginate history in the room.
|
||||
security:
|
||||
- accessToken: []
|
||||
parameters:
|
||||
- in: path
|
||||
type: string
|
||||
name: roomId
|
||||
description: The room to get events from.
|
||||
required: true
|
||||
x-example: "!636q39766251:example.com"
|
||||
- in: query
|
||||
type: string
|
||||
name: from
|
||||
description: |-
|
||||
The token to start returning events from. This token can be obtained
|
||||
from the initial sync API.
|
||||
required: true
|
||||
x-example: "s345_678_333"
|
||||
- in: query
|
||||
type: string
|
||||
enum: ["b", "f"]
|
||||
name: dir
|
||||
description: |-
|
||||
The direction to return events from.
|
||||
required: true
|
||||
x-example: "b"
|
||||
- in: query
|
||||
type: integer
|
||||
name: limit
|
||||
description: |-
|
||||
The maximum number of events to return. Default: 10.
|
||||
x-example: "3"
|
||||
responses:
|
||||
200:
|
||||
description: A list of messages with a new token to request more.
|
||||
schema:
|
||||
type: object
|
||||
description: A list of messages with a new token to request more.
|
||||
properties:
|
||||
start:
|
||||
type: string
|
||||
description: |-
|
||||
The token to start paginating from. If ``dir=b`` this will be
|
||||
the token supplied in ``from``.
|
||||
end:
|
||||
type: string
|
||||
description: |-
|
||||
The token the pagination ends at. If ``dir=b`` this token should
|
||||
be used again to request even earlier events.
|
||||
chunk:
|
||||
type: array
|
||||
description: |-
|
||||
A list of room events.
|
||||
items:
|
||||
type: object
|
||||
title: RoomEvent
|
||||
examples:
|
||||
application/json: |-
|
||||
{
|
||||
"start": "t47429-4392820_219380_26003_2265",
|
||||
"end": "t47409-4357353_219380_26003_2265",
|
||||
"chunk": [
|
||||
{
|
||||
"origin_server_ts": 1444812213737,
|
||||
"user_id": "@alice:example.com",
|
||||
"event_id": "$1444812213350496Caaaa:example.com",
|
||||
"content": {
|
||||
"body": "hello world",
|
||||
"msgtype":"m.text"
|
||||
},
|
||||
"room_id":"!Xq3620DUiqCaoxq:example.com",
|
||||
"type":"m.room.message",
|
||||
"age": 1042
|
||||
},
|
||||
{
|
||||
"origin_server_ts": 1444812194656 ,
|
||||
"user_id": "@bob:example.com",
|
||||
"event_id": "$1444812213350496Cbbbb:example.com",
|
||||
"content": {
|
||||
"body": "the world is big",
|
||||
"msgtype":"m.text"
|
||||
},
|
||||
"room_id":"!Xq3620DUiqCaoxq:example.com",
|
||||
"type":"m.room.message",
|
||||
"age": 20123
|
||||
},
|
||||
{
|
||||
"origin_server_ts": 1444812163990,
|
||||
"user_id": "@bob:example.com",
|
||||
"event_id": "$1444812213350496Ccccc:example.com",
|
||||
"content": {
|
||||
"name": "New room name"
|
||||
},
|
||||
"prev_content": {
|
||||
"name": "Old room name"
|
||||
},
|
||||
"state_key": "",
|
||||
"room_id":"!Xq3620DUiqCaoxq:example.com",
|
||||
"type":"m.room.name",
|
||||
"age": 50789
|
||||
}
|
||||
]
|
||||
}
|
||||
403:
|
||||
description: >
|
||||
You aren't a member of the room.
|
|
@ -30,7 +30,9 @@ paths:
|
|||
- in: query
|
||||
type: string
|
||||
name: from
|
||||
description: The token to stream from.
|
||||
description: |-
|
||||
The token to stream from. This token is either from a previous
|
||||
request to this API or from the initial sync API.
|
||||
required: false
|
||||
x-example: "s3456_9_0"
|
||||
- in: query
|
||||
|
@ -39,16 +41,6 @@ paths:
|
|||
description: The maximum time in milliseconds to wait for an event.
|
||||
required: false
|
||||
x-example: "35000"
|
||||
- in: query
|
||||
type: string
|
||||
name: archived
|
||||
description: |-
|
||||
Whether to include rooms that the user has left. If absent then
|
||||
only rooms that the user has been invited to or has joined are
|
||||
included. If set to "true" then rooms that the user has left are
|
||||
included as well.
|
||||
required: false
|
||||
x-example: "true"
|
||||
responses:
|
||||
200:
|
||||
description: "The events received, which may be none."
|
||||
|
@ -78,19 +70,19 @@ paths:
|
|||
start:
|
||||
type: string
|
||||
description: |-
|
||||
A token which correlates to the first value in ``chunk``. Used
|
||||
for pagination.
|
||||
A token which correlates to the first value in ``chunk``. This
|
||||
is usually the same token supplied to ``from=``.
|
||||
end:
|
||||
type: string
|
||||
description: |-
|
||||
A token which correlates to the last value in ``chunk``. Used
|
||||
for pagination.
|
||||
A token which correlates to the last value in ``chunk``. This
|
||||
token should be used in the next request to ``/events``.
|
||||
chunk:
|
||||
type: array
|
||||
description: "An array of events."
|
||||
items:
|
||||
type: object
|
||||
title: RoomEvent
|
||||
title: Event
|
||||
allOf:
|
||||
- "$ref": "core-event-schema/room_event.json"
|
||||
400:
|
||||
|
@ -110,6 +102,16 @@ paths:
|
|||
description: The maximum number of messages to return for each room.
|
||||
required: false
|
||||
x-example: "2"
|
||||
- in: query
|
||||
type: boolean
|
||||
name: archived
|
||||
description: |-
|
||||
Whether to include rooms that the user has left. If ``false`` then
|
||||
only rooms that the user has been invited to or has joined are
|
||||
included. If set to ``true`` then rooms that the user has left are
|
||||
included as well. By default this is ``false``.
|
||||
required: false
|
||||
x-example: "true"
|
||||
responses:
|
||||
200:
|
||||
description: The user's current state.
|
||||
|
|
101
api/client-server/v2_alpha/registration.yaml
Normal file
101
api/client-server/v2_alpha/registration.yaml
Normal file
|
@ -0,0 +1,101 @@
|
|||
swagger: '2.0'
|
||||
info:
|
||||
title: "Matrix Client-Server v2 Registration API"
|
||||
version: "1.0.0"
|
||||
host: localhost:8008
|
||||
schemes:
|
||||
- https
|
||||
- http
|
||||
basePath: /_matrix/client/api/v2_alpha
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
paths:
|
||||
"/register":
|
||||
post:
|
||||
summary: Register for an account on this homeserver.
|
||||
description: |-
|
||||
Register for an account on this homeserver.
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
schema:
|
||||
type: object
|
||||
example: |-
|
||||
{
|
||||
"username": "cheeky_monkey",
|
||||
"password": "ilovebananas",
|
||||
"bind_email": false
|
||||
}
|
||||
properties:
|
||||
bind_email:
|
||||
type: boolean
|
||||
description: |-
|
||||
If true, the server binds the email used for authentication to
|
||||
the Matrix ID with the ID Server.
|
||||
username:
|
||||
type: string
|
||||
description: |-
|
||||
The local part of the desired Matrix ID. If omitted,
|
||||
the homeserver MUST generate a Matrix ID local part.
|
||||
password:
|
||||
type: string
|
||||
description: The desired password for the account.
|
||||
required: ["password"]
|
||||
responses:
|
||||
200:
|
||||
description: The account has been registered.
|
||||
examples:
|
||||
application/json: |-
|
||||
{
|
||||
"user_id": "@cheeky_monkey:matrix.org",
|
||||
"access_token": "abc123",
|
||||
"home_server": "matrix.org",
|
||||
"refresh_token": "def456"
|
||||
}
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
user_id:
|
||||
type: string
|
||||
description: The fully-qualified Matrix ID that has been registered.
|
||||
access_token:
|
||||
type: string
|
||||
description: |-
|
||||
An access token for the account.
|
||||
This access token can then be used to authorize other requests.
|
||||
The access token may expire at some point, and if so, it SHOULD come with a ``refresh_token``.
|
||||
There is no specific error message to indicate that a request has failed because
|
||||
an access token has expired; instead, if a client has reason to believe its
|
||||
access token is valid, and it receives an auth error, they should attempt to
|
||||
refresh for a new token on failure, and retry the request with the new token.
|
||||
refresh_token:
|
||||
type: string
|
||||
# TODO: Work out how to linkify /tokenrefresh
|
||||
description: |-
|
||||
(optional) A ``refresh_token`` may be exchanged for a new ``access_token`` using the /tokenrefresh API endpoint.
|
||||
home_server:
|
||||
type: string
|
||||
description: The hostname of the Home Server on which the account has been registered.
|
||||
400:
|
||||
description: |-
|
||||
Part of the request was invalid. This may include one of the following error codes:
|
||||
|
||||
* ``M_USER_IN_USE`` : The desired user ID is already taken.
|
||||
* ``M_EXCLUSIVE`` : The desired user ID is in the exclusive namespace
|
||||
claimed by an application service.
|
||||
|
||||
These errors may be returned at any stage of the registration process,
|
||||
including after authentication if the requested user ID was registered
|
||||
whilst the client was performing authentication.
|
||||
examples:
|
||||
application/json: |-
|
||||
{
|
||||
"errcode": "M_USER_IN_USE",
|
||||
"error": "Desired user ID is already taken."
|
||||
}
|
||||
429:
|
||||
description: This request was rate-limited.
|
||||
schema:
|
||||
"$ref": "definitions/error.yaml"
|
|
@ -1,5 +1,11 @@
|
|||
#!/bin/bash -e
|
||||
# Runs z-schema over all of the schema files (looking for matching examples)
|
||||
|
||||
if ! which z-schema; then
|
||||
echo >&2 "Need to install z-schema; run: sudo npm install -g z-schema"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
find schema/v1/m.* | while read line
|
||||
do
|
||||
split_path=(${line///// })
|
||||
|
|
18
event-schemas/examples/v1/m.room.avatar
Normal file
18
event-schemas/examples/v1/m.room.avatar
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"age": 242352,
|
||||
"content": {
|
||||
"info": {
|
||||
"h": 398,
|
||||
"w": 394,
|
||||
"mimetype": "image/jpeg",
|
||||
"size": 31037
|
||||
},
|
||||
"url": "mxc://localhost/JWEIFJgwEIhweiWJE"
|
||||
},
|
||||
"origin_server_ts": 1431961217939,
|
||||
"event_id": "$WLGTSEFSEF:localhost",
|
||||
"type": "m.room.avatar",
|
||||
"state_key": "",
|
||||
"room_id": "!Cuyf34gef24t:localhost",
|
||||
"user_id": "@example:localhost"
|
||||
}
|
|
@ -8,10 +8,34 @@
|
|||
"token": "pc98",
|
||||
"public_key": "abc123",
|
||||
"key_validity_url": "https://magic.forest/verifykey",
|
||||
"signature": "q1w2e3",
|
||||
"signed": {
|
||||
"mxid": "@alice:localhost",
|
||||
"token": "pc98",
|
||||
"signatures": {
|
||||
"magic.forest": {
|
||||
"ed25519:0": "poi098"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sender": "@zun:zun.soft"
|
||||
}
|
||||
},
|
||||
"invite_room_state": [
|
||||
{
|
||||
"type": "m.room.name",
|
||||
"state_key": "",
|
||||
"content": {
|
||||
"name": "Forest of Magic"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "m.room.join_rules",
|
||||
"state_key": "",
|
||||
"content": {
|
||||
"join_rules": "invite"
|
||||
}
|
||||
}
|
||||
],
|
||||
"state_key": "@alice:localhost",
|
||||
"origin_server_ts": 1431961217939,
|
||||
"event_id": "$WLGTSEFSEF:localhost",
|
||||
|
|
64
event-schemas/schema/v1/m.room.avatar
Normal file
64
event-schemas/schema/v1/m.room.avatar
Normal file
|
@ -0,0 +1,64 @@
|
|||
{
|
||||
"title": "RoomAvatar",
|
||||
"description": "A picture that is associated with the room. This can be displayed alongside the room information.",
|
||||
"type": "object",
|
||||
"allOf": [{
|
||||
"$ref": "core-event-schema/state_event.json"
|
||||
}],
|
||||
"properties": {
|
||||
"content": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"url": {
|
||||
"type": "string",
|
||||
"description": "The URL to the image."
|
||||
},
|
||||
"thumbnail_url": {
|
||||
"type": "string",
|
||||
"description": "The URL to the thumbnail of the image."
|
||||
},
|
||||
"thumbnail_info": {
|
||||
"type": "object",
|
||||
"title": "ImageInfo",
|
||||
"description": "Metadata about the image referred to in ``thumbnail_url``.",
|
||||
"allOf": [{
|
||||
"$ref": "core-event-schema/msgtype_infos/image_info.json"
|
||||
}]
|
||||
},
|
||||
"info": {
|
||||
"type": "object",
|
||||
"title": "ImageInfo",
|
||||
"description": "Metadata about the image referred to in ``url``.",
|
||||
"properties": {
|
||||
"size": {
|
||||
"type": "integer",
|
||||
"description": "Size of the image in bytes."
|
||||
},
|
||||
"w": {
|
||||
"type": "integer",
|
||||
"description": "The width of the image in pixels."
|
||||
},
|
||||
"h": {
|
||||
"type": "integer",
|
||||
"description": "The height of the image in pixels."
|
||||
},
|
||||
"mimetype": {
|
||||
"type": "string",
|
||||
"description": "The mimetype of the image, e.g. ``image/jpeg``."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": ["url"]
|
||||
},
|
||||
"state_key": {
|
||||
"type": "string",
|
||||
"description": "A zero-length string.",
|
||||
"pattern": "^$"
|
||||
},
|
||||
"type": {
|
||||
"type": "string",
|
||||
"enum": ["m.room.avatar"]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"type": "object",
|
||||
"title": "The current membership state of a user in the room.",
|
||||
"description": "Adjusts the membership state for a user in a room. It is preferable to use the membership APIs (``/rooms/<room id>/invite`` etc) when performing membership actions rather than adjusting the state directly as there are a restricted set of valid transformations. For example, user A cannot force user B to join a room, and trying to force this state change directly will fail. The ``third_party_invite`` property will be set if the invite was an ``m.room.third_party_invite`` event, and absent if the invite was an ``m.room.member`` event.",
|
||||
"description": "Adjusts the membership state for a user in a room. It is preferable to use the membership APIs (``/rooms/<room id>/invite`` etc) when performing membership actions rather than adjusting the state directly as there are a restricted set of valid transformations. For example, user A cannot force user B to join a room, and trying to force this state change directly will fail. \n\nThe ``third_party_invite`` property will be set if the invite was an ``m.room.third_party_invite`` event, and absent if the invite was an ``m.room.member`` event.\n\nThis event also includes an ``invite_room_state`` key **outside the** ``content`` **key**. This contains an array of ``StrippedState`` Events. These events provide information on a few select state events such as the room name.",
|
||||
"allOf": [{
|
||||
"$ref": "core-event-schema/state_event.json"
|
||||
}],
|
||||
|
@ -24,7 +24,7 @@
|
|||
},
|
||||
"third_party_invite": {
|
||||
"type": "object",
|
||||
"title": "invite",
|
||||
"title": "Invite",
|
||||
"properties": {
|
||||
"token": {
|
||||
"type": "string",
|
||||
|
@ -38,16 +38,32 @@
|
|||
"type": "string",
|
||||
"description": "A base64-encoded ed25519 key with which token must be signed."
|
||||
},
|
||||
"signature": {
|
||||
"type": "string",
|
||||
"description": "A base64-encoded signature of token with public_key."
|
||||
"signed": {
|
||||
"type": "object",
|
||||
"title": "signed",
|
||||
"properties": {
|
||||
"mxid": {
|
||||
"type": "string",
|
||||
"description": "The invited matrix user ID. Must be equal to the user_id property of the event."
|
||||
},
|
||||
"token": {
|
||||
"type": "string",
|
||||
"description": "The token property of the containing third_party_invite object."
|
||||
},
|
||||
"signatures": {
|
||||
"type": "object",
|
||||
"description": "A single signature from the verifying server, in the format specified by the Signing Events section.",
|
||||
"title": "Signatures"
|
||||
}
|
||||
},
|
||||
"required": ["mxid", "signatures", "token"]
|
||||
},
|
||||
"sender": {
|
||||
"type": "string",
|
||||
"description": "The matrix user ID of the user who send the invite which is being used."
|
||||
}
|
||||
},
|
||||
"required": ["token", "key_validity_url", "public_key", "signature", "sender"]
|
||||
"required": ["token", "key_validity_url", "public_key", "sender", "signed"]
|
||||
}
|
||||
},
|
||||
"required": ["membership"]
|
||||
|
@ -65,17 +81,23 @@
|
|||
"description": "A subset of the state of the room at the time of the invite, if ``membership`` is ``invite``",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"title": "StateEvent",
|
||||
"title": "StrippedState",
|
||||
"description": "A stripped down state event, with only the ``type``, ``state_key`` and ``content`` keys.",
|
||||
"required": ["type", "state_key", "content"],
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "The ``type`` for the event.",
|
||||
"enum": ["m.room.join_rules", "m.room.canonical_alias", "m.room.avatar", "m.room.name"]
|
||||
},
|
||||
"state_key": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"description": "The ``state_key`` for the event."
|
||||
},
|
||||
"content": {
|
||||
"type": "object"
|
||||
"title": "EventContent",
|
||||
"type": "object",
|
||||
"description": "The ``content`` for the event."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ Threat: Unrecoverable Consistency Violations
|
|||
++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
An attacker could send messages which created an unrecoverable "split-brain"
|
||||
state in the cluster such that the victim's servers could no longer dervive a
|
||||
state in the cluster such that the victim's servers could no longer derive a
|
||||
consistent view of the chatroom state.
|
||||
|
||||
Threat: Bad History
|
||||
|
@ -63,7 +63,7 @@ Spoofing
|
|||
An attacker could try to send a message claiming to be from the victim without
|
||||
the victim having sent the message in order to:
|
||||
|
||||
* Impersonate the victim while performing illict activity.
|
||||
* Impersonate the victim while performing illicit activity.
|
||||
* Obtain privileges of the victim.
|
||||
|
||||
Threat: Altering Message Contents
|
||||
|
@ -81,7 +81,7 @@ with a phony "origin" field.
|
|||
Spamming
|
||||
~~~~~~~~
|
||||
|
||||
The attacker could try to send a high volume of solicicted or unsolicted
|
||||
The attacker could try to send a high volume of solicited or unsolicited
|
||||
messages to the victim in order to:
|
||||
|
||||
* Find victims for scams.
|
|
@ -147,6 +147,9 @@ application services MUST implement these APIs. These APIs are defined below.
|
|||
|
||||
{{application_service_http_api}}
|
||||
|
||||
|
||||
.. _create the user: `sect:asapi-permissions`_
|
||||
|
||||
Client-Server v2 API Extensions
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -165,11 +168,8 @@ additional permissions granting the AS permission to masquerade as a matrix user
|
|||
|
||||
Inputs:
|
||||
- Application service token (``access_token``)
|
||||
- User ID in the AS namespace to act as.
|
||||
|
||||
Either:
|
||||
- User ID in the AS namespace to act as.
|
||||
Or:
|
||||
- OAuth2 token of real user (which may end up being an access token)
|
||||
Notes:
|
||||
- This will apply on all aspects of the CS API, except for Account Management.
|
||||
- The ``as_token`` is inserted into ``access_token`` which is usually where the
|
||||
|
@ -184,12 +184,6 @@ Notes:
|
|||
access_token: The application service token
|
||||
user_id: The desired user ID to act as.
|
||||
|
||||
/path?access_token=$token&user_token=$token
|
||||
|
||||
Query Parameters:
|
||||
access_token: The application service token
|
||||
user_token: The token granted to the AS by the real user
|
||||
|
||||
Timestamp massaging
|
||||
+++++++++++++++++++
|
||||
The application service may want to inject events at a certain time (reflecting
|
||||
|
@ -212,6 +206,9 @@ Notes:
|
|||
|
||||
Server admin style permissions
|
||||
++++++++++++++++++++++++++++++
|
||||
|
||||
.. _sect:asapi-permissions:
|
||||
|
||||
The home server needs to give the application service *full control* over its
|
||||
namespace, both for users and for room aliases. This means that the AS should
|
||||
be able to create/edit/delete any room alias in its namespace, as well as
|
||||
|
@ -238,7 +235,7 @@ including the AS token on a ``/register`` request, along with a login type of
|
|||
|
||||
Application services which attempt to create users or aliases *outside* of
|
||||
their defined namespaces will receive an error code ``M_EXCLUSIVE``. Similarly,
|
||||
normal users who attempt to create users or alises *inside* an application
|
||||
normal users who attempt to create users or aliases *inside* an application
|
||||
service-defined namespace will receive the same ``M_EXCLUSIVE`` error code,
|
||||
but only if the application service has defined the namespace as ``exclusive``.
|
||||
|
||||
|
@ -291,9 +288,10 @@ an API is exposed.
|
|||
Room Aliases
|
||||
++++++++++++
|
||||
We may want to expose some 3P network rooms so Matrix users can join them directly,
|
||||
e.g. IRC rooms. We don't want to expose every 3P network room though, e.g. mailto,
|
||||
tel. Rooms which are publicly accessible (e.g. IRC rooms) can be exposed as an alias by
|
||||
the application service. Private rooms (e.g. sending an email to someone) should not
|
||||
e.g. IRC rooms. We don't want to expose every 3P network room though, e.g.
|
||||
``mailto``, ``tel``. Rooms which are publicly accessible (e.g. IRC rooms) can be
|
||||
exposed as an alias by the application service. Private rooms
|
||||
(e.g. sending an email to someone) should not
|
||||
be exposed in this way, but should instead operate using normal invite/join semantics.
|
||||
Therefore, the ID conventions discussed below are only valid for public rooms which
|
||||
expose room aliases.
|
||||
|
@ -313,9 +311,9 @@ SHOULD be mapped in the same way as "user" URIs.
|
|||
|
||||
Event fields
|
||||
++++++++++++
|
||||
We recommend that any gatewayed events should include an ``external_url`` field
|
||||
in their content to provide a way for Matrix clients to link into the 'native'
|
||||
client from which the event originated. For instance, this could contain the
|
||||
message-ID for emails/nntp posts, or a link to a blog comment when gatewaying
|
||||
blog comment traffic in & out of matrix
|
||||
We recommend that any events that originated from a remote network should
|
||||
include an ``external_url`` field in their content to provide a way for Matrix
|
||||
clients to link into the 'native' client from which the event originated.
|
||||
For instance, this could contain the message-ID for emails/nntp posts, or a link
|
||||
to a blog comment when bridging blog comment traffic in & out of Matrix.
|
||||
|
|
@ -1,9 +1,6 @@
|
|||
Client-Server API
|
||||
=================
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The client-server API provides a simple lightweight API to let clients send
|
||||
messages, control rooms and synchronise conversation history. It is designed to
|
||||
support both lightweight clients which store no state and lazy-load data from
|
||||
|
@ -31,7 +28,10 @@ return with a status of 401 and the error code, ``M_MISSING_TOKEN`` or
|
|||
``M_UNKNOWN_TOKEN`` respectively.
|
||||
|
||||
User-Interactive Authentication API
|
||||
-----------------------------------
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. _sect:auth-api:
|
||||
|
||||
This section refers to API Version 2.
|
||||
|
||||
Some API endpoints such as ``login`` or ``register`` require authentication that
|
||||
|
@ -159,7 +159,7 @@ absence of that login stage type in the 'completed' array indicating whether
|
|||
that stage is complete.
|
||||
|
||||
Example
|
||||
~~~~~~~
|
||||
+++++++
|
||||
At a high level, the requests made for an API call completing an auth flow with
|
||||
three stages will resemble the following diagram::
|
||||
|
||||
|
@ -201,7 +201,7 @@ This specification defines the following login types:
|
|||
- ``m.login.dummy``
|
||||
|
||||
Password-based
|
||||
~~~~~~~~~~~~~~
|
||||
++++++++++++++
|
||||
:Type:
|
||||
``m.login.password``
|
||||
:Description:
|
||||
|
@ -222,7 +222,7 @@ To respond to this type, reply with an auth dict as follows::
|
|||
weak passwords with an error code ``M_WEAK_PASSWORD``.
|
||||
|
||||
Google ReCaptcha
|
||||
~~~~~~~~~~~~~~~~
|
||||
++++++++++++++++
|
||||
:Type:
|
||||
``m.login.recaptcha``
|
||||
:Description:
|
||||
|
@ -236,7 +236,7 @@ To respond to this type, reply with an auth dict as follows::
|
|||
}
|
||||
|
||||
Token-based
|
||||
~~~~~~~~~~~
|
||||
+++++++++++
|
||||
:Type:
|
||||
``m.login.token``
|
||||
:Description:
|
||||
|
@ -267,7 +267,7 @@ newly provisioned access_token).
|
|||
The ``token`` must be a macaroon.
|
||||
|
||||
OAuth2-based
|
||||
~~~~~~~~~~~~
|
||||
++++++++++++
|
||||
:Type:
|
||||
``m.login.oauth2``
|
||||
:Description:
|
||||
|
@ -291,7 +291,7 @@ the OAuth flow has completed, the client retries the request with the session
|
|||
only, as above.
|
||||
|
||||
Email-based (identity server)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
+++++++++++++++++++++++++++++
|
||||
:Type:
|
||||
``m.login.email.identity``
|
||||
:Description:
|
||||
|
@ -316,7 +316,7 @@ To respond to this type, reply with an auth dict as follows::
|
|||
}
|
||||
|
||||
Dummy Auth
|
||||
~~~~~~~~~~
|
||||
++++++++++
|
||||
:Type:
|
||||
``m.login.dummy``
|
||||
:Description:
|
||||
|
@ -333,7 +333,7 @@ if provided::
|
|||
|
||||
|
||||
Fallback
|
||||
~~~~~~~~
|
||||
++++++++
|
||||
Clients cannot be expected to be able to know how to process every single login
|
||||
type. If a client does not know how to handle a given login type, it can direct
|
||||
the user to a web browser with the URL of a fallback page which will allow the
|
||||
|
@ -349,16 +349,169 @@ This MUST return an HTML page which can perform this authentication stage. This
|
|||
page must attempt to call the JavaScript function ``window.onAuthDone`` when
|
||||
the authentication has been completed.
|
||||
|
||||
Registration
|
||||
~~~~~~~~~~~~
|
||||
This section refers to API Version 2. These API calls currently use the prefix
|
||||
``/_matrix/client/v2_alpha``.
|
||||
|
||||
Registering for a user account is done using the request::
|
||||
|
||||
POST $V2PREFIX/register
|
||||
|
||||
This API endpoint uses the `User-Interactive Authentication API`_.
|
||||
This API endpoint does not require an access token.
|
||||
|
||||
.. _User-Interactive Authentication API: `sect:auth-api`_
|
||||
|
||||
The body of the POST request is a JSON object containing:
|
||||
|
||||
username
|
||||
Optional. This is the local part of the desired Matrix ID. If omitted, the
|
||||
Home Server must generate a Matrix ID local part.
|
||||
password
|
||||
Required. The desired password for the account.
|
||||
bind_email
|
||||
Optional. If ``true``, the server binds the email used for authentication to
|
||||
the Matrix ID with the ID Server.
|
||||
|
||||
On success, this returns a JSON object with keys:
|
||||
|
||||
user_id
|
||||
The fully-qualified Matrix ID that has been registered.
|
||||
access_token
|
||||
An access token for the new account.
|
||||
home_server
|
||||
The hostname of the Home Server on which the account has been registered.
|
||||
refresh_token
|
||||
A token that may be exchanged for a new ``access_token`` using the
|
||||
``/tokenrefresh`` API endpoint.
|
||||
|
||||
This endpoint may also return the following error codes:
|
||||
|
||||
M_USER_IN_USE
|
||||
If the Matrix ID is already in use
|
||||
M_EXCLUSIVE
|
||||
If the requested Matrix ID is in the exclusive namespace of an application
|
||||
service.
|
||||
|
||||
Home Servers MUST perform the relevant checks and return these codes before
|
||||
performing `User-Interactive Authentication`_, although they may also return
|
||||
them after authentication is completed if, for example, the requested user ID
|
||||
was registered whilst the client was performing authentication.
|
||||
|
||||
.. _User-Interactive Authentication: `sect:auth-api`_
|
||||
|
||||
Old V1 API docs: |register|_
|
||||
|
||||
{{login_http_api}}
|
||||
|
||||
Changing Password
|
||||
+++++++++++++++++
|
||||
This section refers to API Version 2. These API calls currently use the prefix
|
||||
``/_matrix/client/v2_alpha``.
|
||||
|
||||
Request::
|
||||
|
||||
POST $V2PREFIX/account/password
|
||||
|
||||
This API endpoint uses the User-Interactive Authentication API. An access token
|
||||
should be submitted to this endpoint if the client has an active session. The
|
||||
Home Server may change the flows available depending on whether a valid access
|
||||
token is provided.
|
||||
|
||||
The body of the POST request is a JSON object containing:
|
||||
|
||||
new_password
|
||||
The new password for the account.
|
||||
|
||||
On success, an empty JSON object is returned.
|
||||
|
||||
The error code M_NOT_FOUND is returned if the user authenticated with a third
|
||||
party identifier but the Home Server could not find a matching account in its
|
||||
database.
|
||||
|
||||
Adding Account Administrative Contact Information
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
This section refers to API Version 2. These API calls currently use the prefix
|
||||
``/_matrix/client/v2_alpha``.
|
||||
|
||||
Request::
|
||||
|
||||
POST $V2PREFIX/account/3pid
|
||||
|
||||
Used to add contact information to the user's account.
|
||||
|
||||
The body of the POST request is a JSON object containing:
|
||||
|
||||
threePidCreds
|
||||
An object containing contact information.
|
||||
bind
|
||||
Optional. A boolean indicating whether the Home Server should also bind this
|
||||
third party identifier to the account's matrix ID with the Identity Server. If
|
||||
supplied and true, the Home Server must bind the 3pid accordingly.
|
||||
|
||||
The contact information object comprises:
|
||||
|
||||
id_server
|
||||
The colon-separated hostname and port of the Identity Server used to
|
||||
authenticate the third party identifier. If the port is the default, it and the
|
||||
colon should be omitted.
|
||||
sid
|
||||
The session ID given by the Identity Server
|
||||
client_secret
|
||||
The client secret used in the session with the Identity Server.
|
||||
|
||||
On success, the empty JSON object is returned.
|
||||
|
||||
May also return error codes:
|
||||
|
||||
M_THREEPID_AUTH_FAILED
|
||||
If the credentials provided could not be verified with the ID Server.
|
||||
|
||||
Fetching Currently Associated Contact Information
|
||||
+++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
This section refers to API Version 2. These API calls currently use the prefix
|
||||
``/_matrix/client/v2_alpha``.
|
||||
|
||||
Request::
|
||||
|
||||
GET $V2PREFIX/account/3pid
|
||||
|
||||
This returns a list of third party identifiers that the Home Server has
|
||||
associated with the user's account. This is *not* the same as the list of third
|
||||
party identifiers bound to the user's Matrix ID in Identity Servers. Identifiers
|
||||
in this list may be used by the Home Server as, for example, identifiers that it
|
||||
will accept to reset the user's account password.
|
||||
|
||||
Returns a JSON object with the key ``threepids`` whose contents is an array of
|
||||
objects with the following keys:
|
||||
|
||||
medium
|
||||
The medium of the 3pid (eg, ``email``)
|
||||
address
|
||||
The textual address of the 3pid, eg. the email address
|
||||
|
||||
Pagination
|
||||
----------
|
||||
|
||||
Querying large datasets in Matrix always uses the same pagination API pattern to
|
||||
.. NOTE::
|
||||
The paths referred to in this section are not actual endpoints. They only
|
||||
serve as examples to explain how pagination functions.
|
||||
|
||||
Pagination is the process of dividing a dataset into multiple discrete pages.
|
||||
Matrix makes use of pagination to allow clients to view extremely large datasets.
|
||||
These datasets are not limited to events in a room (for example clients may want
|
||||
to paginate a list of rooms in addition to events within those rooms). Regardless
|
||||
of *what* is being paginated, there is a common underlying API which is used to
|
||||
to give clients a consistent way of selecting subsets of a potentially changing
|
||||
dataset. Requests pass in ``from``, ``to`` and ``limit`` parameters which describe
|
||||
where to read from the stream. ``from`` and ``to`` are opaque textual 'stream
|
||||
tokens' which describe positions in the dataset. The response returns new
|
||||
``start`` and ``end`` stream token values which can then be passed to subsequent
|
||||
requests to continue pagination.
|
||||
dataset. Requests pass in ``from``, ``to``, ``dir`` and ``limit`` parameters
|
||||
which describe where to read from the stream. ``from`` and ``to`` are opaque
|
||||
textual 'stream tokens' which describe the current position in the dataset.
|
||||
The ``dir`` parameter is an enum representing the direction of events to return:
|
||||
either ``f`` orwards or ``b`` ackwards. The response returns new ``start`` and
|
||||
``end`` stream token values which can then be passed to subsequent requests to
|
||||
continue pagination. Not all endpoints will make use of all the parameters
|
||||
outlined here: see the specific endpoint in question for more information.
|
||||
|
||||
Pagination Request Query Parameters
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -373,24 +526,26 @@ Query parameters:
|
|||
limit:
|
||||
integer - An integer representing the maximum number of items to
|
||||
return.
|
||||
dir:
|
||||
f|b - The direction to return events in. Typically this is ``b`` to paginate
|
||||
backwards in time.
|
||||
|
||||
'START' and 'END' are placeholder values used in these examples to describe the
|
||||
start and end of the dataset respectively.
|
||||
|
||||
Unless specified, the default pagination parameters are from=START, to=END,
|
||||
without a limit set. This allows you to hit an API like
|
||||
/events without any query parameters to get everything.
|
||||
Unless specified, the default pagination parameters are ``from=START``,
|
||||
``to=END``, without a limit set.
|
||||
|
||||
For example, the event stream has events E1 -> E15. The client wants the last 5
|
||||
For example, if an endpoint had events E1 -> E15. The client wants the last 5
|
||||
events and doesn't know any previous events::
|
||||
|
||||
S E
|
||||
|-E1-E2-E3-E4-E5-E6-E7-E8-E9-E10-E11-E12-E13-E14-E15-|
|
||||
| | |
|
||||
| _____| |
|
||||
|__________________ | ___________________|
|
||||
| | |
|
||||
GET /events?to=START&limit=5&from=END
|
||||
| _____| <--backwards-- |
|
||||
|__________________ | | ________|
|
||||
| | | |
|
||||
GET /somepath?to=START&limit=5&dir=b&from=END
|
||||
Returns:
|
||||
E15,E14,E13,E12,E11
|
||||
|
||||
|
@ -407,7 +562,7 @@ now show page 3 (rooms R11 -> 15)::
|
|||
Currently |
|
||||
viewing |
|
||||
|
|
||||
GET /rooms/list?from=9&to=END&limit=5
|
||||
GET /roomslist?from=9&to=END&limit=5
|
||||
Returns: R11,R12,R13,R14,R15
|
||||
|
||||
Note that tokens are treated in an *exclusive*, not inclusive, manner. The end
|
||||
|
@ -435,9 +590,6 @@ Events
|
|||
|
||||
.. _sect:events:
|
||||
|
||||
Overview
|
||||
~~~~~~~~
|
||||
|
||||
The model of conversation history exposed by the client-server API can be
|
||||
considered as a list of events. The server 'linearises' the
|
||||
eventually-consistent event graph of events into an 'event stream' at any given
|
||||
|
@ -465,7 +617,7 @@ You can visualise the range of events being returned as::
|
|||
| |
|
||||
start: '1-2-3' end: 'a-b-c'
|
||||
|
||||
Now, to receive future events in real-time on the eventstream, you simply GET
|
||||
Now, to receive future events in real-time on the event stream, you simply GET
|
||||
$PREFIX/events with a ``from`` parameter of 'a-b-c': in other words passing in the
|
||||
``end`` token returned by initial sync. The request blocks until new events are
|
||||
available or until your specified timeout elapses, and then returns a
|
||||
|
@ -495,34 +647,36 @@ To continue paginating backwards, one calls the /messages API again, supplying
|
|||
the new ``start`` value as the ``from`` parameter.
|
||||
|
||||
|
||||
Receiving live updates on a client
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Syncing
|
||||
~~~~~~~
|
||||
|
||||
Clients receive new events by long-polling the home server via the
|
||||
$PREFIX/events API, specifying a timeout in milliseconds in the timeout
|
||||
parameter. This will hold open the HTTP connection for a short period of time
|
||||
waiting for new events, returning early if an event occurs. This is called the
|
||||
`Event Stream`_. All events which are visible to the client will appear in the
|
||||
event stream. When the request returns, an ``end`` token is included in the
|
||||
Clients receive new events by "long-polling" the home server via the events API.
|
||||
This involves specifying a timeout in the request which will hold
|
||||
open the HTTP connection for a short period of time waiting for new events,
|
||||
returning early if an event occurs. Only the events API supports long-polling.
|
||||
All events which are visible to the client will appear in the
|
||||
events API. When the request returns, an ``end`` token is included in the
|
||||
response. This token can be used in the next request to continue where the
|
||||
last request left off.
|
||||
last request left off. Multiple events can be returned per long-poll.
|
||||
|
||||
All events must be de-duplicated based on their event ID.
|
||||
|
||||
.. TODO
|
||||
is deduplication actually a hard requirement in CS v2?
|
||||
.. Warning::
|
||||
Events are ordered in this API according to the arrival time of the event on
|
||||
the homeserver. This can conflict with other APIs which order events based on
|
||||
their partial ordering in the event graph. This can result in duplicate events
|
||||
being received (once per distinct API called). Clients SHOULD de-duplicate
|
||||
events based on the event ID when this happens.
|
||||
|
||||
.. TODO-spec
|
||||
Do we ever return multiple events in a single request?
|
||||
Don't we get lots of request setup RTT latency if we only do one event per request?
|
||||
Do we ever support streaming requests? Why not websockets?
|
||||
|
||||
When the client first logs in, they will need to initially synchronise with
|
||||
their home server. This is achieved via the |initialSync|_ API. This API also
|
||||
returns an ``end`` token which can be used with the event stream. See the 'Room Sync' section below.
|
||||
their home server. This is achieved via the initial sync API described below.
|
||||
This API also returns an ``end`` token which can be used with the event stream.
|
||||
|
||||
Events in a room
|
||||
~~~~~~~~~~~~~~~~
|
||||
{{sync_http_api}}
|
||||
|
||||
Types of room events
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Room events are split into two categories:
|
||||
|
||||
|
@ -534,7 +688,7 @@ Room events are split into two categories:
|
|||
:Message events:
|
||||
These are events which describe transient "once-off" activity in a room:
|
||||
typically communication such as sending an instant message or setting up a
|
||||
VoIP call. These used to be called 'non-state' events.
|
||||
VoIP call.
|
||||
|
||||
This specification outlines several events, all with the event type prefix
|
||||
``m.``. However, applications may wish to add their own type of event, and this
|
||||
|
@ -544,7 +698,7 @@ convention, e.g. ``com.example.myapp.event``. This ensures event types are
|
|||
suitably namespaced for each application and reduces the risk of clashes.
|
||||
|
||||
State events
|
||||
~~~~~~~~~~~~
|
||||
++++++++++++
|
||||
|
||||
State events can be sent by ``PUT`` ing to
|
||||
|/rooms/<room_id>/state/<event_type>/<state_key>|_. These events will be
|
||||
|
@ -587,7 +741,7 @@ In some cases, there may be no need for a ``state_key``, so it can be omitted::
|
|||
See `Room Events`_ for the ``m.`` event specification.
|
||||
|
||||
Message events
|
||||
~~~~~~~~~~~~~~
|
||||
++++++++++++++
|
||||
|
||||
Message events can be sent by sending a request to
|
||||
|/rooms/<room_id>/send/<event_type>|_. These requests *can* use transaction
|
||||
|
@ -603,69 +757,6 @@ example::
|
|||
|
||||
See `Room Events`_ for the ``m.`` event specification.
|
||||
|
||||
Syncing rooms
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
.. NOTE::
|
||||
This section is a work in progress.
|
||||
|
||||
When a client logs in, they may have a list of rooms which they have already
|
||||
joined. These rooms may also have a list of events associated with them. The
|
||||
purpose of 'syncing' is to present the current room and event information in a
|
||||
convenient, compact manner. The events returned are not limited to room events;
|
||||
presence events will also be returned. A single syncing API is provided:
|
||||
|
||||
- |initialSync|_ : A global sync which will present room and event information
|
||||
for all rooms the user has joined.
|
||||
|
||||
.. TODO-spec room-scoped initial sync
|
||||
- |/rooms/<room_id>/initialSync|_ : A sync scoped to a single room. Presents
|
||||
room and event information for this room only.
|
||||
- Room-scoped initial sync is Very Tricky because typically people would
|
||||
want to sync the room then listen for any new content from that point
|
||||
onwards. The event stream cannot do this for a single room currently.
|
||||
As a result, commenting room-scoped initial sync at this time.
|
||||
|
||||
The |initialSync|_ API contains the following keys:
|
||||
|
||||
``presence``
|
||||
Description:
|
||||
Contains a list of presence information for users the client is interested
|
||||
in.
|
||||
Format:
|
||||
A JSON array of ``m.presence`` events.
|
||||
|
||||
``end``
|
||||
Description:
|
||||
Contains an event stream token which can be used with the `Event Stream`_.
|
||||
Format:
|
||||
A string containing the event stream token.
|
||||
|
||||
``rooms``
|
||||
Description:
|
||||
Contains a list of room information for all rooms the client has joined,
|
||||
and limited room information on rooms the client has been invited to.
|
||||
Format:
|
||||
A JSON array containing Room Information JSON objects.
|
||||
|
||||
Room Information:
|
||||
Description:
|
||||
Contains all state events for the room, along with a limited amount of
|
||||
the most recent events, configured via the ``limit`` query
|
||||
parameter. Also contains additional keys with room metadata, such as the
|
||||
``room_id`` and the client's ``membership`` to the room.
|
||||
Format:
|
||||
A JSON object with the following keys:
|
||||
``room_id``
|
||||
A string containing the ID of the room being described.
|
||||
``membership``
|
||||
A string representing the client's membership status in this room.
|
||||
``messages``
|
||||
An event stream JSON object containing a ``chunk`` of recent
|
||||
events (both state events and non-state events), along with an ``end`` token.
|
||||
``state``
|
||||
A JSON array containing all the current state events for this room.
|
||||
|
||||
Getting events for a room
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -673,6 +764,9 @@ There are several APIs provided to ``GET`` events for a room:
|
|||
|
||||
{{rooms_http_api}}
|
||||
|
||||
|
||||
{{message_pagination_http_api}}
|
||||
|
||||
Redactions
|
||||
~~~~~~~~~~
|
||||
Since events are extensible it is possible for malicious users and/or servers
|
||||
|
@ -723,140 +817,20 @@ Rooms
|
|||
|
||||
Creation
|
||||
~~~~~~~~
|
||||
To create a room, a client has to use the |createRoom|_ API. There are various
|
||||
options which can be set when creating a room:
|
||||
|
||||
``visibility``
|
||||
Type:
|
||||
String
|
||||
Optional:
|
||||
Yes
|
||||
Value:
|
||||
Either ``public`` or ``private``.
|
||||
Description:
|
||||
A ``public`` visibility indicates that the room will be shown in the public
|
||||
room list. A ``private`` visibility will hide the room from the public room
|
||||
list. Rooms default to ``private`` visibility if this key is not included.
|
||||
|
||||
``room_alias_name``
|
||||
Type:
|
||||
String
|
||||
Optional:
|
||||
Yes
|
||||
Value:
|
||||
The room alias localpart.
|
||||
Description:
|
||||
If this is included, a room alias will be created and mapped to the newly
|
||||
created room. The alias will belong on the same home server which created
|
||||
the room, e.g. ``!qadnasoi:domain.com >>> #room_alias_name:domain.com``
|
||||
|
||||
``name``
|
||||
Type:
|
||||
String
|
||||
Optional:
|
||||
Yes
|
||||
Value:
|
||||
The ``name`` value for the ``m.room.name`` state event.
|
||||
Description:
|
||||
If this is included, an ``m.room.name`` event will be sent into the room to
|
||||
indicate the name of the room. See `Room Events`_ for more information on
|
||||
``m.room.name``.
|
||||
|
||||
``topic``
|
||||
Type:
|
||||
String
|
||||
Optional:
|
||||
Yes
|
||||
Value:
|
||||
The ``topic`` value for the ``m.room.topic`` state event.
|
||||
Description:
|
||||
If this is included, an ``m.room.topic`` event will be sent into the room
|
||||
to indicate the topic for the room. See `Room Events`_ for more information
|
||||
on ``m.room.topic``.
|
||||
|
||||
``invite``
|
||||
Type:
|
||||
List
|
||||
Optional:
|
||||
Yes
|
||||
Value:
|
||||
A list of user ids to invite.
|
||||
Description:
|
||||
This will tell the server to invite everyone in the list to the newly
|
||||
created room.
|
||||
|
||||
``creation_content``
|
||||
Type:
|
||||
Object
|
||||
Optional:
|
||||
Yes
|
||||
Value:
|
||||
Extra keys to be added to the content of the ``m.room.create``. The server
|
||||
will clober the following keys: ``creator``. Future versions of this
|
||||
spec may allow the server to clobber other keys if required.
|
||||
Description:
|
||||
Allows clients to add keys to the content of ``m.room.create``.
|
||||
|
||||
``preset``
|
||||
Type:
|
||||
String
|
||||
Optional:
|
||||
Yes
|
||||
Value:
|
||||
``private_chat``, ``trusted_private_chat`` or ``public_chat``
|
||||
Description:
|
||||
Convenience parameter for setting various default state events based on a
|
||||
preset.
|
||||
|
||||
Three presets are defined:
|
||||
|
||||
- ``private_chat``: Sets the ``join_rules`` to ``invite`` and
|
||||
``history_visibility`` to ``shared``
|
||||
- ``trusted_private_chat``: Set the ``join_rules`` to ``invite``,
|
||||
``history_visibility`` to ``shared`` and gives all invitees the same
|
||||
power level as the creator.
|
||||
- ``public_chat``: Sets the ``join_rules`` to ``public`` and
|
||||
``history_visibility`` to ``shared``
|
||||
|
||||
``initial_state``
|
||||
Type:
|
||||
List
|
||||
Optional:
|
||||
Yes
|
||||
Value:
|
||||
A list of state events to set in the new room.
|
||||
Description:
|
||||
Allows the user to override the default state events set in the new room.
|
||||
|
||||
The expected format of the state events are an object with ``type``,
|
||||
``state_key`` and ``content`` keys set.
|
||||
|
||||
Takes precedence over events set by ``presets``, but gets overriden by
|
||||
``name`` and ``topic`` keys.
|
||||
|
||||
Example::
|
||||
|
||||
{
|
||||
"preset": "public_chat",
|
||||
"room_alias_name": "thepub",
|
||||
"name": "The Grand Duke Pub",
|
||||
"topic": "All about happy hour",
|
||||
"creation_content": {
|
||||
"m.federate": false
|
||||
}
|
||||
}
|
||||
|
||||
The home server will create a ``m.room.create`` event when the room is created,
|
||||
which serves as the root of the PDU graph for this room. This event also has a
|
||||
The home server will create an ``m.room.create`` event when a room is created,
|
||||
which serves as the root of the event graph for this room. This event also has a
|
||||
``creator`` key which contains the user ID of the room creator. It will also
|
||||
generate several other events in order to manage permissions in this room. This
|
||||
includes:
|
||||
|
||||
- ``m.room.power_levels`` : Sets the power levels of users and required power
|
||||
levels.
|
||||
levels for various actions within the room such as sending events.
|
||||
- ``m.room.join_rules`` : Whether the room is "invite-only" or not.
|
||||
|
||||
See `Room Events`_ for more information on these events.
|
||||
See `Room Events`_ for more information on these events. To create a room, a
|
||||
client has to use the the following API.
|
||||
|
||||
{{create_room_http_api}}
|
||||
|
||||
Room aliases
|
||||
~~~~~~~~~~~~
|
||||
|
@ -921,7 +895,7 @@ certain operations such as kicking, banning and sending state events. See
|
|||
`m.room.power_levels`_ for more information.
|
||||
|
||||
Joining rooms
|
||||
-------------
|
||||
~~~~~~~~~~~~~
|
||||
Users need to be a member of a room in order to send and receive events in that
|
||||
room. There are several states in which a user may be, in relation to a room:
|
||||
|
||||
|
@ -931,6 +905,11 @@ room. There are several states in which a user may be, in relation to a room:
|
|||
- Joined (the user can send and receive events in the room)
|
||||
- Banned (the user is not allowed to join the room)
|
||||
|
||||
There is an exception to the requirement that a user join a room before sending
|
||||
events to it: users may send an ``m.room.member`` event to a room with
|
||||
``content.membership`` set to ``leave`` to reject an invitation if they have
|
||||
currently been invited to a room but have not joined it.
|
||||
|
||||
Some rooms require that users be invited to it before they can join; others
|
||||
allow anyone to join. Whether a given room is an "invite-only" room is
|
||||
determined by the room config key ``m.room.join_rules``. It can have one of the
|
||||
|
@ -957,8 +936,11 @@ Leaving rooms
|
|||
|
||||
|
||||
A user can leave a room to stop receiving events for that room. A user must
|
||||
have joined the room before they are eligible to leave the room. If the room is
|
||||
an "invite-only" room, they will need to be re-invited before they can re-join
|
||||
have been invited to or have joined the room before they are eligible to leave
|
||||
the room. Leaving a room to which the user has been invited rejects the invite.
|
||||
|
||||
Whether or not they actually joined the room, if the room is
|
||||
an "invite-only" room they will need to be re-invited before they can re-join
|
||||
the room. To leave a room, a request should be made to
|
||||
|/rooms/<room_id>/leave|_ with::
|
||||
|
||||
|
@ -1000,53 +982,17 @@ member's state, by making a request to
|
|||
"membership": "ban"
|
||||
}
|
||||
|
||||
Account operations
|
||||
------------------
|
||||
|
||||
Registration
|
||||
------------
|
||||
This section refers to API Version 2. These API calls currently use the prefix
|
||||
``/_matrix/client/v2_alpha``.
|
||||
~~~~~~~~~~~~
|
||||
This API endpoint uses the `User-Interactive Authentication API`_.
|
||||
|
||||
Registering for a user account is done using the request::
|
||||
{{v2_registration_http_api}}
|
||||
|
||||
POST $V2PREFIX/register
|
||||
|
||||
This API endpoint uses the User-Interactive Authentication API.
|
||||
This API endpoint does not require an access token.
|
||||
|
||||
The body of the POST request is a JSON object containing:
|
||||
|
||||
username
|
||||
Optional. This is the local part of the desired Matrix ID. If omitted, the
|
||||
Home Server must generate a Matrix ID local part.
|
||||
password
|
||||
Required. The desired password for the account.
|
||||
bind_email
|
||||
Optional. If ``true``, the server binds the email used for authentication to
|
||||
the Matrix ID with the ID Server.
|
||||
|
||||
On success, this returns a JSON object with keys:
|
||||
|
||||
user_id
|
||||
The fully-qualified Matrix ID that has been registered.
|
||||
access_token
|
||||
An access token for the new account.
|
||||
home_server
|
||||
The hostname of the Home Server on which the account has been registered.
|
||||
|
||||
This endpoint may also return the following error codes:
|
||||
|
||||
M_USER_IN_USE
|
||||
If the Matrix ID is already in use
|
||||
M_EXCLUSIVE
|
||||
If the requested Matrix ID is in the exclusive namespace of an application
|
||||
service.
|
||||
|
||||
Home Servers MUST perform the relevant checks and return these codes before
|
||||
performing User-Interactive Authentication, although they may also return
|
||||
them after authentication is completed if, for example, the requested user ID
|
||||
was registered whilst the client was performing authentication.
|
||||
|
||||
Old V1 API docs: |register|_
|
||||
Login
|
||||
~~~~~
|
||||
|
||||
{{login_http_api}}
|
||||
|
|
@ -190,9 +190,64 @@ in the event JSON in a ``hash`` object under a ``sha256`` key.
|
|||
event_json_object["unsigned"] = unsigned
|
||||
return event_json_object
|
||||
|
||||
Then all non-essential keys are stripped from the event object, and the
|
||||
resulting object which included the ``hash`` key is signed using the JSON
|
||||
signing algorithm
|
||||
The event is then stripped of all non-essential keys both at the top level and
|
||||
within the ``content`` object. Any top-level keys not in the following list
|
||||
MUST be removed:
|
||||
|
||||
.. code::
|
||||
|
||||
auth_events
|
||||
depth
|
||||
event_id
|
||||
hashes
|
||||
membership
|
||||
origin
|
||||
origin_server_ts
|
||||
prev_events
|
||||
prev_state
|
||||
room_id
|
||||
sender
|
||||
signatures
|
||||
state_key
|
||||
type
|
||||
|
||||
A new ``content`` object is constructed for the resulting event that contains
|
||||
only the essential keys of the original ``content`` object. If the original
|
||||
event lacked a ``content`` object at all, a new empty JSON object is created
|
||||
for it.
|
||||
|
||||
The keys that are considered essential for the ``content`` object depend on the
|
||||
the ``type`` of the event. These are:
|
||||
|
||||
.. code::
|
||||
|
||||
type is "m.room.aliases":
|
||||
aliases
|
||||
|
||||
type is "m.room.create":
|
||||
creator
|
||||
|
||||
type is "m.room.history_visibility":
|
||||
history_visibility
|
||||
|
||||
type is "m.room.join_rules":
|
||||
join_rule
|
||||
|
||||
type is "m.room.member":
|
||||
membership
|
||||
|
||||
type is "m.room.power_levels":
|
||||
ban
|
||||
events
|
||||
events_default
|
||||
kick
|
||||
redact
|
||||
state_default
|
||||
users
|
||||
users_default
|
||||
|
||||
The resulting stripped object with the new ``content`` object and the original
|
||||
``hashes`` key is then signed using the JSON signing algorithm outlined below:
|
||||
|
||||
.. code:: python
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
Events
|
||||
======
|
||||
Event Structure
|
||||
===============
|
||||
|
||||
All communication in Matrix is expressed in the form of data objects called
|
||||
Events. These are the fundamental building blocks common to the client-server,
|
|
@ -1,7 +1,7 @@
|
|||
Feature Profiles
|
||||
================
|
||||
|
||||
.. sect:feature-profiles:
|
||||
.. _sect:feature-profiles:
|
||||
|
||||
Matrix supports many different kinds of clients: from embedded IoT devices to
|
||||
desktop clients. Not all clients can provide the same feature sets as other
|
|
@ -99,23 +99,23 @@ Architecture
|
|||
------------
|
||||
|
||||
Matrix defines APIs for synchronising extensible JSON objects known as
|
||||
``events`` between compatible clients, servers and services. Clients are
|
||||
"events" between compatible clients, servers and services. Clients are
|
||||
typically messaging/VoIP applications or IoT devices/hubs and communicate by
|
||||
synchronising communication history with their ``homeserver`` using the
|
||||
``Client-Server API``. Each homeserver stores the communication history and
|
||||
synchronising communication history with their "homeserver" using the
|
||||
"Client-Server API". Each homeserver stores the communication history and
|
||||
account information for all of its clients, and shares data with the wider
|
||||
Matrix ecosystem by synchronising communication history with other homeservers
|
||||
and their clients.
|
||||
|
||||
Clients typically communicate with each other by emitting events in the
|
||||
context of a virtual ``room``. Room data is replicated across *all of the
|
||||
context of a virtual "room". Room data is replicated across *all of the
|
||||
homeservers* whose users are participating in a given room. As such, *no
|
||||
single homeserver has control or ownership over a given room*. Homeservers
|
||||
model communication history as a partially ordered graph of events known as
|
||||
the room's ``event graph``, which is synchronised with eventual consistency
|
||||
between the participating servers using the ``Server-Server API``. This process
|
||||
the room's "event graph", which is synchronised with eventual consistency
|
||||
between the participating servers using the "Server-Server API". This process
|
||||
of synchronising shared conversation history between homeservers run by
|
||||
different parties is called ``Federation``. Matrix optimises for the the
|
||||
different parties is called "Federation". Matrix optimises for the the
|
||||
Availability and Partitioned properties of CAP theorem at
|
||||
the expense of Consistency.
|
||||
|
||||
|
@ -151,13 +151,13 @@ Users
|
|||
~~~~~
|
||||
|
||||
Each client is associated with a user account, which is identified in Matrix
|
||||
using a unique "User ID". This ID is namespaced to the home server which
|
||||
using a unique "User ID". This ID is namespaced to the homeserver which
|
||||
allocated the account and has the form::
|
||||
|
||||
@localpart:domain
|
||||
|
||||
The ``localpart`` of a user ID may be a user name, or an opaque ID identifying
|
||||
this user. They are case-insensitive.
|
||||
this user. The ``domain`` of a user ID is the domain of the homeserver.
|
||||
|
||||
.. TODO-spec
|
||||
- Need to specify precise grammar for Matrix IDs
|
||||
|
@ -183,9 +183,9 @@ Event Graphs
|
|||
.. _sect:event-graph:
|
||||
|
||||
Events exchanged in the context of a room are stored in a directed acyclic graph
|
||||
(DAG) called an ``event graph``. The partial ordering of this graph gives the
|
||||
(DAG) called an "event graph". The partial ordering of this graph gives the
|
||||
chronological ordering of events within the room. Each event in the graph has a
|
||||
list of zero or more ``parent`` events, which refer to any preceding events
|
||||
list of zero or more "parent" events, which refer to any preceding events
|
||||
which have no chronological successor from the perspective of the homeserver
|
||||
which created the event.
|
||||
|
||||
|
@ -292,11 +292,12 @@ Each room can also have multiple "Room Aliases", which look like::
|
|||
|
||||
A room alias "points" to a room ID and is the human-readable label by which
|
||||
rooms are publicised and discovered. The room ID the alias is pointing to can
|
||||
be obtained by visiting the domain specified. They are case-insensitive. Note
|
||||
that the mapping from a room alias to a room ID is not fixed, and may change
|
||||
over time to point to a different room ID. For this reason, Clients SHOULD
|
||||
resolve the room alias to a room ID once and then use that ID on subsequent
|
||||
requests. Room aliases MUST NOT exceed 255 bytes (including the domain).
|
||||
be obtained by visiting the domain specified. Note that the mapping from a room
|
||||
alias to a room ID is not fixed, and may change over time to point to a
|
||||
different room ID. For this reason, Clients SHOULD resolve the room alias to a
|
||||
room ID once and then use that ID on subsequent requests. Room aliases MUST NOT
|
||||
exceed 255 bytes (including the domain).
|
||||
|
||||
|
||||
When resolving a room alias the server will also respond with a list of servers
|
||||
that are in the room that can be used to join via.
|
||||
|
@ -339,12 +340,9 @@ Profiles
|
|||
~~~~~~~~
|
||||
|
||||
Users may publish arbitrary key/value data associated with their account - such
|
||||
as a human readable ``display name``, a profile photo URL, contact information
|
||||
as a human readable display name, a profile photo URL, contact information
|
||||
(email address, phone numbers, website URLs etc).
|
||||
|
||||
In Client-Server API v2, profile data is typed using namespaced keys for
|
||||
interoperability, much like events - e.g. ``m.profile.display_name``.
|
||||
|
||||
.. TODO
|
||||
Actually specify the different types of data - e.g. what format are display
|
||||
names allowed to be?
|
||||
|
@ -431,15 +429,12 @@ Some requests have unique error codes:
|
|||
:``M_BAD_PAGINATION``:
|
||||
Encountered when specifying bad pagination query parameters.
|
||||
|
||||
:``M_LOGIN_EMAIL_URL_NOT_YET``:
|
||||
Encountered when polling for an email link which has not been clicked yet.
|
||||
|
||||
.. _sect:txn_ids:
|
||||
|
||||
The C-S API typically uses ``HTTP POST`` to submit requests. This means these
|
||||
requests are not idempotent. The C-S API also allows ``HTTP PUT`` to make
|
||||
requests idempotent. In order to use a ``PUT``, paths should be suffixed with
|
||||
``/{txnId}``. ``{txnId}`` is a unique client-generated transaction ID which
|
||||
The Client-Server API typically uses ``HTTP POST`` to submit requests. This
|
||||
means these requests are not idempotent. The C-S API also allows ``HTTP PUT`` to
|
||||
make requests idempotent. In order to use a ``PUT``, paths should be suffixed
|
||||
with ``/{txnId}``. ``{txnId}`` is a unique client-generated transaction ID which
|
||||
identifies the request, and is scoped to a given Client (identified by that
|
||||
client's ``access_token``). Crucially, it **only** serves to identify new
|
||||
requests from retransmits. After the request has finished, the ``{txnId}``
|
|
@ -30,6 +30,8 @@ Usage of this event is discouraged for several reasons:
|
|||
|
||||
{{m_room_topic_event}}
|
||||
|
||||
{{m_room_avatar_event}}
|
||||
|
||||
m.room.message msgtypes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
|
|
@ -36,7 +36,8 @@ A client asks a server to invite a user by their third party identifier.
|
|||
Server behaviour
|
||||
----------------
|
||||
|
||||
All homeservers MUST verify that sig(``token``, ``public_key``) = ``signature``.
|
||||
All homeservers MUST verify the signature in the event's
|
||||
``content.third_party_invite.signed`` object.
|
||||
|
||||
If a client of the current homeserver is joining by an
|
||||
``m.room.third_party_invite``, that homesever MUST validate that the public
|
||||
|
@ -93,11 +94,11 @@ For example:
|
|||
When the third party user validates their identity, they are told about the
|
||||
invite, and ask their homeserver, H3, to join the room.
|
||||
|
||||
H3 validates that sign(``token``, ``public_key``) = ``signature``, and may check
|
||||
``key_validity_url``.
|
||||
H3 validates the signature in the event's
|
||||
``content.third_party_invite.signed`` object.
|
||||
|
||||
H3 then asks H1 to join it to the room. H1 *must* validate that
|
||||
sign(``token``, ``public_key``) = ``signature`` *and* check ``key_validity_url``.
|
||||
H3 then asks H1 to join it to the room. H1 *must* validate the ``signed``
|
||||
property *and* check ``key_validity_url``.
|
||||
|
||||
Having validated these things, H1 writes the join event to the room, and H3
|
||||
begins participating in the room. H2 *must* accept this event.
|
||||
|
|
|
@ -630,7 +630,7 @@ because HTTP services like Matrix are often deployed behind load balancers that
|
|||
handle the TLS and these load balancers make it difficult to check TLS client
|
||||
certificates.
|
||||
|
||||
A home server may provide a TLS client certficate and the receiving home server
|
||||
A home server may provide a TLS client certificate and the receiving home server
|
||||
may check that the client certificate matches the certificate of the origin
|
||||
home server.
|
||||
|
|
@ -1,17 +1,17 @@
|
|||
targets:
|
||||
main: # arbitrary name to identify this build target
|
||||
files: # the sort order of files to cat
|
||||
- 0-intro.rst
|
||||
- 1-client_server_api.rst
|
||||
- { 1: 0-events.rst }
|
||||
- { 1: 0-event_signing.rst }
|
||||
- 2-modules.rst
|
||||
- { 1: 0-feature_profiles.rst }
|
||||
- intro.rst
|
||||
- client_server_api.rst
|
||||
- { 1: events.rst }
|
||||
- { 1: event_signing.rst }
|
||||
- modules.rst
|
||||
- { 1: feature_profiles.rst }
|
||||
- { 1: "group:modules" } # reference a group of files
|
||||
- 3-application_service_api.rst
|
||||
- 4-server_server_api.rst
|
||||
- 5-identity_servers.rst
|
||||
- 6-appendices.rst
|
||||
- application_service_api.rst
|
||||
- server_server_api.rst
|
||||
- identity_servers.rst
|
||||
- appendices.rst
|
||||
groups: # reusable blobs of files when prefixed with 'group:'
|
||||
modules:
|
||||
- modules/instant_messaging.rst
|
||||
|
|
|
@ -7,18 +7,18 @@
|
|||
{% for table in event.content_fields -%}
|
||||
{{"``"+table.title+"``" if table.title else "" }}
|
||||
|
||||
================== ================= ===========================================
|
||||
{{table.title or "Content"}} Key Type Description
|
||||
================== ================= ===========================================
|
||||
======================= ================= ===========================================
|
||||
{{table.title or "Content"}} Key Type Description
|
||||
======================= ================= ===========================================
|
||||
{% for row in table.rows -%}
|
||||
{# -#}
|
||||
{# Row type needs to prepend spaces to line up with the type column (19 ch) -#}
|
||||
{# Desc needs to prepend the required text (maybe) and prepend spaces too -#}
|
||||
{# It also needs to then wrap inside the desc col (43 ch width) -#}
|
||||
{# -#}
|
||||
{{row.key}}{{row.type|indent(19-row.key|length)}}{{row.desc|wrap(43,row.req_str | indent(18 - (row.type|length))) |indent_block(37)}}
|
||||
{{row.key}}{{row.type|indent(24-row.key|length)}}{{row.desc|wrap(43,row.req_str | indent(18 - (row.type|length))) |indent_block(42)}}
|
||||
{% endfor -%}
|
||||
================== ================= ===========================================
|
||||
======================= ================= ===========================================
|
||||
|
||||
{% endfor %}
|
||||
Example::
|
||||
|
|
|
@ -532,6 +532,15 @@ class MatrixUnits(Units):
|
|||
Units.prop(json_schema, "properties/content")
|
||||
)
|
||||
|
||||
# This is horrible because we're special casing a key on m.room.member.
|
||||
# We need to do this because we want to document a non-content object.
|
||||
if schema["type"] == "m.room.member":
|
||||
invite_room_state = get_json_schema_object_fields(
|
||||
json_schema["properties"]["invite_room_state"]["items"]
|
||||
)
|
||||
schema["content_fields"].extend(invite_room_state)
|
||||
|
||||
|
||||
# grab msgtype if it is the right kind of event
|
||||
msgtype = Units.prop(
|
||||
json_schema, "properties/content/properties/msgtype/enum"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue