Merge branch 'master' of github.com:matrix-org/matrix-doc into erikj/public_rooms
This commit is contained in:
commit
a69d6c63c6
34 changed files with 857 additions and 186 deletions
|
@ -170,7 +170,12 @@ paths:
|
|||
``public_chat``: =>
|
||||
``join_rules`` is set to ``public``.
|
||||
``history_visibility`` is set to ``shared``.
|
||||
|
||||
is_direct:
|
||||
type: boolean
|
||||
description: |-
|
||||
This flag makes the server set the ``is_direct`` flag on the
|
||||
``m.room.member`` events sent to the users in ``invite`` and
|
||||
``invite_3pid``. See `Direct Messaging`_ for more information.
|
||||
responses:
|
||||
200:
|
||||
description: Information about the newly created room.
|
||||
|
|
|
@ -28,4 +28,8 @@ properties:
|
|||
items:
|
||||
type: string
|
||||
type: array
|
||||
contains_url:
|
||||
type: boolean
|
||||
description: If ``true``, includes only events with a url key in their content. If
|
||||
``false``, excludes those events.
|
||||
type: object
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
# limitations under the License.
|
||||
accessToken:
|
||||
type: apiKey
|
||||
description: The access_token returned by a call to ``/login`` or ``/tokenrefresh``
|
||||
description: The access_token returned by a call to ``/login`` or ``/register``
|
||||
name: access_token
|
||||
in: query
|
||||
|
|
|
@ -90,15 +90,6 @@ paths:
|
|||
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
|
||||
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 homeserver on which the account has been registered.
|
||||
|
@ -123,67 +114,3 @@ paths:
|
|||
"$ref": "definitions/error.yaml"
|
||||
tags:
|
||||
- Session management
|
||||
"/tokenrefresh":
|
||||
post:
|
||||
summary: Exchanges a refresh token for an access token.
|
||||
description: |-
|
||||
Exchanges a refresh token for a new access token.
|
||||
This is intended to be used if the access token has expired.
|
||||
|
||||
The server MUST invalidate the supplied ``refresh_token`` if the
|
||||
request is successful. It MUST also invalidate the ``access_token``
|
||||
which was issued at the same time as the ``refresh_token``, if it
|
||||
has not already expired.
|
||||
security:
|
||||
- accessToken: []
|
||||
parameters:
|
||||
- in: body
|
||||
name: body
|
||||
schema:
|
||||
type: object
|
||||
example: |-
|
||||
{
|
||||
"refresh_token": "a1b2c3"
|
||||
}
|
||||
properties:
|
||||
refresh_token:
|
||||
type: string
|
||||
description: The refresh token which was issued by the server.
|
||||
required: ["refresh_token"]
|
||||
responses:
|
||||
200:
|
||||
description: |-
|
||||
The refresh token was accepted, and a new access token has been issued.
|
||||
The passed refresh token is no longer valid and cannot be used.
|
||||
A new refresh token will have been returned unless some policy does
|
||||
not allow the user to continue to renew their session.
|
||||
examples:
|
||||
application/json: |-
|
||||
{
|
||||
"access_token": "bearwithme123",
|
||||
"refresh_token": "exchangewithme987"
|
||||
}
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
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``.
|
||||
refresh_token:
|
||||
type: string
|
||||
description: Optional. A new ``refresh_token`` which may be exchanged for another new ``access_token``.
|
||||
403:
|
||||
description: |-
|
||||
The exchange attempt failed. For example, the refresh token may have already been used.
|
||||
examples:
|
||||
application/json: |-
|
||||
{"errcode": "M_FORBIDDEN"}
|
||||
429:
|
||||
description: This request was rate-limited.
|
||||
schema:
|
||||
"$ref": "definitions/error.yaml"
|
||||
tags:
|
||||
- Session management
|
||||
|
|
|
@ -75,6 +75,13 @@ paths:
|
|||
description: |-
|
||||
The maximum number of events to return. Default: 10.
|
||||
x-example: "3"
|
||||
- in: query
|
||||
type: string
|
||||
name: filter
|
||||
description: |-
|
||||
A JSON RoomEventFilter to filter returned events with.
|
||||
x-example: |-
|
||||
{"contains_url":true}
|
||||
responses:
|
||||
200:
|
||||
description: A list of messages with a new token to request more.
|
||||
|
|
142
api/client-server/notifications.yaml
Normal file
142
api/client-server/notifications.yaml
Normal file
|
@ -0,0 +1,142 @@
|
|||
# Copyright 2016 OpenMarket Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
swagger: '2.0'
|
||||
info:
|
||||
title: "Matrix Client-Server Notifications API"
|
||||
version: "1.0.0"
|
||||
host: localhost:8008
|
||||
schemes:
|
||||
- https
|
||||
- http
|
||||
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
securityDefinitions:
|
||||
$ref: definitions/security.yaml
|
||||
paths:
|
||||
"/notifications":
|
||||
get:
|
||||
summary: Gets a list of events that the user has been notified about
|
||||
description: |-
|
||||
This API is used to paginate through the list of events that the
|
||||
user has been, or would have been notified about.
|
||||
security:
|
||||
- accessToken: []
|
||||
parameters:
|
||||
- in: query
|
||||
type: string
|
||||
name: from
|
||||
description: Pagination token given to retrieve the next set of events.
|
||||
required: false
|
||||
x-example: "xxxxx"
|
||||
- in: query
|
||||
type: number
|
||||
name: limit
|
||||
description: Limit on the number of events to return in this request.
|
||||
required: false
|
||||
x-example: "20"
|
||||
- in: query
|
||||
name: only
|
||||
type: string
|
||||
description: |-
|
||||
Allows basic filtering of events returned. Supply ``highlight``
|
||||
to return only events where the notification had the highlight
|
||||
tweak set.
|
||||
required: false
|
||||
x-example: "highlight"
|
||||
responses:
|
||||
200:
|
||||
description: A batch of events is being returned
|
||||
examples:
|
||||
application/json: |-
|
||||
{
|
||||
"next_token": "abcdef",
|
||||
"notifications": [
|
||||
{
|
||||
"actions": [
|
||||
"notify"
|
||||
],
|
||||
"profile_tag": "hcbvkzxhcvb",
|
||||
"read": true,
|
||||
"room_id": "!abcdefg:example.com",
|
||||
"ts": 1475508881945,
|
||||
"event": {
|
||||
"sender": "@alice:example.com",
|
||||
"type": "m.room.message",
|
||||
"age": 124524,
|
||||
"txn_id": "1234",
|
||||
"content": {
|
||||
"body": "I am a fish",
|
||||
"msgtype": "m.text"
|
||||
},
|
||||
"origin_server_ts": 1417731086797,
|
||||
"event_id": "$74686972643033:example.com"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
schema:
|
||||
type: object
|
||||
required: ["notifications"]
|
||||
properties:
|
||||
next_token:
|
||||
type: string
|
||||
description: |-
|
||||
The token to supply in the ``from`` param of the next
|
||||
``/notifications`` request in order to request more
|
||||
events. If this is absent, there are no more results.
|
||||
notifications:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required: ["actions", "event", "read", "room_id", "ts"]
|
||||
title: Notification
|
||||
properties:
|
||||
actions:
|
||||
type: array
|
||||
description: |-
|
||||
The action(s) to perform when the conditions for this rule are met.
|
||||
See `Push Rules: API`_.
|
||||
items:
|
||||
type:
|
||||
- object
|
||||
- string
|
||||
event:
|
||||
type: object
|
||||
title: Event
|
||||
description: The Event object for the event that triggered the notification.
|
||||
allOf:
|
||||
- "$ref": "definitions/event.yaml"
|
||||
profile_tag:
|
||||
type: string
|
||||
description: The profile tag of the rule that matched this event.
|
||||
read:
|
||||
type: boolean
|
||||
description: |-
|
||||
Indicates whether the user has sent a read receipt indicating
|
||||
that they have read this message.
|
||||
room_id:
|
||||
type: string
|
||||
description: The ID of the room in which the event was posted.
|
||||
ts:
|
||||
type: integer
|
||||
description: |-
|
||||
The unix timestamp at which the event notification was sent,
|
||||
in milliseconds.
|
||||
description: The list of events that triggered notifications.
|
||||
tags:
|
||||
- Push notifications
|
|
@ -39,6 +39,9 @@ paths:
|
|||
|
||||
- `guest` accounts. These accounts may have limited permissions and may not be supported by all servers.
|
||||
|
||||
If registration is successful, this endpoint will issue an access token
|
||||
the client can use to authorize itself in subsequent requests.
|
||||
|
||||
parameters:
|
||||
- in: query
|
||||
name: kind
|
||||
|
@ -90,8 +93,7 @@ paths:
|
|||
{
|
||||
"user_id": "@cheeky_monkey:matrix.org",
|
||||
"access_token": "abc123",
|
||||
"home_server": "matrix.org",
|
||||
"refresh_token": "def456"
|
||||
"home_server": "matrix.org"
|
||||
}
|
||||
schema:
|
||||
type: object
|
||||
|
@ -104,16 +106,6 @@ paths:
|
|||
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 homeserver on which the account has been registered.
|
||||
|
|
|
@ -246,7 +246,7 @@ paths:
|
|||
200:
|
||||
description: |-
|
||||
A list of members of the room. If you are joined to the room then
|
||||
this will be the current members of the room. If you have left te
|
||||
this will be the current members of the room. If you have left the
|
||||
room then this will be the members of the room when you left.
|
||||
examples:
|
||||
application/json: |-
|
||||
|
|
|
@ -236,6 +236,12 @@ paths:
|
|||
The global private data created by this user.
|
||||
allOf:
|
||||
- $ref: "definitions/event_batch.yaml"
|
||||
to_device:
|
||||
title: ToDevice
|
||||
type: object
|
||||
description: |-
|
||||
Information on the send-to-device messages for the client
|
||||
device, as defined in |send_to_device_sync|_.
|
||||
examples:
|
||||
application/json: |-
|
||||
{
|
||||
|
|
89
api/client-server/to_device.yaml
Normal file
89
api/client-server/to_device.yaml
Normal file
|
@ -0,0 +1,89 @@
|
|||
# Copyright 2016 OpenMarket Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
swagger: '2.0'
|
||||
info:
|
||||
title: "Matrix Client-Server Send-to-device API"
|
||||
version: "1.0.0"
|
||||
host: localhost:8008
|
||||
schemes:
|
||||
- https
|
||||
- http
|
||||
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
securityDefinitions:
|
||||
$ref: definitions/security.yaml
|
||||
paths:
|
||||
"/sendToDevice/{eventType}/{txnId}":
|
||||
put:
|
||||
summary: Send an event to a given set of devices.
|
||||
description: |-
|
||||
This endpoint is used to send send-to-device events to a set of
|
||||
client devices.
|
||||
security:
|
||||
- accessToken: []
|
||||
parameters:
|
||||
- in: path
|
||||
type: string
|
||||
name: eventType
|
||||
description: The type of event to send.
|
||||
required: true
|
||||
x-example: "m.new_device"
|
||||
- in: path
|
||||
name: txnId
|
||||
type: string
|
||||
description: |-
|
||||
The transaction ID for this event. Clients should generate an
|
||||
ID unique across requests with the same access token; it will be
|
||||
used by the server to ensure idempotency of requests.
|
||||
required: true
|
||||
x-example: "35"
|
||||
- in: body
|
||||
name: body
|
||||
required: true
|
||||
schema:
|
||||
type: object
|
||||
title: body
|
||||
properties:
|
||||
messages:
|
||||
type: object
|
||||
description: |-
|
||||
The messages to send. A map from user ID, to a map from
|
||||
device ID to message body. The device ID may also be `*`,
|
||||
meaning all known devices for the user.
|
||||
additionalProperties:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: object
|
||||
title: EventContent
|
||||
description: Message content
|
||||
example: {
|
||||
"@alice:example.com": {
|
||||
"TLLBEANAAG": {
|
||||
"example_content_key": "value"
|
||||
}
|
||||
}
|
||||
}
|
||||
responses:
|
||||
200:
|
||||
description:
|
||||
The message was successfully sent.
|
||||
examples:
|
||||
application/json: |-
|
||||
{}
|
||||
tags:
|
||||
- Send-to-Device messaging
|
|
@ -19,7 +19,7 @@ host: localhost:8090
|
|||
schemes:
|
||||
- https
|
||||
- http
|
||||
basePath: /_matrix/identity/v1/api
|
||||
basePath: /_matrix/identity/api/v1
|
||||
produces:
|
||||
- application/json
|
||||
paths:
|
||||
|
|
|
@ -19,7 +19,7 @@ host: localhost:8090
|
|||
schemes:
|
||||
- https
|
||||
- http
|
||||
basePath: /_matrix/identity/v1/api
|
||||
basePath: /_matrix/identity/api/v1
|
||||
produces:
|
||||
- application/json
|
||||
paths:
|
||||
|
|
|
@ -8,21 +8,11 @@
|
|||
which support push rules, but any other clients implementing
|
||||
the push rules API should be aware of this change. This
|
||||
makes it simple to mute rooms correctly in the API.
|
||||
|
||||
- Spec clarifications:
|
||||
|
||||
- Spell out the way that state is handled by ``POST /createRoom``
|
||||
(`#362 <https://github.com/matrix-org/matrix-doc/pull/362>`_).
|
||||
- Emphasise that ``POST /tokenrefresh`` should expire the access token
|
||||
(`#363 <https://github.com/matrix-org/matrix-doc/pull/363>`_).
|
||||
- Clarify the fields which are applicable to different types of push rule
|
||||
(`#365 <https://github.com/matrix-org/matrix-doc/pull/365>`_).
|
||||
- A number of clarifications to authentication
|
||||
(`#371 <https://github.com/matrix-org/matrix-doc/pull/371>`_).
|
||||
- Correct references to ``user_id`` which should have been ``sender``
|
||||
(`#376 <https://github.com/matrix-org/matrix-doc/pull/376>`_).
|
||||
- Correct inconsistent specification of ``redacted_because`` fields and their
|
||||
values (`#378 <https://github.com/matrix-org/matrix-doc/pull/378>`_).
|
||||
(`#373 <https://github.com/matrix-org/matrix-doc/pull/373>`_).
|
||||
- Remove ``/tokenrefresh`` from the API.
|
||||
(`#395 <https://github.com/matrix-org/matrix-doc/pull/395>`_).
|
||||
- Remove requirement that tokens used in token-based login be macaroons.
|
||||
(`#395 <https://github.com/matrix-org/matrix-doc/pull/395>`_).
|
||||
|
||||
- Changes to the API which will be backwards-compatible for clients:
|
||||
|
||||
|
@ -35,11 +25,38 @@
|
|||
- Add top-level ``account_data`` key to the responses to ``GET /sync`` and
|
||||
``GET /initialSync``
|
||||
(`#380 <https://github.com/matrix-org/matrix-doc/pull/380>`_).
|
||||
- Add ``is_direct`` flag to |/createRoom|_ and invite member event.
|
||||
Add 'Direct Messaging' module.
|
||||
(`#389 <https://github.com/matrix-org/matrix-doc/pull/389>`_).
|
||||
- Add ``contains_url`` option to ``RoomEventFilter``.
|
||||
(`#390 <https://github.com/matrix-org/matrix-doc/pull/390>`_).
|
||||
- Add ``filter`` optional query param to ``/messages``
|
||||
(`#390 <https://github.com/matrix-org/matrix-doc/pull/390>`_).
|
||||
- Add "Send-to-Device messaging" module
|
||||
(`#386 <https://github.com/matrix-org/matrix-doc/pull/386>`_).
|
||||
- Require that User-Interactive auth fallback pages call
|
||||
``window.postMessage`` to notify apps of completion
|
||||
(`#398 <https://github.com/matrix-org/matrix-doc/pull/398>`_).
|
||||
- Add pagination and filter support to ``/publicRooms``. Change response to
|
||||
omit fields rather than return ``null``. Add estimate of total number of
|
||||
rooms in list.
|
||||
(`#388 <https://github.com/matrix-org/matrix-doc/pull/388>`_).
|
||||
|
||||
- Spec clarifications:
|
||||
|
||||
- Spell out the way that state is handled by ``POST /createRoom``
|
||||
(`#362 <https://github.com/matrix-org/matrix-doc/pull/362>`_).
|
||||
- Clarify the fields which are applicable to different types of push rule
|
||||
(`#365 <https://github.com/matrix-org/matrix-doc/pull/365>`_).
|
||||
- A number of clarifications to authentication
|
||||
(`#371 <https://github.com/matrix-org/matrix-doc/pull/371>`_).
|
||||
- Correct references to ``user_id`` which should have been ``sender``
|
||||
(`#376 <https://github.com/matrix-org/matrix-doc/pull/376>`_).
|
||||
- Correct inconsistent specification of ``redacted_because`` fields and their
|
||||
values (`#378 <https://github.com/matrix-org/matrix-doc/pull/378>`_).
|
||||
- Mark required fields in response objects as such
|
||||
(`#394 <https://github.com/matrix-org/matrix-doc/pull/394>`_).
|
||||
|
||||
r0.2.0
|
||||
======
|
||||
|
||||
|
|
9
event-schemas/examples/m.direct
Normal file
9
event-schemas/examples/m.direct
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"type": "m.direct",
|
||||
"content": {
|
||||
"@bob:example.com": [
|
||||
"!abcdefgh:example.com",
|
||||
"!hgfedcba:example.com"
|
||||
]
|
||||
}
|
||||
}
|
21
event-schemas/schema/m.direct
Normal file
21
event-schemas/schema/m.direct
Normal file
|
@ -0,0 +1,21 @@
|
|||
---
|
||||
allOf:
|
||||
- $ref: core-event-schema/event.yaml
|
||||
description: |-
|
||||
A map of which rooms are considered 'direct' rooms for specific users
|
||||
is kept in ``account_data`` in an event of type ``m.direct``. The
|
||||
content of this event is an object where the keys are the user IDs
|
||||
and values are lists of room ID strings of the 'direct' rooms for
|
||||
that user ID.
|
||||
properties:
|
||||
content:
|
||||
additionalProperties:
|
||||
type: array
|
||||
title: User ID
|
||||
type: object
|
||||
type:
|
||||
enum:
|
||||
- m.direct
|
||||
type: string
|
||||
title: Direct Chat Mapping
|
||||
type: object
|
|
@ -39,6 +39,9 @@ properties:
|
|||
- leave
|
||||
- ban
|
||||
type: string
|
||||
is_direct:
|
||||
description: Flag indicating if the room containing this event was created with the intention of being a direct chat. See `Direct Messaging`_.
|
||||
type: boolean
|
||||
third_party_invite:
|
||||
properties:
|
||||
display_name:
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/golang-lru"
|
||||
|
@ -83,19 +84,15 @@ func accessTokenQuerystring() string {
|
|||
return fmt.Sprintf("?access_token=%s", *accessToken)
|
||||
}
|
||||
|
||||
func gitClone(url string, shared bool) (string, error) {
|
||||
directory := path.Join("/tmp/matrix-doc", strconv.FormatInt(rand.Int63(), 10))
|
||||
if err := os.MkdirAll(directory, permissionsOwnerFull); err != nil {
|
||||
return "", fmt.Errorf("error making directory %s: %v", directory, err)
|
||||
}
|
||||
func gitClone(url string, directory string, shared bool) error {
|
||||
args := []string{"clone", url, directory}
|
||||
if shared {
|
||||
args = append(args, "--shared")
|
||||
}
|
||||
if err := runGitCommand(directory, args); err != nil {
|
||||
return "", err
|
||||
return err
|
||||
}
|
||||
return directory, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func gitCheckout(path, sha string) error {
|
||||
|
@ -159,6 +156,16 @@ func generate(dir string) error {
|
|||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("error generating spec: %v\nOutput from gendoc:\n%v", err, b.String())
|
||||
}
|
||||
|
||||
// cheekily dump the swagger docs into the gen directory so they can be
|
||||
// served by serveSpec
|
||||
cmd = exec.Command("python", "dump-swagger.py", "gen/api-docs.json")
|
||||
cmd.Dir = path.Join(dir, "scripts")
|
||||
cmd.Stderr = &b
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("error generating api docs: %v\nOutput from dump-swagger:\n%v", err, b.String())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -195,8 +202,14 @@ func (s *server) generateAt(sha string) (dst string, err error) {
|
|||
return
|
||||
}
|
||||
}
|
||||
|
||||
dst, err = makeTempDir()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
log.Printf("Generating %s in %s\n", sha, dst)
|
||||
s.mu.Lock()
|
||||
dst, err = gitClone(s.matrixDocCloneURL, true)
|
||||
err = gitClone(s.matrixDocCloneURL, dst, true)
|
||||
s.mu.Unlock()
|
||||
if err != nil {
|
||||
return
|
||||
|
@ -219,7 +232,7 @@ func (s *server) getSHAOf(ref string) (string, error) {
|
|||
err := cmd.Run()
|
||||
s.mu.Unlock()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error generating spec: %v\nOutput from gendoc:\n%v", err, b.String())
|
||||
return "", fmt.Errorf("error generating spec: %v\nOutput from git:\n%v", err, b.String())
|
||||
}
|
||||
return strings.TrimSpace(b.String()), nil
|
||||
}
|
||||
|
@ -396,6 +409,11 @@ func (s *server) serveSpec(w http.ResponseWriter, req *http.Request) {
|
|||
cache.Add(sha, pathToContent)
|
||||
}
|
||||
|
||||
if requestedPath == "api-docs.json" {
|
||||
// allow other swagger UIs access to our swagger
|
||||
w.Header().Set("Access-Control-Allow-Origin", "*")
|
||||
}
|
||||
|
||||
if b, ok := pathToContent[requestedPath]; ok {
|
||||
w.Write(b)
|
||||
return
|
||||
|
@ -588,12 +606,6 @@ func (srv *server) makeIndex(w http.ResponseWriter, req *http.Request) {
|
|||
writeError(w, 500, err)
|
||||
return
|
||||
}
|
||||
s := "<body><ul>"
|
||||
for _, pull := range pulls {
|
||||
s += fmt.Sprintf(`<li>%d: <a href="%s">%s</a>: <a href="%s">%s</a>: <a href="spec/%d/">spec</a> <a href="diff/html/%d/">spec diff</a> <a href="diff/rst/%d/">rst diff</a></li>`,
|
||||
pull.Number, pull.User.HTMLURL, pull.User.Login, pull.HTMLURL, pull.Title, pull.Number, pull.Number, pull.Number)
|
||||
}
|
||||
s += "</ul>"
|
||||
|
||||
branches, err := srv.getBranches()
|
||||
if err != nil {
|
||||
|
@ -601,7 +613,48 @@ func (srv *server) makeIndex(w http.ResponseWriter, req *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
s += `<div>View the spec at:<ul>`
|
||||
// write our stuff into a buffer so that we can change our minds
|
||||
// and write a 500 if it all goes wrong.
|
||||
var b bytes.Buffer
|
||||
b.Write([]byte(`
|
||||
<head>
|
||||
<script>
|
||||
function redirectToApiDocs(relativePath) {
|
||||
var url = new URL(window.location);
|
||||
url.pathname += relativePath;
|
||||
var newLoc = "http://matrix.org/docs/api/client-server/?url=" + encodeURIComponent(url);
|
||||
window.location = newLoc;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body><ul>
|
||||
`))
|
||||
|
||||
tmpl, err := template.New("pr entry").Parse(`
|
||||
<li>{{.Number}}:
|
||||
<a href="{{.User.HTMLURL}}">{{.User.Login}}</a>:
|
||||
<a href="{{.HTMLURL}}">{{.Title}}</a>:
|
||||
<a href="spec/{{.Number}}/">spec</a>
|
||||
<a href="#" onclick="redirectToApiDocs('spec/{{.Number}}/api-docs.json')">api docs</a>
|
||||
<a href="diff/html/{{.Number}}/">spec diff</a>
|
||||
<a href="diff/rst/{{.Number}}/">rst diff</a>
|
||||
</li>
|
||||
`)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, pull := range pulls {
|
||||
err = tmpl.Execute(&b, pull)
|
||||
if err != nil {
|
||||
writeError(w, 500, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
b.Write([]byte(`
|
||||
</ul>
|
||||
<div>View the spec at:<ul>
|
||||
`))
|
||||
branchNames := []string{}
|
||||
for _, branch := range branches {
|
||||
if strings.HasPrefix(branch, "drafts/") {
|
||||
|
@ -611,15 +664,14 @@ func (srv *server) makeIndex(w http.ResponseWriter, req *http.Request) {
|
|||
branchNames = append(branchNames, "HEAD")
|
||||
for _, branch := range branchNames {
|
||||
href := "spec/" + url.QueryEscape(branch) + "/"
|
||||
s += fmt.Sprintf(`<li><a href="%s">%s</a></li>`, href, branch)
|
||||
fmt.Fprintf(&b, `<li><a href="%s">%s</a></li>`, href, branch)
|
||||
if *includesDir != "" {
|
||||
s += fmt.Sprintf(`<li><a href="%s?matrixdotorgstyle=1">%s, styled like matrix.org</a></li>`,
|
||||
fmt.Fprintf(&b, `<li><a href="%s?matrixdotorgstyle=1">%s, styled like matrix.org</a></li>`,
|
||||
href, branch)
|
||||
}
|
||||
}
|
||||
s += "</ul></div></body>"
|
||||
|
||||
io.WriteString(w, s)
|
||||
b.Write([]byte("</ul></div></body>"))
|
||||
b.WriteTo(w)
|
||||
}
|
||||
|
||||
func ignoreExitCodeOne(err error) error {
|
||||
|
@ -655,10 +707,14 @@ func main() {
|
|||
log.Fatal(err)
|
||||
}
|
||||
rand.Seed(time.Now().Unix())
|
||||
masterCloneDir, err := gitClone(matrixDocCloneURL, false)
|
||||
masterCloneDir, err := makeTempDir()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
log.Printf("Creating master clone dir %s\n", masterCloneDir)
|
||||
if err = gitClone(matrixDocCloneURL, masterCloneDir, false); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
s := server{matrixDocCloneURL: masterCloneDir}
|
||||
http.HandleFunc("/spec/", forceHTML(s.serveSpec))
|
||||
http.HandleFunc("/diff/rst/", s.serveRSTDiff)
|
||||
|
@ -691,3 +747,11 @@ func initCache() error {
|
|||
styledSpecCache = c2
|
||||
return err
|
||||
}
|
||||
|
||||
func makeTempDir() (string, error) {
|
||||
directory := path.Join("/tmp/matrix-doc", strconv.FormatInt(rand.Int63(), 10))
|
||||
if err := os.MkdirAll(directory, permissionsOwnerFull); err != nil {
|
||||
return "", fmt.Errorf("error making directory %s: %v", directory, err)
|
||||
}
|
||||
return directory, nil
|
||||
}
|
||||
|
|
|
@ -158,14 +158,23 @@ recommended.
|
|||
|
||||
Client Authentication
|
||||
---------------------
|
||||
|
||||
Most API endpoints require the user to identify themselves by presenting
|
||||
previously obtained credentials in the form of an ``access_token`` query
|
||||
parameter.
|
||||
parameter. An access token is typically obtained via the `Login`_ or
|
||||
`Registration`_ processes.
|
||||
|
||||
When credentials are required but missing or invalid, the HTTP call will
|
||||
return with a status of 401 and the error code, ``M_MISSING_TOKEN`` or
|
||||
``M_UNKNOWN_TOKEN`` respectively.
|
||||
|
||||
.. NOTE::
|
||||
|
||||
This specification does not mandate a particular format for the access
|
||||
token. Clients should treat it as an opaque byte sequence. Servers are free
|
||||
to choose an appropriate format. Server implementors may like to investigate
|
||||
`macaroons <macaroon_>`_.
|
||||
|
||||
User-Interactive Authentication API
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -249,7 +258,7 @@ complete auth type ``example.type.foo``, it might submit something like this:
|
|||
|
||||
POST /_matrix/client/r0/endpoint HTTP/1.1
|
||||
Content-Type: application/json
|
||||
|
||||
|
||||
{
|
||||
"a_request_parameter": "something",
|
||||
"another_request_parameter": "something else",
|
||||
|
@ -289,8 +298,42 @@ successfully:
|
|||
"session": "xxxxxx"
|
||||
}
|
||||
|
||||
If the homeserver decides the attempt was unsuccessful, it returns an error
|
||||
message in the standard format:
|
||||
Individual stages may require more than one request to complete, in which case
|
||||
the response will be as if the request was unauthenticated with the addition of
|
||||
any other keys as defined by the auth type.
|
||||
|
||||
If the homeserver decides that an attempt on a stage was unsuccessful, but the
|
||||
client may make a second attempt, it returns the same HTTP status 401 response
|
||||
as above, with the addition of the standard ``errcode`` and ``error`` fields
|
||||
describing the error. For example:
|
||||
|
||||
.. code::
|
||||
|
||||
HTTP/1.1 401 Unauthorized
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"errcode": "M_FORBIDDEN",
|
||||
"error": "Invalid password",
|
||||
"completed": [ "example.type.foo" ],
|
||||
"flows": [
|
||||
{
|
||||
"stages": [ "example.type.foo", "example.type.bar" ]
|
||||
},
|
||||
{
|
||||
"stages": [ "example.type.foo", "example.type.baz" ]
|
||||
}
|
||||
],
|
||||
"params": {
|
||||
"example.type.baz": {
|
||||
"example_key": "foobar"
|
||||
}
|
||||
},
|
||||
"session": "xxxxxx"
|
||||
}
|
||||
|
||||
If the request fails for a reason other than authentication, the server returns an error
|
||||
message in the standard format. For example:
|
||||
|
||||
.. code::
|
||||
|
||||
|
@ -302,10 +345,6 @@ message in the standard format:
|
|||
"error": "Something was wrong"
|
||||
}
|
||||
|
||||
Individual stages may require more than one request to complete, in which case
|
||||
the response will be as if the request was unauthenticated with the addition of
|
||||
any other keys as defined by the auth type.
|
||||
|
||||
If the client has completed all stages of a flow, the homeserver performs the
|
||||
API call and returns the result as normal.
|
||||
|
||||
|
@ -389,7 +428,8 @@ To use this authentication type, clients should submit an auth dict as follows:
|
|||
{
|
||||
"type": "m.login.password",
|
||||
"user": "<user_id or user localpart>",
|
||||
"password": "<password>"
|
||||
"password": "<password>",
|
||||
"session": "<session ID>"
|
||||
}
|
||||
|
||||
Alternatively reply using a 3pid bound to the user's account on the homeserver
|
||||
|
@ -402,18 +442,13 @@ follows:
|
|||
"type": "m.login.password",
|
||||
"medium": "<The medium of the third party identifier. Must be 'email'>",
|
||||
"address": "<The third party address of the user>",
|
||||
"password": "<password>"
|
||||
"password": "<password>",
|
||||
"session": "<session ID>"
|
||||
}
|
||||
|
||||
In the case that the homeserver does not know about the supplied 3pid, the
|
||||
homeserver must respond with 403 Forbidden.
|
||||
|
||||
.. WARNING::
|
||||
Clients SHOULD enforce that the password provided is suitably complex. The
|
||||
password SHOULD include a lower-case letter, an upper-case letter, a number
|
||||
and a symbol and be at a minimum 8 characters in length. Servers MAY reject
|
||||
weak passwords with an error code ``M_WEAK_PASSWORD``.
|
||||
|
||||
Google ReCaptcha
|
||||
<<<<<<<<<<<<<<<<
|
||||
:Type:
|
||||
|
@ -427,7 +462,8 @@ To use this authentication type, clients should submit an auth dict as follows:
|
|||
|
||||
{
|
||||
"type": "m.login.recaptcha",
|
||||
"response": "<captcha response>"
|
||||
"response": "<captcha response>",
|
||||
"session": "<session ID>"
|
||||
}
|
||||
|
||||
Token-based
|
||||
|
@ -444,7 +480,8 @@ To use this authentication type, clients should submit an auth dict as follows:
|
|||
{
|
||||
"type": "m.login.token",
|
||||
"token": "<token>",
|
||||
"txn_id": "<client generated nonce>"
|
||||
"txn_id": "<client generated nonce>",
|
||||
"session": "<session ID>"
|
||||
}
|
||||
|
||||
The ``nonce`` should be a random string generated by the client for the
|
||||
|
@ -460,8 +497,8 @@ server side, as well as potentially invalidating the token completely once the
|
|||
device has successfully logged in (e.g. when we receive a request from the
|
||||
newly provisioned access_token).
|
||||
|
||||
The ``token`` must be a macaroon, with a caveat encoding the user id. There is
|
||||
therefore no need for the client to submit a separate username.
|
||||
The server must encode the user id in the ``token``. There is therefore no need
|
||||
for the client to submit a separate username.
|
||||
|
||||
OAuth2-based
|
||||
<<<<<<<<<<<<
|
||||
|
@ -511,7 +548,8 @@ To use this authentication type, clients should submit an auth dict as follows:
|
|||
"client_secret": "<identity server client secret>",
|
||||
"id_server": "<url of identity server authed with, e.g. 'matrix.org:8090'>"
|
||||
}
|
||||
]
|
||||
],
|
||||
"session": "<session ID>"
|
||||
}
|
||||
|
||||
Dummy Auth
|
||||
|
@ -529,12 +567,13 @@ the type and session, if provided:
|
|||
.. code:: json
|
||||
|
||||
{
|
||||
"type": "m.login.dummy"
|
||||
"type": "m.login.dummy",
|
||||
"session": "<session ID>"
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
@ -544,11 +583,93 @@ should open is::
|
|||
/_matrix/client/%CLIENT_MAJOR_VERSION%/auth/<auth type>/fallback/web?session=<session ID>
|
||||
|
||||
Where ``auth type`` is the type name of the stage it is attempting and
|
||||
``session id`` is the ID of the session given by the homeserver.
|
||||
``session ID`` is the ID of the session given by the homeserver.
|
||||
|
||||
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.
|
||||
page must use the following JavaScript when the authentication has been
|
||||
completed:
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
if (window.onAuthDone) {
|
||||
window.onAuthDone();
|
||||
} else if (window.opener && window.opener.postMessage) {
|
||||
window.opener.postMessage("authDone", "*");
|
||||
}
|
||||
|
||||
This allows the client to either arrange for the global function ``onAuthDone``
|
||||
to be defined in an embedded browser, or to use the HTML5 `cross-document
|
||||
messaging <https://www.w3.org/TR/webmessaging/#web-messaging>`_ API, to receive
|
||||
a notification that the authentication stage has been completed.
|
||||
|
||||
Once a client receives the notificaton that the authentication stage has been
|
||||
completed, it should resubmit the request with an auth dict with just the
|
||||
session ID:
|
||||
|
||||
.. code:: json
|
||||
|
||||
{
|
||||
"session": "<session ID>"
|
||||
}
|
||||
|
||||
|
||||
Example
|
||||
<<<<<<<
|
||||
A client webapp might use the following javascript to open a popup window which will
|
||||
handle unknown login types:
|
||||
|
||||
.. code:: javascript
|
||||
|
||||
/**
|
||||
* Arguments:
|
||||
* homeserverUrl: the base url of the homeserver (eg "https://matrix.org")
|
||||
*
|
||||
* apiEndpoint: the API endpoint being used (eg
|
||||
* "/_matrix/client/%CLIENT_MAJOR_VERSION%/account/password")
|
||||
*
|
||||
* loginType: the loginType being attempted (eg "m.login.recaptcha")
|
||||
*
|
||||
* sessionID: the session ID given by the homeserver in earlier requests
|
||||
*
|
||||
* onComplete: a callback which will be called with the results of the request
|
||||
*/
|
||||
function unknownLoginType(homeserverUrl, apiEndpoint, loginType, sessionID, onComplete) {
|
||||
var popupWindow;
|
||||
|
||||
var eventListener = function(ev) {
|
||||
// check it's the right message from the right place.
|
||||
if (ev.data !== "authDone" || ev.origin !== homeserverUrl) {
|
||||
return;
|
||||
}
|
||||
|
||||
// close the popup
|
||||
popupWindow.close();
|
||||
window.removeEventListener("message", eventListener);
|
||||
|
||||
// repeat the request
|
||||
var requestBody = {
|
||||
auth: {
|
||||
session: sessionID,
|
||||
},
|
||||
};
|
||||
|
||||
request({
|
||||
method:'POST', url:apiEndpint, json:requestBody,
|
||||
}, onComplete);
|
||||
};
|
||||
|
||||
window.addEventListener("message", eventListener);
|
||||
|
||||
var url = homeserverUrl +
|
||||
"/_matrix/client/%CLIENT_MAJOR_VERSION%/auth/" +
|
||||
encodeURIComponent(loginType) +
|
||||
"/fallback/web?session=" +
|
||||
encodeURIComponent(sessionID);
|
||||
|
||||
|
||||
popupWindow = window.open(url);
|
||||
}
|
||||
|
||||
|
||||
Login
|
||||
~~~~~
|
||||
|
@ -595,9 +716,9 @@ follows:
|
|||
"token": "<login token>"
|
||||
}
|
||||
|
||||
As with `token-based`_ interactive login, the ``token`` must be a macroon with
|
||||
a caveat which includes the user id. In the case that the token is not valid, the
|
||||
homeserver must respond with ``403 Forbidden`` and an error code of ``M_FORBIDDEN``.
|
||||
As with `token-based`_ interactive login, the ``token`` must encode the
|
||||
user id. In the case that the token is not valid, the homeserver must respond
|
||||
with ``403 Forbidden`` and an error code of ``M_FORBIDDEN``.
|
||||
|
||||
{{login_cs_http_api}}
|
||||
|
||||
|
@ -615,6 +736,8 @@ This returns an HTML and JavaScript page which can perform the entire login
|
|||
process. The page will attempt to call the JavaScript function
|
||||
``window.onLogin`` when login has been successfully completed.
|
||||
|
||||
.. _Registration:
|
||||
|
||||
Account registration and management
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
@ -1230,6 +1353,9 @@ have to wait in milliseconds before they can try again.
|
|||
homeserver come up with their own idea, causing totally unpredictable performance over
|
||||
federated rooms?
|
||||
|
||||
.. References
|
||||
|
||||
.. _`macaroon`: http://research.google.com/pubs/pub41892.html
|
||||
|
||||
.. Links through the external API docs are below
|
||||
.. =============================================
|
||||
|
@ -1237,15 +1363,15 @@ have to wait in milliseconds before they can try again.
|
|||
.. |/initialSync| replace:: ``/initialSync``
|
||||
.. _/initialSync: #get-matrix-client-%CLIENT_MAJOR_VERSION%-initialsync
|
||||
|
||||
.. |/tokenrefresh| replace:: ``/tokenrefresh``
|
||||
.. _/tokenrefresh: #post-matrix-client-%CLIENT_MAJOR_VERSION%-tokenrefresh
|
||||
|
||||
.. |/sync| replace:: ``/sync``
|
||||
.. _/sync: #get-matrix-client-%CLIENT_MAJOR_VERSION%-sync
|
||||
|
||||
.. |/events| replace:: ``/events``
|
||||
.. _/events: #get-matrix-client-%CLIENT_MAJOR_VERSION%-events
|
||||
|
||||
.. |/createRoom| replace:: ``/createRoom``
|
||||
.. _/createRoom: #post-matrix-client-%CLIENT_MAJOR_VERSION%-createroom
|
||||
|
||||
.. |/rooms/<room_id>/initialSync| replace:: ``/rooms/<room_id>/initialSync``
|
||||
.. _/rooms/<room_id>/initialSync: #get-matrix-client-%CLIENT_MAJOR_VERSION%-rooms-roomid-initialsync
|
||||
|
||||
|
@ -1258,6 +1384,9 @@ have to wait in milliseconds before they can try again.
|
|||
.. |/rooms/<room_id>/state| replace:: ``/rooms/<room_id>/state``
|
||||
.. _/rooms/<room_id>/state: #get-matrix-client-%CLIENT_MAJOR_VERSION%-rooms-roomid-state
|
||||
|
||||
.. |/rooms/<room_id>/send| replace:: ``/rooms/<room_id>/send``
|
||||
.. _/rooms/<room_id>/send: #put-matrix-client-%CLIENT_MAJOR_VERSION%-rooms-roomid-send-eventtype-txnid
|
||||
|
||||
.. |/rooms/<room_id>/invite| replace:: ``/rooms/<room_id>/invite``
|
||||
.. _/rooms/<room_id>/invite: #post-matrix-client-%CLIENT_MAJOR_VERSION%-rooms-roomid-invite
|
||||
|
||||
|
@ -1278,3 +1407,6 @@ have to wait in milliseconds before they can try again.
|
|||
|
||||
.. |/account/3pid| replace:: ``/account/3pid``
|
||||
.. _/account/3pid: #post-matrix-client-%CLIENT_MAJOR_VERSION%-account-3pid
|
||||
|
||||
.. |/user/<user_id>/account_data/<type>| replace:: ``/user/<user_id>/account_data/<type>``
|
||||
.. _/user/<user_id>/account_data/<type>: #put-matrix-client-%CLIENT_MAJOR_VERSION%-user-userid-account-data-type
|
||||
|
|
|
@ -110,7 +110,7 @@ Creating a session
|
|||
|
||||
A client makes a call to::
|
||||
|
||||
POST https://my.id.server:8090/_matrix/identity/v1/api/validate/email/requestToken
|
||||
POST https://my.id.server:8090/_matrix/identity/api/v1/validate/email/requestToken
|
||||
|
||||
client_secret=monkeys_are_GREAT&
|
||||
email=foo@bar.com&
|
||||
|
@ -147,7 +147,7 @@ Validating ownership of an email
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A user may make either a ``GET`` or a ``POST`` request to
|
||||
``/_matrix/identity/v1/api/validate/email/submitToken`` with the following
|
||||
``/_matrix/identity/api/v1/validate/email/submitToken`` with the following
|
||||
parameters (either as query parameters or URL-encoded POST parameters):
|
||||
- ``sid`` the sid for the session, generated by the ``requestToken`` call.
|
||||
- ``client_secret`` the client secret which was supplied to the ``requestToken`` call.
|
||||
|
@ -164,7 +164,7 @@ Checking non-published 3pid ownership
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A client can check whether ownership of a 3pid was validated by making an
|
||||
HTTP GET request to ``/_matrix/identity/v1/api/3pid/getValidated3pid``, passing
|
||||
HTTP GET request to ``/_matrix/identity/api/v1/3pid/getValidated3pid``, passing
|
||||
the ``sid`` and ``client_secret`` as query parameters from the ``requestToken``
|
||||
call.
|
||||
|
||||
|
@ -183,7 +183,7 @@ Publishing a validated association
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
An association between a session and a Matrix user ID can be published by making
|
||||
a URL-encoded HTTP POST request to ``/_matrix/identity/v1/api/3pid/bind`` with
|
||||
a URL-encoded HTTP POST request to ``/_matrix/identity/api/v1/3pid/bind`` with
|
||||
the following parameters::
|
||||
|
||||
sid=sid&
|
||||
|
@ -256,7 +256,7 @@ At a later point, if the owner of that particular 3pid binds it with a Matrix us
|
|||
|
||||
Where the signature is produced using a long-term private key.
|
||||
|
||||
Also, the generated ephemeral public key will be listed as valid on requests to ``/_matrix/identity/v1/api/pubkey/ephemeral/isvalid``.
|
||||
Also, the generated ephemeral public key will be listed as valid on requests to ``/_matrix/identity/api/v1/pubkey/ephemeral/isvalid``.
|
||||
|
||||
Ephemeral invitation signing
|
||||
----------------------------
|
||||
|
|
58
specification/modules/dm.rst
Normal file
58
specification/modules/dm.rst
Normal file
|
@ -0,0 +1,58 @@
|
|||
.. Copyright 2016 OpenMarket Ltd
|
||||
..
|
||||
.. Licensed under the Apache License, Version 2.0 (the "License");
|
||||
.. you may not use this file except in compliance with the License.
|
||||
.. You may obtain a copy of the License at
|
||||
..
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
..
|
||||
.. Unless required by applicable law or agreed to in writing, software
|
||||
.. distributed under the License is distributed on an "AS IS" BASIS,
|
||||
.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
.. See the License for the specific language governing permissions and
|
||||
.. limitations under the License.
|
||||
|
||||
Direct Messaging
|
||||
================
|
||||
|
||||
.. _module:dm:
|
||||
|
||||
All communication over Matrix happens within a room. It is sometimes
|
||||
desirable to offer users the concept of speaking directly to one
|
||||
particular person. This module defines a way of marking certain rooms
|
||||
as 'direct chats' with a given person. This does not restrict the chat
|
||||
to being between exactly two people since this would preclude the
|
||||
presence of automated 'bot' users or even a 'personal assistant' who is
|
||||
able to answer direct messages on behalf of the user in their absence.
|
||||
|
||||
A room may not necessarily be considered 'direct' by all members of the
|
||||
room, but a signalling mechanism exists to propagate the information of
|
||||
whether a chat is 'direct' to an invitee.
|
||||
|
||||
Events
|
||||
------
|
||||
|
||||
{{m_direct_event}}
|
||||
|
||||
Client behaviour
|
||||
----------------
|
||||
To start a direct chat with another user, the inviting user's client
|
||||
should set the ``is_direct`` flag to |/createRoom|_. The client should do
|
||||
this whenever the flow the user has followed is one where their
|
||||
intention is to speak directly with another person, as opposed to bringing that
|
||||
person in to a shared room. For example, clicking on 'Start Chat' beside a
|
||||
person's profile picture would imply the ``is_direct`` flag should be set.
|
||||
|
||||
The invitee's client may use the ``is_direct`` flag in the `m.room.member`_
|
||||
event to automatically mark the room as a direct chat but this is not
|
||||
required: it may for example, prompt the user, or ignore the flag altogether.
|
||||
|
||||
Both the inviting client and the invitee's client should record the fact that
|
||||
the room is a direct chat by storing an ``m.direct`` event in the account data
|
||||
using |/user/<user_id>/account_data/<type>|_.
|
||||
|
||||
Server behaviour
|
||||
----------------
|
||||
When the ``is_direct`` flag is given to |/createRoom|_, the home
|
||||
server must set the ``is_direct`` flag in the invite member event for any users
|
||||
invited in the |/createRoom|_ call.
|
|
@ -107,6 +107,15 @@ There is a single API endpoint for this, as described below.
|
|||
|
||||
.. _pushers: `def:pushers`_
|
||||
|
||||
Listing Notifications
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
A client can retrieve a list of events that it has been notified about. This
|
||||
may be useful so that users can see a summary of what important messages they
|
||||
have received.
|
||||
|
||||
{{notifications_cs_http_api}}
|
||||
|
||||
Push Rules
|
||||
~~~~~~~~~~
|
||||
A push rule is a single rule that states under what *conditions* an event should
|
||||
|
|
146
specification/modules/send_to_device.rst
Normal file
146
specification/modules/send_to_device.rst
Normal file
|
@ -0,0 +1,146 @@
|
|||
.. Copyright 2016 OpenMarket Ltd
|
||||
..
|
||||
.. Licensed under the Apache License, Version 2.0 (the "License");
|
||||
.. you may not use this file except in compliance with the License.
|
||||
.. You may obtain a copy of the License at
|
||||
..
|
||||
.. http://www.apache.org/licenses/LICENSE-2.0
|
||||
..
|
||||
.. Unless required by applicable law or agreed to in writing, software
|
||||
.. distributed under the License is distributed on an "AS IS" BASIS,
|
||||
.. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
.. See the License for the specific language governing permissions and
|
||||
.. limitations under the License.
|
||||
|
||||
Send-to-Device messaging
|
||||
========================
|
||||
|
||||
.. _module:to_device:
|
||||
|
||||
This module provides a means by which clients can exchange signalling messages
|
||||
without them being stored permanently as part of a shared communication
|
||||
history. A message is delivered exactly once to each client device.
|
||||
|
||||
The primary motivation for this API is exchanging data that is meaningless or
|
||||
undesirable to persist in the room DAG - for example, one-time authentication
|
||||
tokens or key data. It is not intended for conversational data, which should be
|
||||
sent using the normal |/rooms/<room_id>/send|_ API for consistency throughout
|
||||
Matrix.
|
||||
|
||||
Client behaviour
|
||||
----------------
|
||||
To send a message to other devices, a client should call |/sendToDevice|_.
|
||||
Only one message can be sent to each device per transaction, and they must all
|
||||
have the same event type. The device ID in the request body can be set to ``*``
|
||||
to request that the message be sent to all known devices.
|
||||
|
||||
If there are send-to-device messages waiting for a client, they will be
|
||||
returned by |/sync|_, as detailed in `Extensions to /sync`_. Clients should
|
||||
inspect the ``type`` of each returned event, and ignore any they do not
|
||||
understand.
|
||||
|
||||
Server behaviour
|
||||
----------------
|
||||
Servers should store pending messages for local users until they are
|
||||
successfully delivered to the destination device. When a client calls |/sync|_
|
||||
with an access token which corresponds to a device with pending messages, the
|
||||
server should list the pending messages, in order of arrival, in the response
|
||||
body.
|
||||
|
||||
When the client calls ``/sync`` again with the ``next_batch`` token from the
|
||||
first response, the server should infer that any send-to-device messages in
|
||||
that response have been delivered successfully, and delete them from the store.
|
||||
|
||||
If there is a large queue of send-to-device messages, the server should
|
||||
limit the number sent in each ``/sync`` response. 100 messages is recommended
|
||||
as a reasonable limit.
|
||||
|
||||
If the client sends messages to users on remote domains, those messages should
|
||||
be sent on to the remote servers via
|
||||
`federation`_.
|
||||
|
||||
.. _`federation`: ../server_server/latest.html#send-to-device-messages
|
||||
|
||||
.. TODO-spec:
|
||||
|
||||
* Is a server allowed to delete undelivered messages? After how long? What
|
||||
about if the device is deleted?
|
||||
|
||||
* If the destination HS doesn't support the ``m.direct_to_device`` EDU, it
|
||||
will just get dumped. Should we indicate that to the client?
|
||||
|
||||
|
||||
Protocol definitions
|
||||
--------------------
|
||||
|
||||
{{to_device_cs_http_api}}
|
||||
|
||||
.. TODO-spec:
|
||||
|
||||
* What should a server do if the user id or device id is unknown? Presumably
|
||||
it shouldn't reject the request outright, because some of the destinations
|
||||
may be valid. Should we add something to the response?
|
||||
|
||||
.. anchor for link from /sync api spec
|
||||
.. |send_to_device_sync| replace:: Send-to-Device messaging
|
||||
.. _send_to_device_sync:
|
||||
|
||||
Extensions to /sync
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This module adds the following properties to the |/sync|_ response:
|
||||
|
||||
.. todo: generate this from a swagger definition?
|
||||
|
||||
========= ========= =======================================================
|
||||
Parameter Type Description
|
||||
========= ========= =======================================================
|
||||
to_device ToDevice Optional. Information on the send-to-device messages
|
||||
for the client device.
|
||||
========= ========= =======================================================
|
||||
|
||||
``ToDevice``
|
||||
|
||||
========= ========= =============================================
|
||||
Parameter Type Description
|
||||
========= ========= =============================================
|
||||
events [Event] List of send-to-device messages
|
||||
========= ========= =============================================
|
||||
|
||||
``Event``
|
||||
|
||||
================ ============ ==================================================
|
||||
Parameter Type Description
|
||||
================ ============ ==================================================
|
||||
content EventContent The content of this event. The fields in this
|
||||
object will vary depending on the type of event.
|
||||
sender string The Matrix user ID of the user who sent this
|
||||
event.
|
||||
type string The type of event.
|
||||
================ ============ ==================================================
|
||||
|
||||
|
||||
Example response:
|
||||
|
||||
.. code:: json
|
||||
|
||||
{
|
||||
"next_batch": "s72595_4483_1934",
|
||||
"rooms": {"leave": {}, "join": {}, "invite": {}},
|
||||
"to_device": {
|
||||
"events": [
|
||||
{
|
||||
"sender": "@alice:example.com",
|
||||
"type": "m.new_device",
|
||||
"content": {
|
||||
"device_id": "XYZABCDE",
|
||||
"rooms": ["!726s6s6q:example.com"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.. |/sendToDevice| replace:: ``/sendToDevice``
|
||||
.. _/sendToDevice: #put-matrix-client-%CLIENT_MAJOR_VERSION%-sendtodevice-eventtype-txnid
|
|
@ -974,3 +974,27 @@ The list of join candidates is a list of server names that are likely to hold
|
|||
the given room; these are servers that the requesting server may wish to use as
|
||||
resident servers as part of the remote join handshake. This list may or may not
|
||||
include the server answering the query.
|
||||
|
||||
Send-to-device messaging
|
||||
------------------------
|
||||
|
||||
.. TODO: add modules to the federation spec and make this a module
|
||||
|
||||
The server API for send-to-device messaging is based on the following
|
||||
EDU. There are no PDUs or Federation Queries involved.
|
||||
|
||||
Each send-to-device message should be sent to the destination server using
|
||||
the following EDU::
|
||||
|
||||
EDU type: m.direct_to_device
|
||||
|
||||
Content keys:
|
||||
sender: user ID of the sender
|
||||
|
||||
type: event type for the message
|
||||
|
||||
message_id: unique id for the message: used for idempotence
|
||||
|
||||
messages: The messages to send. A map from user ID, to a map from device ID
|
||||
to message body. The device ID may also be *, meaning all known devices
|
||||
for the user.
|
||||
|
|
|
@ -41,6 +41,7 @@ groups: # reusable blobs of files when prefixed with 'group:'
|
|||
- modules/receipts.rst
|
||||
- modules/presence.rst
|
||||
- modules/content_repo.rst
|
||||
- modules/send_to_device.rst
|
||||
- modules/end_to_end_encryption.rst
|
||||
- modules/history_visibility.rst
|
||||
- modules/push.rst
|
||||
|
@ -53,6 +54,7 @@ groups: # reusable blobs of files when prefixed with 'group:'
|
|||
- modules/admin.rst
|
||||
- modules/event_context.rst
|
||||
- modules/cas_login.rst
|
||||
- modules/dm.rst
|
||||
|
||||
|
||||
title_styles: ["=", "-", "~", "+", "^", "`", "@", ":"]
|
||||
|
|
|
@ -5,7 +5,7 @@ categories: projects client
|
|||
thumbnail: https://matrix.org/blog/wp-content/uploads/2015/08/vector030216-400x284.png
|
||||
author: Riot.im
|
||||
description: Riot is a glossy web client with an emphasis on performance and usability
|
||||
maturity: Late beta
|
||||
maturity: Released
|
||||
---
|
||||
|
||||

|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
layout: project
|
||||
title: Try Matrix Now!
|
||||
categories: projects client
|
||||
---
|
||||
|
||||
<html>
|
||||
|
|
|
@ -5,7 +5,7 @@ categories: projects client
|
|||
thumbnail: /docs/projects/images/vector-iOS-small.png
|
||||
description: Riot is a glossy client with an emphasis on performance and usability
|
||||
author: Riot.im
|
||||
maturity: Beta
|
||||
maturity: Released
|
||||
---
|
||||
|
||||

|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
layout: project
|
||||
title: Try Matrix Now!
|
||||
categories: projects client
|
||||
---
|
||||
|
||||
<html>
|
||||
|
|
|
@ -5,7 +5,7 @@ categories: projects client
|
|||
thumbnail: /docs/projects/images/vector-android-small.png
|
||||
description: Riot is a glossy client with an emphasis on performance and usability
|
||||
author: Riot.im
|
||||
maturity: Beta
|
||||
maturity: Released
|
||||
---
|
||||
|
||||

|
||||
|
@ -13,6 +13,6 @@ maturity: Beta
|
|||
# {{ page.title }}
|
||||
The Android version of the [Riot](https://matrix.org/docs/projects/client/riot.html) web client. Riot is a glossy client with focus on performance and usability.
|
||||
|
||||
The code is available from [github](https://github.com/vector-im/vector-android), and the app is available from the [Google Play store](https://play.google.com/store/apps/details?id=im.riot) and (as "Vector") [F-Droid](https://f-droid.org/repository/browse/?fdfilter=vector&fdid=im.vector.alpha).
|
||||
The code is available from [github](https://github.com/vector-im/vector-android), and the app is available from the [Google Play store](https://play.google.com/store/apps/details?id=im.vector.alpha) and [F-Droid](https://f-droid.org/repository/browse/?fdfilter=vector&fdid=im.vector.alpha).
|
||||
|
||||
If you want to help test the app, you can download development versions from [Jenkins](https://matrix.org/jenkins/job/VectorAndroidDevelop/).
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
layout: project
|
||||
title: Try Matrix Now!
|
||||
categories: projects client
|
||||
---
|
||||
|
||||
<html>
|
||||
|
|
13
supporting-docs/projects/2015-11-28-matrixtool.md
Normal file
13
supporting-docs/projects/2015-11-28-matrixtool.md
Normal file
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
layout: project
|
||||
title: MatrixTool
|
||||
categories: projects other
|
||||
description: Commands to interact with a Matrix homeserver
|
||||
author: LeoNerd
|
||||
maturity: Alpha
|
||||
---
|
||||
# {{ page.title }}
|
||||
|
||||
The tool provides a wrapper around a number of sub-commands that provide useful interactions with a Matrix homeserver.
|
||||
|
||||
You can grab it from [CPAN](http://search.cpan.org/~pevans/App-MatrixTool/).
|
|
@ -1,7 +1,6 @@
|
|||
---
|
||||
layout: project
|
||||
title: Vector Desktop
|
||||
categories: projects client
|
||||
description: Desktop version of Vector
|
||||
author: Steven Hammerton
|
||||
maturity: Alpha
|
||||
|
|
12
supporting-docs/projects/2016-09-13-telematrix.md
Normal file
12
supporting-docs/projects/2016-09-13-telematrix.md
Normal file
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
layout: project
|
||||
title: telematrix
|
||||
categories: projects as
|
||||
author: SijmenSchoon
|
||||
maturity: Alpha
|
||||
---
|
||||
|
||||
# {{ page.title }}
|
||||
This project bridges [Telegram Messenger](https://telegram.org/) to Matrix. It's currently in early development, and not considered to be in a usable state yet.
|
||||
|
||||
Get it and report issues at [github](https://github.com/SijmenSchoon/telematrix)!
|
|
@ -96,8 +96,7 @@ def inherit_parents(obj):
|
|||
return result
|
||||
|
||||
|
||||
def get_json_schema_object_fields(obj, enforce_title=False,
|
||||
mark_required=True):
|
||||
def get_json_schema_object_fields(obj, enforce_title=False):
|
||||
# Algorithm:
|
||||
# f.e. property => add field info (if field is object then recurse)
|
||||
if obj.get("type") != "object":
|
||||
|
@ -175,8 +174,7 @@ def get_json_schema_object_fields(obj, enforce_title=False,
|
|||
try:
|
||||
logger.debug("Processing property %s.%s", obj_title, key_name)
|
||||
required = key_name in required_keys
|
||||
res = process_prop(key_name, props[key_name], required,
|
||||
mark_required)
|
||||
res = process_prop(key_name, props[key_name], required)
|
||||
|
||||
first_table_rows.append(res["row"])
|
||||
tables.extend(res["tables"])
|
||||
|
@ -196,7 +194,7 @@ def get_json_schema_object_fields(obj, enforce_title=False,
|
|||
|
||||
return tables
|
||||
|
||||
def process_prop(key_name, prop, required, mark_required):
|
||||
def process_prop(key_name, prop, required):
|
||||
prop = inherit_parents(prop)
|
||||
|
||||
value_type = None
|
||||
|
@ -213,7 +211,6 @@ def process_prop(key_name, prop, required, mark_required):
|
|||
nested_objects = get_json_schema_object_fields(
|
||||
prop,
|
||||
enforce_title=True,
|
||||
mark_required=mark_required,
|
||||
)
|
||||
value_type = nested_objects[0]["title"]
|
||||
value_id = value_type
|
||||
|
@ -226,7 +223,6 @@ def process_prop(key_name, prop, required, mark_required):
|
|||
nested_objects = get_json_schema_object_fields(
|
||||
items,
|
||||
enforce_title=True,
|
||||
mark_required=mark_required,
|
||||
)
|
||||
value_id = nested_objects[0]["title"]
|
||||
value_type = "[%s]" % value_id
|
||||
|
@ -269,7 +265,7 @@ def process_prop(key_name, prop, required, mark_required):
|
|||
value_type = " or ".join(value_type)
|
||||
|
||||
|
||||
if required and mark_required:
|
||||
if required:
|
||||
desc = "**Required.** " + desc
|
||||
|
||||
return {
|
||||
|
@ -284,10 +280,9 @@ def process_prop(key_name, prop, required, mark_required):
|
|||
}
|
||||
|
||||
|
||||
def get_tables_for_schema(schema, mark_required=True):
|
||||
def get_tables_for_schema(schema):
|
||||
schema = inherit_parents(schema)
|
||||
tables = get_json_schema_object_fields(schema,
|
||||
mark_required=mark_required)
|
||||
tables = get_json_schema_object_fields(schema)
|
||||
|
||||
# the result may contain duplicates, if objects are referred to more than
|
||||
# once. Filter them out.
|
||||
|
@ -470,9 +465,7 @@ class MatrixUnits(Units):
|
|||
elif res_type and Units.prop(good_response, "schema/properties"):
|
||||
# response is an object:
|
||||
schema = good_response["schema"]
|
||||
res_tables = get_tables_for_schema(schema,
|
||||
mark_required=False,
|
||||
)
|
||||
res_tables = get_tables_for_schema(schema)
|
||||
endpoint["res_tables"].extend(res_tables)
|
||||
elif res_type and Units.prop(good_response, "schema/items"):
|
||||
# response is an array:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue