diff --git a/api/client-server/create_room.yaml b/api/client-server/create_room.yaml index 9107e185..a321b0f7 100644 --- a/api/client-server/create_room.yaml +++ b/api/client-server/create_room.yaml @@ -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. diff --git a/api/client-server/definitions/room_event_filter.yaml b/api/client-server/definitions/room_event_filter.yaml index a3bb6852..7d9184b5 100644 --- a/api/client-server/definitions/room_event_filter.yaml +++ b/api/client-server/definitions/room_event_filter.yaml @@ -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 diff --git a/api/client-server/definitions/security.yaml b/api/client-server/definitions/security.yaml index 0668eb95..bb78f0e3 100644 --- a/api/client-server/definitions/security.yaml +++ b/api/client-server/definitions/security.yaml @@ -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 diff --git a/api/client-server/login.yaml b/api/client-server/login.yaml index 3ca397ea..7731f507 100644 --- a/api/client-server/login.yaml +++ b/api/client-server/login.yaml @@ -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 diff --git a/api/client-server/message_pagination.yaml b/api/client-server/message_pagination.yaml index 853e0ec3..005b8fb3 100644 --- a/api/client-server/message_pagination.yaml +++ b/api/client-server/message_pagination.yaml @@ -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. diff --git a/api/client-server/notifications.yaml b/api/client-server/notifications.yaml new file mode 100644 index 00000000..8a5e9553 --- /dev/null +++ b/api/client-server/notifications.yaml @@ -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 diff --git a/api/client-server/registration.yaml b/api/client-server/registration.yaml index 6da04d45..8145824e 100644 --- a/api/client-server/registration.yaml +++ b/api/client-server/registration.yaml @@ -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. diff --git a/api/client-server/rooms.yaml b/api/client-server/rooms.yaml index 5cbd144f..0bb268dd 100644 --- a/api/client-server/rooms.yaml +++ b/api/client-server/rooms.yaml @@ -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: |- diff --git a/api/client-server/sync.yaml b/api/client-server/sync.yaml index 8bfdd48a..66f7d935 100644 --- a/api/client-server/sync.yaml +++ b/api/client-server/sync.yaml @@ -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: |- { diff --git a/api/client-server/to_device.yaml b/api/client-server/to_device.yaml new file mode 100644 index 00000000..16af1182 --- /dev/null +++ b/api/client-server/to_device.yaml @@ -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 diff --git a/api/identity/lookup.yaml b/api/identity/lookup.yaml index c02ec3b5..83c3b661 100644 --- a/api/identity/lookup.yaml +++ b/api/identity/lookup.yaml @@ -19,7 +19,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/v1/api +basePath: /_matrix/identity/api/v1 produces: - application/json paths: diff --git a/api/identity/pubkey.yaml b/api/identity/pubkey.yaml index c8101281..40d2a237 100644 --- a/api/identity/pubkey.yaml +++ b/api/identity/pubkey.yaml @@ -19,7 +19,7 @@ host: localhost:8090 schemes: - https - http -basePath: /_matrix/identity/v1/api +basePath: /_matrix/identity/api/v1 produces: - application/json paths: diff --git a/changelogs/client_server.rst b/changelogs/client_server.rst index 33cc8c73..9abfe4fe 100644 --- a/changelogs/client_server.rst +++ b/changelogs/client_server.rst @@ -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 `_). - - Emphasise that ``POST /tokenrefresh`` should expire the access token - (`#363 `_). - - Clarify the fields which are applicable to different types of push rule - (`#365 `_). - - A number of clarifications to authentication - (`#371 `_). - - Correct references to ``user_id`` which should have been ``sender`` - (`#376 `_). - - Correct inconsistent specification of ``redacted_because`` fields and their - values (`#378 `_). + (`#373 `_). + - Remove ``/tokenrefresh`` from the API. + (`#395 `_). + - Remove requirement that tokens used in token-based login be macaroons. + (`#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 `_). + - Add ``is_direct`` flag to |/createRoom|_ and invite member event. + Add 'Direct Messaging' module. + (`#389 `_). + - Add ``contains_url`` option to ``RoomEventFilter``. + (`#390 `_). + - Add ``filter`` optional query param to ``/messages`` + (`#390 `_). + - Add "Send-to-Device messaging" module + (`#386 `_). + - Require that User-Interactive auth fallback pages call + ``window.postMessage`` to notify apps of completion + (`#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 `_). +- Spec clarifications: + + - Spell out the way that state is handled by ``POST /createRoom`` + (`#362 `_). + - Clarify the fields which are applicable to different types of push rule + (`#365 `_). + - A number of clarifications to authentication + (`#371 `_). + - Correct references to ``user_id`` which should have been ``sender`` + (`#376 `_). + - Correct inconsistent specification of ``redacted_because`` fields and their + values (`#378 `_). + - Mark required fields in response objects as such + (`#394 `_). + r0.2.0 ====== diff --git a/event-schemas/examples/m.direct b/event-schemas/examples/m.direct new file mode 100644 index 00000000..92f13daa --- /dev/null +++ b/event-schemas/examples/m.direct @@ -0,0 +1,9 @@ +{ + "type": "m.direct", + "content": { + "@bob:example.com": [ + "!abcdefgh:example.com", + "!hgfedcba:example.com" + ] + } +} diff --git a/event-schemas/schema/m.direct b/event-schemas/schema/m.direct new file mode 100644 index 00000000..b8a9cfc2 --- /dev/null +++ b/event-schemas/schema/m.direct @@ -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 diff --git a/event-schemas/schema/m.room.member b/event-schemas/schema/m.room.member index f9aa5051..4f4077a7 100644 --- a/event-schemas/schema/m.room.member +++ b/event-schemas/schema/m.room.member @@ -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: diff --git a/scripts/speculator/main.go b/scripts/speculator/main.go index b433a327..87ee4bf6 100644 --- a/scripts/speculator/main.go +++ b/scripts/speculator/main.go @@ -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 := "
    " - for _, pull := range pulls { - s += fmt.Sprintf(`
  • %d: %s: %s: spec spec diff rst diff
  • `, - pull.Number, pull.User.HTMLURL, pull.User.Login, pull.HTMLURL, pull.Title, pull.Number, pull.Number, pull.Number) - } - s += "
" branches, err := srv.getBranches() if err != nil { @@ -601,7 +613,48 @@ func (srv *server) makeIndex(w http.ResponseWriter, req *http.Request) { return } - s += `
View the spec at:
    ` + // 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(` + + + +
      +`)) + + tmpl, err := template.New("pr entry").Parse(` +
    • {{.Number}}: + {{.User.Login}}: + {{.Title}}: + spec + api docs + spec diff + rst diff +
    • +`) + 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(` +
    +
    View the spec at:
      +`)) 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(`
    • %s
    • `, href, branch) + fmt.Fprintf(&b, `
    • %s
    • `, href, branch) if *includesDir != "" { - s += fmt.Sprintf(`
    • %s, styled like matrix.org
    • `, + fmt.Fprintf(&b, `
    • %s, styled like matrix.org
    • `, href, branch) } } - s += "
    " - - io.WriteString(w, s) + b.Write([]byte("
")) + 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 +} diff --git a/specification/client_server_api.rst b/specification/client_server_api.rst index a74129b5..d95164c5 100644 --- a/specification/client_server_api.rst +++ b/specification/client_server_api.rst @@ -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 `_. + 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": "", - "password": "" + "password": "", + "session": "" } Alternatively reply using a 3pid bound to the user's account on the homeserver @@ -402,18 +442,13 @@ follows: "type": "m.login.password", "medium": "", "address": "", - "password": "" + "password": "", + "session": "" } 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": "" + "response": "", + "session": "" } Token-based @@ -444,7 +480,8 @@ To use this authentication type, clients should submit an auth dict as follows: { "type": "m.login.token", "token": "", - "txn_id": "" + "txn_id": "", + "session": "" } 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": "", "id_server": "" } - ] + ], + "session": "" } Dummy Auth @@ -529,12 +567,13 @@ the type and session, if provided: .. code:: json { - "type": "m.login.dummy" + "type": "m.login.dummy", + "session": "" } 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//fallback/web?session= 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 `_ 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": "" + } + + +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": "" } -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//initialSync| replace:: ``/rooms//initialSync`` .. _/rooms//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//state| replace:: ``/rooms//state`` .. _/rooms//state: #get-matrix-client-%CLIENT_MAJOR_VERSION%-rooms-roomid-state +.. |/rooms//send| replace:: ``/rooms//send`` +.. _/rooms//send: #put-matrix-client-%CLIENT_MAJOR_VERSION%-rooms-roomid-send-eventtype-txnid + .. |/rooms//invite| replace:: ``/rooms//invite`` .. _/rooms//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//account_data/| replace:: ``/user//account_data/`` +.. _/user//account_data/: #put-matrix-client-%CLIENT_MAJOR_VERSION%-user-userid-account-data-type diff --git a/specification/identity_service_api.rst b/specification/identity_service_api.rst index f6e22a1a..3be9d9eb 100644 --- a/specification/identity_service_api.rst +++ b/specification/identity_service_api.rst @@ -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 ---------------------------- diff --git a/specification/modules/dm.rst b/specification/modules/dm.rst new file mode 100644 index 00000000..a89d3522 --- /dev/null +++ b/specification/modules/dm.rst @@ -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//account_data/|_. + +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. diff --git a/specification/modules/push.rst b/specification/modules/push.rst index ba98ea44..58c816b3 100644 --- a/specification/modules/push.rst +++ b/specification/modules/push.rst @@ -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 diff --git a/specification/modules/send_to_device.rst b/specification/modules/send_to_device.rst new file mode 100644 index 00000000..dd85a992 --- /dev/null +++ b/specification/modules/send_to_device.rst @@ -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//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 diff --git a/specification/server_server_api.rst b/specification/server_server_api.rst index 5c8a456a..5d7f2b17 100644 --- a/specification/server_server_api.rst +++ b/specification/server_server_api.rst @@ -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. diff --git a/specification/targets.yaml b/specification/targets.yaml index 6cbfa917..a157366f 100644 --- a/specification/targets.yaml +++ b/specification/targets.yaml @@ -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: ["=", "-", "~", "+", "^", "`", "@", ":"] diff --git a/supporting-docs/projects/2014-06-09-riot.md b/supporting-docs/projects/2014-06-09-riot.md index b5c2d4e3..80a9172c 100644 --- a/supporting-docs/projects/2014-06-09-riot.md +++ b/supporting-docs/projects/2014-06-09-riot.md @@ -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 --- ![screenshot](https://matrix.org/blog/wp-content/uploads/2015/08/vector030216-1080x745.png "{{ page.title }}") diff --git a/supporting-docs/projects/2014-06-09-vector.md b/supporting-docs/projects/2014-06-09-vector.md index 3f49be69..4f0ea2f5 100644 --- a/supporting-docs/projects/2014-06-09-vector.md +++ b/supporting-docs/projects/2014-06-09-vector.md @@ -1,7 +1,6 @@ --- layout: project title: Try Matrix Now! -categories: projects client --- diff --git a/supporting-docs/projects/2015-04-02-riot-ios.md b/supporting-docs/projects/2015-04-02-riot-ios.md index 555601a1..e9dcb3b9 100644 --- a/supporting-docs/projects/2015-04-02-riot-ios.md +++ b/supporting-docs/projects/2015-04-02-riot-ios.md @@ -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 --- ![screenshot](/docs/projects/images/vector-iOS-large.png "{{ page.title }}") diff --git a/supporting-docs/projects/2015-04-03-vector-ios.md b/supporting-docs/projects/2015-04-03-vector-ios.md index 2d295483..11fc618e 100644 --- a/supporting-docs/projects/2015-04-03-vector-ios.md +++ b/supporting-docs/projects/2015-04-03-vector-ios.md @@ -1,7 +1,6 @@ --- layout: project title: Try Matrix Now! -categories: projects client --- diff --git a/supporting-docs/projects/2015-06-02-riot-android.md b/supporting-docs/projects/2015-06-02-riot-android.md index a23e0afd..cedf4454 100644 --- a/supporting-docs/projects/2015-06-02-riot-android.md +++ b/supporting-docs/projects/2015-06-02-riot-android.md @@ -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 --- ![screenshot](/docs/projects/images/vector-android-large.png "{{ page.title }}") @@ -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/). diff --git a/supporting-docs/projects/2015-06-02-vector-android.md b/supporting-docs/projects/2015-06-02-vector-android.md index 0af7c7b1..9d4e585e 100644 --- a/supporting-docs/projects/2015-06-02-vector-android.md +++ b/supporting-docs/projects/2015-06-02-vector-android.md @@ -1,7 +1,6 @@ --- layout: project title: Try Matrix Now! -categories: projects client --- diff --git a/supporting-docs/projects/2015-11-28-matrixtool.md b/supporting-docs/projects/2015-11-28-matrixtool.md new file mode 100644 index 00000000..8acc0df7 --- /dev/null +++ b/supporting-docs/projects/2015-11-28-matrixtool.md @@ -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/). diff --git a/supporting-docs/projects/2016-02-06-vector-desktop.md b/supporting-docs/projects/2016-02-06-vector-desktop.md index f6664f81..7355ccfc 100644 --- a/supporting-docs/projects/2016-02-06-vector-desktop.md +++ b/supporting-docs/projects/2016-02-06-vector-desktop.md @@ -1,7 +1,6 @@ --- layout: project title: Vector Desktop -categories: projects client description: Desktop version of Vector author: Steven Hammerton maturity: Alpha diff --git a/supporting-docs/projects/2016-09-13-telematrix.md b/supporting-docs/projects/2016-09-13-telematrix.md new file mode 100644 index 00000000..29c46554 --- /dev/null +++ b/supporting-docs/projects/2016-09-13-telematrix.md @@ -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)! diff --git a/templating/matrix_templates/units.py b/templating/matrix_templates/units.py index ee5b40a6..f362f63d 100644 --- a/templating/matrix_templates/units.py +++ b/templating/matrix_templates/units.py @@ -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: