mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-12 09:23:09 -06:00
Merge remote-tracking branch 'origin/master' into markjh/depth
This commit is contained in:
commit
8351e1695c
|
|
@ -85,6 +85,12 @@ func WeakPassword(msg string) *MatrixError {
|
||||||
return &MatrixError{"M_WEAK_PASSWORD", msg}
|
return &MatrixError{"M_WEAK_PASSWORD", msg}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GuestAccessForbidden is an error which is returned when the client is
|
||||||
|
// forbidden from accessing a resource as a guest.
|
||||||
|
func GuestAccessForbidden(msg string) *MatrixError {
|
||||||
|
return &MatrixError{"M_GUEST_ACCESS_FORBIDDEN", msg}
|
||||||
|
}
|
||||||
|
|
||||||
// LimitExceededError is a rate-limiting error.
|
// LimitExceededError is a rate-limiting error.
|
||||||
type LimitExceededError struct {
|
type LimitExceededError struct {
|
||||||
MatrixError
|
MatrixError
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,87 @@
|
||||||
|
// Copyright 2017 Vector Creations 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.
|
||||||
|
|
||||||
|
package readers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||||
|
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||||
|
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||||
|
"github.com/matrix-org/dendrite/common/config"
|
||||||
|
"github.com/matrix-org/gomatrix"
|
||||||
|
"github.com/matrix-org/gomatrixserverlib"
|
||||||
|
"github.com/matrix-org/util"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DirectoryRoom looks up a room alias
|
||||||
|
func DirectoryRoom(
|
||||||
|
req *http.Request,
|
||||||
|
device *authtypes.Device,
|
||||||
|
roomAlias string,
|
||||||
|
federation *gomatrixserverlib.FederationClient,
|
||||||
|
cfg *config.Dendrite,
|
||||||
|
) util.JSONResponse {
|
||||||
|
domain, err := domainFromID(roomAlias)
|
||||||
|
if err != nil {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: 400,
|
||||||
|
JSON: jsonerror.BadJSON("Room alias must be in the form '#localpart:domain'"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if domain == cfg.Matrix.ServerName {
|
||||||
|
// TODO: Implement lookup up local room aliases.
|
||||||
|
panic(fmt.Errorf("Looking up local room aliases is not implemented"))
|
||||||
|
} else {
|
||||||
|
resp, err := federation.LookupRoomAlias(domain, roomAlias)
|
||||||
|
if err != nil {
|
||||||
|
switch x := err.(type) {
|
||||||
|
case gomatrix.HTTPError:
|
||||||
|
if x.Code == 404 {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: 404,
|
||||||
|
JSON: jsonerror.NotFound("Room alias not found"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: Return 502 if the remote server errored.
|
||||||
|
// TODO: Return 504 if the remote server timed out.
|
||||||
|
return httputil.LogThenError(req, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: 200,
|
||||||
|
JSON: resp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// domainFromID returns everything after the first ":" character to extract
|
||||||
|
// the domain part of a matrix ID.
|
||||||
|
// TODO: duplicated from gomatrixserverlib.
|
||||||
|
func domainFromID(id string) (gomatrixserverlib.ServerName, error) {
|
||||||
|
// IDs have the format: SIGIL LOCALPART ":" DOMAIN
|
||||||
|
// Split on the first ":" character since the domain can contain ":"
|
||||||
|
// characters.
|
||||||
|
parts := strings.SplitN(id, ":", 2)
|
||||||
|
if len(parts) != 2 {
|
||||||
|
// The ID must have a ":" character.
|
||||||
|
return "", fmt.Errorf("invalid ID: %q", id)
|
||||||
|
}
|
||||||
|
// Return everything after the first ":" character.
|
||||||
|
return gomatrixserverlib.ServerName(parts[1]), nil
|
||||||
|
}
|
||||||
|
|
@ -22,6 +22,7 @@ import (
|
||||||
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
"github.com/matrix-org/dendrite/clientapi/auth/authtypes"
|
||||||
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
|
"github.com/matrix-org/dendrite/clientapi/auth/storage/accounts"
|
||||||
"github.com/matrix-org/dendrite/clientapi/auth/storage/devices"
|
"github.com/matrix-org/dendrite/clientapi/auth/storage/devices"
|
||||||
|
"github.com/matrix-org/dendrite/clientapi/jsonerror"
|
||||||
"github.com/matrix-org/dendrite/clientapi/producers"
|
"github.com/matrix-org/dendrite/clientapi/producers"
|
||||||
"github.com/matrix-org/dendrite/clientapi/readers"
|
"github.com/matrix-org/dendrite/clientapi/readers"
|
||||||
"github.com/matrix-org/dendrite/clientapi/writers"
|
"github.com/matrix-org/dendrite/clientapi/writers"
|
||||||
|
|
@ -34,6 +35,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const pathPrefixR0 = "/_matrix/client/r0"
|
const pathPrefixR0 = "/_matrix/client/r0"
|
||||||
|
const pathPrefixUnstable = "/_matrix/client/unstable"
|
||||||
|
|
||||||
// Setup registers HTTP handlers with the given ServeMux. It also supplies the given http.Client
|
// Setup registers HTTP handlers with the given ServeMux. It also supplies the given http.Client
|
||||||
// to clients which need to make outbound HTTP requests.
|
// to clients which need to make outbound HTTP requests.
|
||||||
|
|
@ -46,7 +48,25 @@ func Setup(
|
||||||
keyRing gomatrixserverlib.KeyRing,
|
keyRing gomatrixserverlib.KeyRing,
|
||||||
) {
|
) {
|
||||||
apiMux := mux.NewRouter()
|
apiMux := mux.NewRouter()
|
||||||
|
|
||||||
|
apiMux.Handle("/_matrix/client/versions",
|
||||||
|
common.MakeAPI("versions", func(req *http.Request) util.JSONResponse {
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: 200,
|
||||||
|
JSON: struct {
|
||||||
|
Versions []string `json:"versions"`
|
||||||
|
}{[]string{
|
||||||
|
"r0.0.1",
|
||||||
|
"r0.1.0",
|
||||||
|
"r0.2.0",
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
r0mux := apiMux.PathPrefix(pathPrefixR0).Subrouter()
|
r0mux := apiMux.PathPrefix(pathPrefixR0).Subrouter()
|
||||||
|
unstableMux := apiMux.PathPrefix(pathPrefixUnstable).Subrouter()
|
||||||
|
|
||||||
r0mux.Handle("/createRoom",
|
r0mux.Handle("/createRoom",
|
||||||
common.MakeAuthAPI("createRoom", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
common.MakeAuthAPI("createRoom", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||||
return writers.CreateRoom(req, device, cfg, producer)
|
return writers.CreateRoom(req, device, cfg, producer)
|
||||||
|
|
@ -85,6 +105,13 @@ func Setup(
|
||||||
return writers.Register(req, accountDB, deviceDB)
|
return writers.Register(req, accountDB, deviceDB)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
r0mux.Handle("/directory/room/{roomAlias}",
|
||||||
|
common.MakeAuthAPI("directory_room", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
|
||||||
|
vars := mux.Vars(req)
|
||||||
|
return readers.DirectoryRoom(req, device, vars["roomAlias"], federation, &cfg)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
// Stub endpoints required by Riot
|
// Stub endpoints required by Riot
|
||||||
|
|
||||||
r0mux.Handle("/login",
|
r0mux.Handle("/login",
|
||||||
|
|
@ -166,6 +193,78 @@ func Setup(
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
r0mux.Handle("/voip/turnServer",
|
||||||
|
common.MakeAPI("turn_server", func(req *http.Request) util.JSONResponse {
|
||||||
|
// TODO: Return credentials for a turn server if one is configured.
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: 200,
|
||||||
|
JSON: struct{}{},
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
r0mux.Handle("/publicRooms",
|
||||||
|
common.MakeAPI("public_rooms", func(req *http.Request) util.JSONResponse {
|
||||||
|
// TODO: Return a list of public rooms
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: 200,
|
||||||
|
JSON: struct {
|
||||||
|
Chunk []struct{} `json:"chunk"`
|
||||||
|
Start string `json:"start"`
|
||||||
|
End string `json:"end"`
|
||||||
|
}{[]struct{}{}, "", ""},
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
unstableMux.Handle("/thirdparty/protocols",
|
||||||
|
common.MakeAPI("thirdparty_protocols", func(req *http.Request) util.JSONResponse {
|
||||||
|
// TODO: Return the third party protcols
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: 200,
|
||||||
|
JSON: struct{}{},
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
r0mux.Handle("/rooms/{roomID}/initialSync",
|
||||||
|
common.MakeAPI("rooms_initial_sync", func(req *http.Request) util.JSONResponse {
|
||||||
|
// TODO: Allow people to peek into rooms.
|
||||||
|
return util.JSONResponse{
|
||||||
|
Code: 403,
|
||||||
|
JSON: jsonerror.GuestAccessForbidden("Guest access not implemented"),
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
r0mux.Handle("/profile/{userID}/displayname",
|
||||||
|
common.MakeAPI("profile_displayname", func(req *http.Request) util.JSONResponse {
|
||||||
|
// TODO: Set and get the displayname
|
||||||
|
return util.JSONResponse{Code: 200, JSON: struct{}{}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
r0mux.Handle("/user/{userID}/account_data/{type}",
|
||||||
|
common.MakeAPI("user_account_data", func(req *http.Request) util.JSONResponse {
|
||||||
|
// TODO: Set and get the account_data
|
||||||
|
return util.JSONResponse{Code: 200, JSON: struct{}{}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
r0mux.Handle("/rooms/{roomID}/read_markers",
|
||||||
|
common.MakeAPI("rooms_read_markers", func(req *http.Request) util.JSONResponse {
|
||||||
|
// TODO: return the read_markers.
|
||||||
|
return util.JSONResponse{Code: 200, JSON: struct{}{}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
|
r0mux.Handle("/rooms/{roomID}/typing/{userID}",
|
||||||
|
common.MakeAPI("rooms_typing", func(req *http.Request) util.JSONResponse {
|
||||||
|
// TODO: handling typing
|
||||||
|
return util.JSONResponse{Code: 200, JSON: struct{}{}}
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
servMux.Handle("/metrics", prometheus.Handler())
|
servMux.Handle("/metrics", prometheus.Handler())
|
||||||
servMux.Handle("/api/", http.StripPrefix("/api", apiMux))
|
servMux.Handle("/api/", http.StripPrefix("/api", apiMux))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ func main() {
|
||||||
|
|
||||||
if *syncServerURL == "" {
|
if *syncServerURL == "" {
|
||||||
flag.Usage()
|
flag.Usage()
|
||||||
fmt.Fprintln(os.Stderr, "no --sync-server-url specified.")
|
fmt.Fprintln(os.Stderr, "no --sync-api-server-url specified.")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ var (
|
||||||
func main() {
|
func main() {
|
||||||
common.SetupLogging(logDir)
|
common.SetupLogging(logDir)
|
||||||
|
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
if *configPath == "" {
|
if *configPath == "" {
|
||||||
log.Fatal("--config must be supplied")
|
log.Fatal("--config must be supplied")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,14 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// An OutputRoomEvent is written when the roomserver receives a new event.
|
// An OutputRoomEvent is written when the roomserver receives a new event.
|
||||||
|
// It contains the full matrix room event and enough information for a
|
||||||
|
// consumer to construct the current state of the room and the state before the
|
||||||
|
// event.
|
||||||
|
//
|
||||||
|
// When we talk about state in a matrix room we are talking about the state
|
||||||
|
// after a list of events. The current state is the state after the latest
|
||||||
|
// event IDs in the room. The state before an event is the state after its
|
||||||
|
// prev_events.
|
||||||
type OutputRoomEvent struct {
|
type OutputRoomEvent struct {
|
||||||
// The JSON bytes of the event.
|
// The JSON bytes of the event.
|
||||||
Event []byte
|
Event []byte
|
||||||
|
|
@ -37,19 +45,42 @@ type OutputRoomEvent struct {
|
||||||
// This is used by consumers to check if they can safely update their
|
// This is used by consumers to check if they can safely update their
|
||||||
// current state using the delta supplied in AddsStateEventIDs and
|
// current state using the delta supplied in AddsStateEventIDs and
|
||||||
// RemovesStateEventIDs.
|
// RemovesStateEventIDs.
|
||||||
|
//
|
||||||
// If the LastSentEventID doesn't match what they were expecting it to be
|
// If the LastSentEventID doesn't match what they were expecting it to be
|
||||||
// they can use the LatestEventIDs to request the full current state.
|
// they can use the LatestEventIDs to request the full current state.
|
||||||
LastSentEventID string
|
LastSentEventID string
|
||||||
// The state event IDs that are part of the state at the event, but not
|
// The state event IDs that are part of the state at the event, but not
|
||||||
// part of the current state. Together with the StateBeforeRemovesEventIDs
|
// part of the current state. Together with the StateBeforeRemovesEventIDs
|
||||||
// this can be used to construct the state before the event from the
|
// this can be used to construct the state before the event from the
|
||||||
// current state.
|
// current state. The StateBeforeAddsEventIDs and StateBeforeRemovesEventIDs
|
||||||
|
// delta is applied after the AddsStateEventIDs and RemovesStateEventIDs.
|
||||||
|
//
|
||||||
|
// Consumers need to know the state at each event in order to determine
|
||||||
|
// which users and servers are allowed to see the event. This information
|
||||||
|
// is needed to apply the history visibility rules and to tell which
|
||||||
|
// servers we need to push events to over federation.
|
||||||
|
//
|
||||||
|
// The state is given as a delta against the current state because they are
|
||||||
|
// usually either the same state, or differ by just a couple of events.
|
||||||
StateBeforeAddsEventIDs []string
|
StateBeforeAddsEventIDs []string
|
||||||
// The state event IDs that are part of the current state, but not part
|
// The state event IDs that are part of the current state, but not part
|
||||||
// of the state at the event.
|
// of the state at the event.
|
||||||
StateBeforeRemovesEventIDs []string
|
StateBeforeRemovesEventIDs []string
|
||||||
// The server name to use to push this event to other servers.
|
// The server name to use to push this event to other servers.
|
||||||
// Or empty if this event shouldn't be pushed to other servers.
|
// Or empty if this event shouldn't be pushed to other servers.
|
||||||
|
//
|
||||||
|
// This is used by the federation sender component. We need to tell it what
|
||||||
|
// event is needs to send because it can't tell on its own. Normally we
|
||||||
|
// if an event was created on this server then we are responsible for
|
||||||
|
// sending. However there are a couple of exceptions. The first is that
|
||||||
|
// when the server joins a remote room through another matrix server, it
|
||||||
|
// is the job of the other matrix server to send the event over federation.
|
||||||
|
// The second is the reverse of the first, that is when a remote server
|
||||||
|
// joins a room that we are in over federation using our server it is our
|
||||||
|
// responsibility to send the join event to other matrix server.
|
||||||
|
//
|
||||||
|
// We encode the server name that the event should be sent using here to
|
||||||
|
// future proof the API for virtual hosting.
|
||||||
SendAsServer string
|
SendAsServer string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,6 @@ func writeEvent(
|
||||||
ore.StateBeforeAddsEventIDs = append(ore.StateBeforeAddsEventIDs, eventIDMap[entry.EventNID])
|
ore.StateBeforeAddsEventIDs = append(ore.StateBeforeAddsEventIDs, eventIDMap[entry.EventNID])
|
||||||
}
|
}
|
||||||
ore.SendAsServer = sendAsServer
|
ore.SendAsServer = sendAsServer
|
||||||
// TODO: Fill out VisibilityStateIDs
|
|
||||||
return ow.WriteOutputRoomEvent(ore)
|
return ow.WriteOutputRoomEvent(ore)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue