Merge branch 'master' into add-nats-support

This commit is contained in:
Neil Alexander 2021-11-02 17:36:22 +00:00
commit 73d6964fb4
No known key found for this signature in database
GPG key ID: A02A2019A2BB0944
205 changed files with 5074 additions and 1217 deletions

View file

@ -52,7 +52,7 @@ func (t *LoginTypePassword) Login(ctx context.Context, req interface{}) (*Login,
if username == "" {
return nil, &util.JSONResponse{
Code: http.StatusUnauthorized,
JSON: jsonerror.BadJSON("'user' must be supplied."),
JSON: jsonerror.BadJSON("A username must be supplied."),
}
}
localpart, err := userutil.ParseUsernameParam(username, &t.Config.Matrix.ServerName)
@ -68,7 +68,7 @@ func (t *LoginTypePassword) Login(ctx context.Context, req interface{}) (*Login,
// but that would leak the existence of the user.
return nil, &util.JSONResponse{
Code: http.StatusForbidden,
JSON: jsonerror.Forbidden("username or password was incorrect, or the account does not exist"),
JSON: jsonerror.Forbidden("The username or password was incorrect or the account does not exist."),
}
}
return &r.Login, nil

View file

@ -220,7 +220,7 @@ func (u *UserInteractive) Verify(ctx context.Context, bodyBytes []byte, device *
if !ok {
return nil, &util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.BadJSON("unknown auth.type: " + authType),
JSON: jsonerror.BadJSON("Unknown auth.type: " + authType),
}
}
@ -231,7 +231,7 @@ func (u *UserInteractive) Verify(ctx context.Context, bodyBytes []byte, device *
if !u.IsSingleStageFlow(authType) {
return nil, &util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.Unknown("missing or unknown auth.session"),
JSON: jsonerror.Unknown("The auth.session is missing or unknown."),
}
}
}

View file

@ -32,7 +32,7 @@ func ParseTSParam(req *http.Request) (time.Time, error) {
// The parameter exists, parse into a Time object
ts, err := strconv.ParseInt(tsStr, 10, 64)
if err != nil {
return time.Time{}, fmt.Errorf("Param 'ts' is no valid int (%s)", err.Error())
return time.Time{}, fmt.Errorf("param 'ts' is no valid int (%s)", err.Error())
}
return time.Unix(ts/1000, 0), nil

View file

@ -111,6 +111,12 @@ func UserInUse(msg string) *MatrixError {
return &MatrixError{"M_USER_IN_USE", msg}
}
// RoomInUse is an error returned when the client tries to make a room
// that already exists
func RoomInUse(msg string) *MatrixError {
return &MatrixError{"M_ROOM_IN_USE", msg}
}
// ASExclusive is an error returned when an application service tries to
// register an username that is outside of its registered namespace, or if a
// user attempts to register a username or room alias within an exclusive
@ -125,6 +131,24 @@ func GuestAccessForbidden(msg string) *MatrixError {
return &MatrixError{"M_GUEST_ACCESS_FORBIDDEN", msg}
}
// InvalidSignature is an error which is returned when the client tries
// to upload invalid signatures.
func InvalidSignature(msg string) *MatrixError {
return &MatrixError{"M_INVALID_SIGNATURE", msg}
}
// InvalidParam is an error that is returned when a parameter was invalid,
// traditionally with cross-signing.
func InvalidParam(msg string) *MatrixError {
return &MatrixError{"M_INVALID_PARAM", msg}
}
// MissingParam is an error that is returned when a parameter was incorrect,
// traditionally with cross-signing.
func MissingParam(msg string) *MatrixError {
return &MatrixError{"M_MISSING_PARAM", msg}
}
type IncompatibleRoomVersionError struct {
RoomVersion string `json:"room_version"`
Error string `json:"error"`

View file

@ -325,7 +325,10 @@ func createRoom(
return jsonerror.InternalServerError()
}
if aliasResp.RoomID != "" {
return util.MessageResponse(400, "Alias already exists")
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.RoomInUse("Room ID already exists."),
}
}
aliasEvent = &fledglingEvent{
@ -484,7 +487,10 @@ func createRoom(
}
if aliasResp.AliasExists {
return util.MessageResponse(400, "Alias already exists")
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.RoomInUse("Room alias already exists."),
}
}
}

View file

@ -33,7 +33,7 @@ func Deactivate(
return *errRes
}
localpart, _, err := gomatrixserverlib.SplitID('@', login.User)
localpart, _, err := gomatrixserverlib.SplitID('@', login.Username())
if err != nil {
util.GetLogger(req.Context()).WithError(err).Error("gomatrixserverlib.SplitID failed")
return jsonerror.InternalServerError()

View file

@ -23,7 +23,6 @@ import (
"github.com/matrix-org/dendrite/clientapi/httputil"
"github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/dendrite/userapi/api"
userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
)
@ -50,18 +49,18 @@ type devicesDeleteJSON struct {
// GetDeviceByID handles /devices/{deviceID}
func GetDeviceByID(
req *http.Request, userAPI userapi.UserInternalAPI, device *api.Device,
req *http.Request, userAPI api.UserInternalAPI, device *api.Device,
deviceID string,
) util.JSONResponse {
var queryRes userapi.QueryDevicesResponse
err := userAPI.QueryDevices(req.Context(), &userapi.QueryDevicesRequest{
var queryRes api.QueryDevicesResponse
err := userAPI.QueryDevices(req.Context(), &api.QueryDevicesRequest{
UserID: device.UserID,
}, &queryRes)
if err != nil {
util.GetLogger(req.Context()).WithError(err).Error("QueryDevices failed")
return jsonerror.InternalServerError()
}
var targetDevice *userapi.Device
var targetDevice *api.Device
for _, device := range queryRes.Devices {
if device.ID == deviceID {
targetDevice = &device
@ -88,10 +87,10 @@ func GetDeviceByID(
// GetDevicesByLocalpart handles /devices
func GetDevicesByLocalpart(
req *http.Request, userAPI userapi.UserInternalAPI, device *api.Device,
req *http.Request, userAPI api.UserInternalAPI, device *api.Device,
) util.JSONResponse {
var queryRes userapi.QueryDevicesResponse
err := userAPI.QueryDevices(req.Context(), &userapi.QueryDevicesRequest{
var queryRes api.QueryDevicesResponse
err := userAPI.QueryDevices(req.Context(), &api.QueryDevicesRequest{
UserID: device.UserID,
}, &queryRes)
if err != nil {

View file

@ -23,7 +23,6 @@ import (
federationSenderAPI "github.com/matrix-org/dendrite/federationsender/api"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/dendrite/userapi/api"
userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
@ -115,7 +114,7 @@ func DirectoryRoom(
// SetLocalAlias implements PUT /directory/room/{roomAlias}
func SetLocalAlias(
req *http.Request,
device *api.Device,
device *userapi.Device,
alias string,
cfg *config.ClientAPI,
rsAPI roomserverAPI.RoomserverInternalAPI,
@ -192,7 +191,7 @@ func SetLocalAlias(
// RemoveLocalAlias implements DELETE /directory/room/{roomAlias}
func RemoveLocalAlias(
req *http.Request,
device *api.Device,
device *userapi.Device,
alias string,
rsAPI roomserverAPI.RoomserverInternalAPI,
) util.JSONResponse {

View file

@ -0,0 +1,291 @@
// Copyright 2021 The Matrix.org Foundation C.I.C.
//
// 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 routing
import (
"encoding/json"
"fmt"
"net/http"
"github.com/matrix-org/dendrite/clientapi/httputil"
"github.com/matrix-org/dendrite/clientapi/jsonerror"
userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/util"
)
type keyBackupVersion struct {
Algorithm string `json:"algorithm"`
AuthData json.RawMessage `json:"auth_data"`
}
type keyBackupVersionCreateResponse struct {
Version string `json:"version"`
}
type keyBackupVersionResponse struct {
Algorithm string `json:"algorithm"`
AuthData json.RawMessage `json:"auth_data"`
Count int64 `json:"count"`
ETag string `json:"etag"`
Version string `json:"version"`
}
type keyBackupSessionRequest struct {
Rooms map[string]struct {
Sessions map[string]userapi.KeyBackupSession `json:"sessions"`
} `json:"rooms"`
}
type keyBackupSessionResponse struct {
Count int64 `json:"count"`
ETag string `json:"etag"`
}
// Create a new key backup. Request must contain a `keyBackupVersion`. Returns a `keyBackupVersionCreateResponse`.
// Implements POST /_matrix/client/r0/room_keys/version
func CreateKeyBackupVersion(req *http.Request, userAPI userapi.UserInternalAPI, device *userapi.Device) util.JSONResponse {
var kb keyBackupVersion
resErr := httputil.UnmarshalJSONRequest(req, &kb)
if resErr != nil {
return *resErr
}
var performKeyBackupResp userapi.PerformKeyBackupResponse
userAPI.PerformKeyBackup(req.Context(), &userapi.PerformKeyBackupRequest{
UserID: device.UserID,
Version: "",
AuthData: kb.AuthData,
Algorithm: kb.Algorithm,
}, &performKeyBackupResp)
if performKeyBackupResp.Error != "" {
if performKeyBackupResp.BadInput {
return util.JSONResponse{
Code: 400,
JSON: jsonerror.InvalidArgumentValue(performKeyBackupResp.Error),
}
}
return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %s", performKeyBackupResp.Error))
}
return util.JSONResponse{
Code: 200,
JSON: keyBackupVersionCreateResponse{
Version: performKeyBackupResp.Version,
},
}
}
// KeyBackupVersion returns the key backup version specified. If `version` is empty, the latest `keyBackupVersionResponse` is returned.
// Implements GET /_matrix/client/r0/room_keys/version and GET /_matrix/client/r0/room_keys/version/{version}
func KeyBackupVersion(req *http.Request, userAPI userapi.UserInternalAPI, device *userapi.Device, version string) util.JSONResponse {
var queryResp userapi.QueryKeyBackupResponse
userAPI.QueryKeyBackup(req.Context(), &userapi.QueryKeyBackupRequest{
UserID: device.UserID,
Version: version,
}, &queryResp)
if queryResp.Error != "" {
return util.ErrorResponse(fmt.Errorf("QueryKeyBackup: %s", queryResp.Error))
}
if !queryResp.Exists {
return util.JSONResponse{
Code: 404,
JSON: jsonerror.NotFound("version not found"),
}
}
return util.JSONResponse{
Code: 200,
JSON: keyBackupVersionResponse{
Algorithm: queryResp.Algorithm,
AuthData: queryResp.AuthData,
Count: queryResp.Count,
ETag: queryResp.ETag,
Version: queryResp.Version,
},
}
}
// Modify the auth data of a key backup. Version must not be empty. Request must contain a `keyBackupVersion`
// Implements PUT /_matrix/client/r0/room_keys/version/{version}
func ModifyKeyBackupVersionAuthData(req *http.Request, userAPI userapi.UserInternalAPI, device *userapi.Device, version string) util.JSONResponse {
var kb keyBackupVersion
resErr := httputil.UnmarshalJSONRequest(req, &kb)
if resErr != nil {
return *resErr
}
var performKeyBackupResp userapi.PerformKeyBackupResponse
userAPI.PerformKeyBackup(req.Context(), &userapi.PerformKeyBackupRequest{
UserID: device.UserID,
Version: version,
AuthData: kb.AuthData,
Algorithm: kb.Algorithm,
}, &performKeyBackupResp)
if performKeyBackupResp.Error != "" {
if performKeyBackupResp.BadInput {
return util.JSONResponse{
Code: 400,
JSON: jsonerror.InvalidArgumentValue(performKeyBackupResp.Error),
}
}
return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %s", performKeyBackupResp.Error))
}
if !performKeyBackupResp.Exists {
return util.JSONResponse{
Code: 404,
JSON: jsonerror.NotFound("backup version not found"),
}
}
// Unclear what the 200 body should be
return util.JSONResponse{
Code: 200,
JSON: keyBackupVersionCreateResponse{
Version: performKeyBackupResp.Version,
},
}
}
// Delete a version of key backup. Version must not be empty. If the key backup was previously deleted, will return 200 OK.
// Implements DELETE /_matrix/client/r0/room_keys/version/{version}
func DeleteKeyBackupVersion(req *http.Request, userAPI userapi.UserInternalAPI, device *userapi.Device, version string) util.JSONResponse {
var performKeyBackupResp userapi.PerformKeyBackupResponse
userAPI.PerformKeyBackup(req.Context(), &userapi.PerformKeyBackupRequest{
UserID: device.UserID,
Version: version,
DeleteBackup: true,
}, &performKeyBackupResp)
if performKeyBackupResp.Error != "" {
if performKeyBackupResp.BadInput {
return util.JSONResponse{
Code: 400,
JSON: jsonerror.InvalidArgumentValue(performKeyBackupResp.Error),
}
}
return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %s", performKeyBackupResp.Error))
}
if !performKeyBackupResp.Exists {
return util.JSONResponse{
Code: 404,
JSON: jsonerror.NotFound("backup version not found"),
}
}
// Unclear what the 200 body should be
return util.JSONResponse{
Code: 200,
JSON: keyBackupVersionCreateResponse{
Version: performKeyBackupResp.Version,
},
}
}
// Upload a bunch of session keys for a given `version`.
func UploadBackupKeys(
req *http.Request, userAPI userapi.UserInternalAPI, device *userapi.Device, version string, keys *keyBackupSessionRequest,
) util.JSONResponse {
var performKeyBackupResp userapi.PerformKeyBackupResponse
userAPI.PerformKeyBackup(req.Context(), &userapi.PerformKeyBackupRequest{
UserID: device.UserID,
Version: version,
Keys: *keys,
}, &performKeyBackupResp)
if performKeyBackupResp.Error != "" {
if performKeyBackupResp.BadInput {
return util.JSONResponse{
Code: 400,
JSON: jsonerror.InvalidArgumentValue(performKeyBackupResp.Error),
}
}
return util.ErrorResponse(fmt.Errorf("PerformKeyBackup: %s", performKeyBackupResp.Error))
}
if !performKeyBackupResp.Exists {
return util.JSONResponse{
Code: 404,
JSON: jsonerror.NotFound("backup version not found"),
}
}
return util.JSONResponse{
Code: 200,
JSON: keyBackupSessionResponse{
Count: performKeyBackupResp.KeyCount,
ETag: performKeyBackupResp.KeyETag,
},
}
}
// Get keys from a given backup version. Response returned varies depending on if roomID and sessionID are set.
func GetBackupKeys(
req *http.Request, userAPI userapi.UserInternalAPI, device *userapi.Device, version, roomID, sessionID string,
) util.JSONResponse {
var queryResp userapi.QueryKeyBackupResponse
userAPI.QueryKeyBackup(req.Context(), &userapi.QueryKeyBackupRequest{
UserID: device.UserID,
Version: version,
ReturnKeys: true,
KeysForRoomID: roomID,
KeysForSessionID: sessionID,
}, &queryResp)
if queryResp.Error != "" {
return util.ErrorResponse(fmt.Errorf("QueryKeyBackup: %s", queryResp.Error))
}
if !queryResp.Exists {
return util.JSONResponse{
Code: 404,
JSON: jsonerror.NotFound("version not found"),
}
}
if sessionID != "" {
// return the key itself if it was found
roomData, ok := queryResp.Keys[roomID]
if ok {
key, ok := roomData[sessionID]
if ok {
return util.JSONResponse{
Code: 200,
JSON: key,
}
}
}
} else if roomID != "" {
roomData, ok := queryResp.Keys[roomID]
if ok {
// wrap response in "sessions"
return util.JSONResponse{
Code: 200,
JSON: struct {
Sessions map[string]userapi.KeyBackupSession `json:"sessions"`
}{
Sessions: roomData,
},
}
}
} else {
// response is the same as the upload request
var resp keyBackupSessionRequest
resp.Rooms = make(map[string]struct {
Sessions map[string]userapi.KeyBackupSession `json:"sessions"`
})
for roomID, roomData := range queryResp.Keys {
resp.Rooms[roomID] = struct {
Sessions map[string]userapi.KeyBackupSession `json:"sessions"`
}{
Sessions: roomData,
}
}
return util.JSONResponse{
Code: 200,
JSON: resp,
}
}
return util.JSONResponse{
Code: 404,
JSON: jsonerror.NotFound("keys not found"),
}
}

View file

@ -0,0 +1,149 @@
// Copyright 2021 The Matrix.org Foundation C.I.C.
//
// 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 routing
import (
"net/http"
"github.com/matrix-org/dendrite/clientapi/auth"
"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/keyserver/api"
"github.com/matrix-org/dendrite/setup/config"
userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/dendrite/userapi/storage/accounts"
"github.com/matrix-org/util"
)
type crossSigningRequest struct {
api.PerformUploadDeviceKeysRequest
Auth newPasswordAuth `json:"auth"`
}
func UploadCrossSigningDeviceKeys(
req *http.Request, userInteractiveAuth *auth.UserInteractive,
keyserverAPI api.KeyInternalAPI, device *userapi.Device,
accountDB accounts.Database, cfg *config.ClientAPI,
) util.JSONResponse {
uploadReq := &crossSigningRequest{}
uploadRes := &api.PerformUploadDeviceKeysResponse{}
resErr := httputil.UnmarshalJSONRequest(req, &uploadReq)
if resErr != nil {
return *resErr
}
sessionID := uploadReq.Auth.Session
if sessionID == "" {
sessionID = util.RandomString(sessionIDLength)
}
if uploadReq.Auth.Type != authtypes.LoginTypePassword {
return util.JSONResponse{
Code: http.StatusUnauthorized,
JSON: newUserInteractiveResponse(
sessionID,
[]authtypes.Flow{
{
Stages: []authtypes.LoginType{authtypes.LoginTypePassword},
},
},
nil,
),
}
}
typePassword := auth.LoginTypePassword{
GetAccountByPassword: accountDB.GetAccountByPassword,
Config: cfg,
}
if _, authErr := typePassword.Login(req.Context(), &uploadReq.Auth.PasswordRequest); authErr != nil {
return *authErr
}
AddCompletedSessionStage(sessionID, authtypes.LoginTypePassword)
uploadReq.UserID = device.UserID
keyserverAPI.PerformUploadDeviceKeys(req.Context(), &uploadReq.PerformUploadDeviceKeysRequest, uploadRes)
if err := uploadRes.Error; err != nil {
switch {
case err.IsInvalidSignature:
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.InvalidSignature(err.Error()),
}
case err.IsMissingParam:
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.MissingParam(err.Error()),
}
case err.IsInvalidParam:
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.InvalidParam(err.Error()),
}
default:
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.Unknown(err.Error()),
}
}
}
return util.JSONResponse{
Code: http.StatusOK,
JSON: struct{}{},
}
}
func UploadCrossSigningDeviceSignatures(req *http.Request, keyserverAPI api.KeyInternalAPI, device *userapi.Device) util.JSONResponse {
uploadReq := &api.PerformUploadDeviceSignaturesRequest{}
uploadRes := &api.PerformUploadDeviceSignaturesResponse{}
if err := httputil.UnmarshalJSONRequest(req, &uploadReq.Signatures); err != nil {
return *err
}
uploadReq.UserID = device.UserID
keyserverAPI.PerformUploadDeviceSignatures(req.Context(), uploadReq, uploadRes)
if err := uploadRes.Error; err != nil {
switch {
case err.IsInvalidSignature:
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.InvalidSignature(err.Error()),
}
case err.IsMissingParam:
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.MissingParam(err.Error()),
}
case err.IsInvalidParam:
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.InvalidParam(err.Error()),
}
default:
return util.JSONResponse{
Code: http.StatusBadRequest,
JSON: jsonerror.Unknown(err.Error()),
}
}
}
return util.JSONResponse{
Code: http.StatusOK,
JSON: struct{}{},
}
}

View file

@ -100,7 +100,7 @@ func (r *queryKeysRequest) GetTimeout() time.Duration {
return time.Duration(r.Timeout) * time.Millisecond
}
func QueryKeys(req *http.Request, keyAPI api.KeyInternalAPI) util.JSONResponse {
func QueryKeys(req *http.Request, keyAPI api.KeyInternalAPI, device *userapi.Device) util.JSONResponse {
var r queryKeysRequest
resErr := httputil.UnmarshalJSONRequest(req, &r)
if resErr != nil {
@ -108,6 +108,7 @@ func QueryKeys(req *http.Request, keyAPI api.KeyInternalAPI) util.JSONResponse {
}
queryRes := api.QueryKeysResponse{}
keyAPI.QueryKeys(req.Context(), &api.QueryKeysRequest{
UserID: device.UserID,
UserToDevices: r.DeviceKeys,
Timeout: r.GetTimeout(),
// TODO: Token?
@ -115,8 +116,11 @@ func QueryKeys(req *http.Request, keyAPI api.KeyInternalAPI) util.JSONResponse {
return util.JSONResponse{
Code: 200,
JSON: map[string]interface{}{
"device_keys": queryRes.DeviceKeys,
"failures": queryRes.Failures,
"device_keys": queryRes.DeviceKeys,
"master_keys": queryRes.MasterKeys,
"self_signing_keys": queryRes.SelfSigningKeys,
"user_signing_keys": queryRes.UserSigningKeys,
"failures": queryRes.Failures,
},
}
}

View file

@ -19,16 +19,15 @@ import (
"github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/dendrite/userapi/api"
userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/util"
)
// Logout handles POST /logout
func Logout(
req *http.Request, userAPI userapi.UserInternalAPI, device *api.Device,
req *http.Request, userAPI api.UserInternalAPI, device *api.Device,
) util.JSONResponse {
var performRes userapi.PerformDeviceDeletionResponse
err := userAPI.PerformDeviceDeletion(req.Context(), &userapi.PerformDeviceDeletionRequest{
var performRes api.PerformDeviceDeletionResponse
err := userAPI.PerformDeviceDeletion(req.Context(), &api.PerformDeviceDeletionRequest{
UserID: device.UserID,
DeviceIDs: []string{device.ID},
}, &performRes)
@ -45,10 +44,10 @@ func Logout(
// LogoutAll handles POST /logout/all
func LogoutAll(
req *http.Request, userAPI userapi.UserInternalAPI, device *api.Device,
req *http.Request, userAPI api.UserInternalAPI, device *api.Device,
) util.JSONResponse {
var performRes userapi.PerformDeviceDeletionResponse
err := userAPI.PerformDeviceDeletion(req.Context(), &userapi.PerformDeviceDeletionRequest{
var performRes api.PerformDeviceDeletionResponse
err := userAPI.PerformDeviceDeletion(req.Context(), &api.PerformDeviceDeletionRequest{
UserID: device.UserID,
DeviceIDs: nil,
}, &performRes)

View file

@ -26,7 +26,6 @@ import (
"github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/dendrite/clientapi/threepid"
"github.com/matrix-org/dendrite/internal/eventutil"
"github.com/matrix-org/dendrite/roomserver/api"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/setup/config"
userapi "github.com/matrix-org/dendrite/userapi/api"
@ -107,7 +106,7 @@ func sendMembership(ctx context.Context, accountDB accounts.Database, device *us
if err = roomserverAPI.SendEvents(
ctx, rsAPI,
api.KindNew,
roomserverAPI.KindNew,
[]*gomatrixserverlib.HeaderedEvent{event.Event.Headered(roomVer)},
cfg.Matrix.ServerName,
nil,
@ -328,11 +327,11 @@ func loadProfile(
return profile, err
}
func extractRequestData(req *http.Request, roomID string, rsAPI api.RoomserverInternalAPI) (
func extractRequestData(req *http.Request, roomID string, rsAPI roomserverAPI.RoomserverInternalAPI) (
body *threepid.MembershipRequest, evTime time.Time, roomVer gomatrixserverlib.RoomVersion, resErr *util.JSONResponse,
) {
verReq := api.QueryRoomVersionForRoomRequest{RoomID: roomID}
verRes := api.QueryRoomVersionForRoomResponse{}
verReq := roomserverAPI.QueryRoomVersionForRoomRequest{RoomID: roomID}
verRes := roomserverAPI.QueryRoomVersionForRoomResponse{}
if err := rsAPI.QueryRoomVersionForRoom(req.Context(), &verReq, &verRes); err != nil {
resErr = &util.JSONResponse{
Code: http.StatusBadRequest,
@ -402,13 +401,13 @@ func checkAndProcessThreepid(
return
}
func checkMemberInRoom(ctx context.Context, rsAPI api.RoomserverInternalAPI, userID, roomID string) *util.JSONResponse {
func checkMemberInRoom(ctx context.Context, rsAPI roomserverAPI.RoomserverInternalAPI, userID, roomID string) *util.JSONResponse {
tuple := gomatrixserverlib.StateKeyTuple{
EventType: gomatrixserverlib.MRoomMember,
StateKey: userID,
}
var membershipRes api.QueryCurrentStateResponse
err := rsAPI.QueryCurrentState(ctx, &api.QueryCurrentStateRequest{
var membershipRes roomserverAPI.QueryCurrentStateResponse
err := rsAPI.QueryCurrentState(ctx, &roomserverAPI.QueryCurrentStateRequest{
RoomID: roomID,
StateTuples: []gomatrixserverlib.StateKeyTuple{tuple},
}, &membershipRes)
@ -445,8 +444,8 @@ func SendForget(
) util.JSONResponse {
ctx := req.Context()
logger := util.GetLogger(ctx).WithField("roomID", roomID).WithField("userID", device.UserID)
var membershipRes api.QueryMembershipForUserResponse
membershipReq := api.QueryMembershipForUserRequest{
var membershipRes roomserverAPI.QueryMembershipForUserResponse
membershipReq := roomserverAPI.QueryMembershipForUserRequest{
RoomID: roomID,
UserID: device.UserID,
}
@ -468,11 +467,11 @@ func SendForget(
}
}
request := api.PerformForgetRequest{
request := roomserverAPI.PerformForgetRequest{
RoomID: roomID,
UserID: device.UserID,
}
response := api.PerformForgetResponse{}
response := roomserverAPI.PerformForgetResponse{}
if err := rsAPI.PerformForget(ctx, &request, &response); err != nil {
logger.WithError(err).Error("PerformForget: unable to forget room")
return jsonerror.InternalServerError()

View file

@ -9,7 +9,6 @@ import (
"github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/dendrite/setup/config"
"github.com/matrix-org/dendrite/userapi/api"
userapi "github.com/matrix-org/dendrite/userapi/api"
"github.com/matrix-org/dendrite/userapi/storage/accounts"
"github.com/matrix-org/gomatrixserverlib"
"github.com/matrix-org/util"
@ -29,7 +28,7 @@ type newPasswordAuth struct {
func Password(
req *http.Request,
userAPI userapi.UserInternalAPI,
userAPI api.UserInternalAPI,
accountDB accounts.Database,
device *api.Device,
cfg *config.ClientAPI,
@ -90,11 +89,11 @@ func Password(
}
// Ask the user API to perform the password change.
passwordReq := &userapi.PerformPasswordUpdateRequest{
passwordReq := &api.PerformPasswordUpdateRequest{
Localpart: localpart,
Password: r.NewPassword,
}
passwordRes := &userapi.PerformPasswordUpdateResponse{}
passwordRes := &api.PerformPasswordUpdateResponse{}
if err := userAPI.PerformPasswordUpdate(req.Context(), passwordReq, passwordRes); err != nil {
util.GetLogger(req.Context()).WithError(err).Error("PerformPasswordUpdate failed")
return jsonerror.InternalServerError()
@ -107,12 +106,12 @@ func Password(
// If the request asks us to log out all other devices then
// ask the user API to do that.
if r.LogoutDevices {
logoutReq := &userapi.PerformDeviceDeletionRequest{
logoutReq := &api.PerformDeviceDeletionRequest{
UserID: device.UserID,
DeviceIDs: nil,
ExceptDeviceID: device.ID,
}
logoutRes := &userapi.PerformDeviceDeletionResponse{}
logoutRes := &api.PerformDeviceDeletionResponse{}
if err := userAPI.PerformDeviceDeletion(req.Context(), logoutReq, logoutRes); err != nil {
util.GetLogger(req.Context()).WithError(err).Error("PerformDeviceDeletion failed")
return jsonerror.InternalServerError()

View file

@ -22,7 +22,6 @@ import (
"github.com/matrix-org/dendrite/clientapi/httputil"
"github.com/matrix-org/dendrite/clientapi/jsonerror"
"github.com/matrix-org/dendrite/internal/eventutil"
"github.com/matrix-org/dendrite/roomserver/api"
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
"github.com/matrix-org/dendrite/setup/config"
userapi "github.com/matrix-org/dendrite/userapi/api"
@ -113,7 +112,7 @@ func SendRedaction(
return jsonerror.InternalServerError()
}
var queryRes api.QueryLatestEventsAndStateResponse
var queryRes roomserverAPI.QueryLatestEventsAndStateResponse
e, err := eventutil.QueryAndBuildEvent(req.Context(), &builder, cfg.Matrix, time.Now(), rsAPI, &queryRes)
if err == eventutil.ErrRoomNoExists {
return util.JSONResponse{
@ -121,7 +120,7 @@ func SendRedaction(
JSON: jsonerror.NotFound("Room does not exist"),
}
}
if err = roomserverAPI.SendEvents(context.Background(), rsAPI, api.KindNew, []*gomatrixserverlib.HeaderedEvent{e}, cfg.Matrix.ServerName, nil); err != nil {
if err = roomserverAPI.SendEvents(context.Background(), rsAPI, roomserverAPI.KindNew, []*gomatrixserverlib.HeaderedEvent{e}, cfg.Matrix.ServerName, nil); err != nil {
util.GetLogger(req.Context()).WithError(err).Errorf("failed to SendEvents")
return jsonerror.InternalServerError()
}

View file

@ -68,18 +68,18 @@ func (r *SharedSecretRegistration) IsValidMacLogin(
) (bool, error) {
// Check that shared secret registration isn't disabled.
if r.sharedSecret == "" {
return false, errors.New("Shared secret registration is disabled")
return false, errors.New("shared secret registration is disabled")
}
if !r.validNonce(nonce) {
return false, fmt.Errorf("Incorrect or expired nonce: %s", nonce)
return false, fmt.Errorf("incorrect or expired nonce: %s", nonce)
}
// Check that username/password don't contain the HMAC delimiters.
if strings.Contains(username, "\x00") {
return false, errors.New("Username contains invalid character")
return false, errors.New("username contains invalid character")
}
if strings.Contains(password, "\x00") {
return false, errors.New("Password contains invalid character")
return false, errors.New("password contains invalid character")
}
adminString := "notadmin"

View file

@ -64,7 +64,9 @@ func Setup(
rateLimits := newRateLimits(&cfg.RateLimiting)
userInteractiveAuth := auth.NewUserInteractive(accountDB.GetAccountByPassword, cfg)
unstableFeatures := make(map[string]bool)
unstableFeatures := map[string]bool{
"org.matrix.e2e_cross_signing": true,
}
for _, msc := range cfg.MSCs.MSCs {
unstableFeatures["org.matrix."+msc] = true
}
@ -289,10 +291,7 @@ func Setup(
return util.ErrorResponse(err)
}
// If there's a trailing slash, remove it
eventType := vars["type"]
if strings.HasSuffix(eventType, "/") {
eventType = eventType[:len(eventType)-1]
}
eventType := strings.TrimSuffix(vars["type"], "/")
eventFormat := req.URL.Query().Get("format") == "event"
return OnIncomingStateTypeRequest(req.Context(), device, rsAPI, vars["roomID"], eventType, "", eventFormat)
})).Methods(http.MethodGet, http.MethodOptions)
@ -313,11 +312,7 @@ func Setup(
return util.ErrorResponse(err)
}
emptyString := ""
eventType := vars["eventType"]
// If there's a trailing slash, remove it
if strings.HasSuffix(eventType, "/") {
eventType = eventType[:len(eventType)-1]
}
eventType := strings.TrimSuffix(vars["eventType"], "/")
return SendEvent(req, device, vars["roomID"], eventType, nil, &emptyString, cfg, rsAPI, nil)
}),
).Methods(http.MethodPut, http.MethodOptions)
@ -896,6 +891,192 @@ func Setup(
}),
).Methods(http.MethodGet, http.MethodOptions)
// Key Backup Versions (Metadata)
getBackupKeysVersion := httputil.MakeAuthAPI("get_backup_keys_version", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
}
return KeyBackupVersion(req, userAPI, device, vars["version"])
})
getLatestBackupKeysVersion := httputil.MakeAuthAPI("get_latest_backup_keys_version", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
return KeyBackupVersion(req, userAPI, device, "")
})
putBackupKeysVersion := httputil.MakeAuthAPI("put_backup_keys_version", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
}
return ModifyKeyBackupVersionAuthData(req, userAPI, device, vars["version"])
})
deleteBackupKeysVersion := httputil.MakeAuthAPI("delete_backup_keys_version", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
}
return DeleteKeyBackupVersion(req, userAPI, device, vars["version"])
})
postNewBackupKeysVersion := httputil.MakeAuthAPI("post_new_backup_keys_version", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
return CreateKeyBackupVersion(req, userAPI, device)
})
r0mux.Handle("/room_keys/version/{version}", getBackupKeysVersion).Methods(http.MethodGet, http.MethodOptions)
r0mux.Handle("/room_keys/version", getLatestBackupKeysVersion).Methods(http.MethodGet, http.MethodOptions)
r0mux.Handle("/room_keys/version/{version}", putBackupKeysVersion).Methods(http.MethodPut)
r0mux.Handle("/room_keys/version/{version}", deleteBackupKeysVersion).Methods(http.MethodDelete)
r0mux.Handle("/room_keys/version", postNewBackupKeysVersion).Methods(http.MethodPost, http.MethodOptions)
unstableMux.Handle("/room_keys/version/{version}", getBackupKeysVersion).Methods(http.MethodGet, http.MethodOptions)
unstableMux.Handle("/room_keys/version", getLatestBackupKeysVersion).Methods(http.MethodGet, http.MethodOptions)
unstableMux.Handle("/room_keys/version/{version}", putBackupKeysVersion).Methods(http.MethodPut)
unstableMux.Handle("/room_keys/version/{version}", deleteBackupKeysVersion).Methods(http.MethodDelete)
unstableMux.Handle("/room_keys/version", postNewBackupKeysVersion).Methods(http.MethodPost, http.MethodOptions)
// Inserting E2E Backup Keys
// Bulk room and session
putBackupKeys := httputil.MakeAuthAPI("put_backup_keys", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
version := req.URL.Query().Get("version")
if version == "" {
return util.JSONResponse{
Code: 400,
JSON: jsonerror.InvalidArgumentValue("version must be specified"),
}
}
var reqBody keyBackupSessionRequest
resErr := clientutil.UnmarshalJSONRequest(req, &reqBody)
if resErr != nil {
return *resErr
}
return UploadBackupKeys(req, userAPI, device, version, &reqBody)
})
// Single room bulk session
putBackupKeysRoom := httputil.MakeAuthAPI("put_backup_keys_room", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
}
version := req.URL.Query().Get("version")
if version == "" {
return util.JSONResponse{
Code: 400,
JSON: jsonerror.InvalidArgumentValue("version must be specified"),
}
}
roomID := vars["roomID"]
var reqBody keyBackupSessionRequest
reqBody.Rooms = make(map[string]struct {
Sessions map[string]userapi.KeyBackupSession `json:"sessions"`
})
reqBody.Rooms[roomID] = struct {
Sessions map[string]userapi.KeyBackupSession `json:"sessions"`
}{
Sessions: map[string]userapi.KeyBackupSession{},
}
body := reqBody.Rooms[roomID]
resErr := clientutil.UnmarshalJSONRequest(req, &body)
if resErr != nil {
return *resErr
}
reqBody.Rooms[roomID] = body
return UploadBackupKeys(req, userAPI, device, version, &reqBody)
})
// Single room, single session
putBackupKeysRoomSession := httputil.MakeAuthAPI("put_backup_keys_room_session", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
}
version := req.URL.Query().Get("version")
if version == "" {
return util.JSONResponse{
Code: 400,
JSON: jsonerror.InvalidArgumentValue("version must be specified"),
}
}
var reqBody userapi.KeyBackupSession
resErr := clientutil.UnmarshalJSONRequest(req, &reqBody)
if resErr != nil {
return *resErr
}
roomID := vars["roomID"]
sessionID := vars["sessionID"]
var keyReq keyBackupSessionRequest
keyReq.Rooms = make(map[string]struct {
Sessions map[string]userapi.KeyBackupSession `json:"sessions"`
})
keyReq.Rooms[roomID] = struct {
Sessions map[string]userapi.KeyBackupSession `json:"sessions"`
}{
Sessions: make(map[string]userapi.KeyBackupSession),
}
keyReq.Rooms[roomID].Sessions[sessionID] = reqBody
return UploadBackupKeys(req, userAPI, device, version, &keyReq)
})
r0mux.Handle("/room_keys/keys", putBackupKeys).Methods(http.MethodPut)
r0mux.Handle("/room_keys/keys/{roomID}", putBackupKeysRoom).Methods(http.MethodPut)
r0mux.Handle("/room_keys/keys/{roomID}/{sessionID}", putBackupKeysRoomSession).Methods(http.MethodPut)
unstableMux.Handle("/room_keys/keys", putBackupKeys).Methods(http.MethodPut)
unstableMux.Handle("/room_keys/keys/{roomID}", putBackupKeysRoom).Methods(http.MethodPut)
unstableMux.Handle("/room_keys/keys/{roomID}/{sessionID}", putBackupKeysRoomSession).Methods(http.MethodPut)
// Querying E2E Backup Keys
getBackupKeys := httputil.MakeAuthAPI("get_backup_keys", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
return GetBackupKeys(req, userAPI, device, req.URL.Query().Get("version"), "", "")
})
getBackupKeysRoom := httputil.MakeAuthAPI("get_backup_keys_room", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
}
return GetBackupKeys(req, userAPI, device, req.URL.Query().Get("version"), vars["roomID"], "")
})
getBackupKeysRoomSession := httputil.MakeAuthAPI("get_backup_keys_room_session", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
if err != nil {
return util.ErrorResponse(err)
}
return GetBackupKeys(req, userAPI, device, req.URL.Query().Get("version"), vars["roomID"], vars["sessionID"])
})
r0mux.Handle("/room_keys/keys", getBackupKeys).Methods(http.MethodGet, http.MethodOptions)
r0mux.Handle("/room_keys/keys/{roomID}", getBackupKeysRoom).Methods(http.MethodGet, http.MethodOptions)
r0mux.Handle("/room_keys/keys/{roomID}/{sessionID}", getBackupKeysRoomSession).Methods(http.MethodGet, http.MethodOptions)
unstableMux.Handle("/room_keys/keys", getBackupKeys).Methods(http.MethodGet, http.MethodOptions)
unstableMux.Handle("/room_keys/keys/{roomID}", getBackupKeysRoom).Methods(http.MethodGet, http.MethodOptions)
unstableMux.Handle("/room_keys/keys/{roomID}/{sessionID}", getBackupKeysRoomSession).Methods(http.MethodGet, http.MethodOptions)
// Deleting E2E Backup Keys
// Cross-signing device keys
postDeviceSigningKeys := httputil.MakeAuthAPI("post_device_signing_keys", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
return UploadCrossSigningDeviceKeys(req, userInteractiveAuth, keyAPI, device, accountDB, cfg)
})
postDeviceSigningSignatures := httputil.MakeAuthAPI("post_device_signing_signatures", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
return UploadCrossSigningDeviceSignatures(req, keyAPI, device)
})
r0mux.Handle("/keys/device_signing/upload", postDeviceSigningKeys).Methods(http.MethodPost, http.MethodOptions)
r0mux.Handle("/keys/signatures/upload", postDeviceSigningSignatures).Methods(http.MethodPost, http.MethodOptions)
unstableMux.Handle("/keys/device_signing/upload", postDeviceSigningKeys).Methods(http.MethodPost, http.MethodOptions)
unstableMux.Handle("/keys/signatures/upload", postDeviceSigningSignatures).Methods(http.MethodPost, http.MethodOptions)
// Supplying a device ID is deprecated.
r0mux.Handle("/keys/upload/{deviceID}",
httputil.MakeAuthAPI("keys_upload", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
@ -909,7 +1090,7 @@ func Setup(
).Methods(http.MethodPost, http.MethodOptions)
r0mux.Handle("/keys/query",
httputil.MakeAuthAPI("keys_query", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
return QueryKeys(req, keyAPI)
return QueryKeys(req, keyAPI, device)
}),
).Methods(http.MethodPost, http.MethodOptions)
r0mux.Handle("/keys/claim",

View file

@ -81,7 +81,7 @@ func CreateSession(
// Error if the status isn't OK
if resp.StatusCode != http.StatusOK {
return "", fmt.Errorf("Could not create a session on the server %s", req.IDServer)
return "", fmt.Errorf("could not create a session on the server %s", req.IDServer)
}
// Extract the SID from the response and return it
@ -168,7 +168,7 @@ func PublishAssociation(creds Credentials, userID string, cfg *config.ClientAPI)
// Error if the status isn't OK
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("Could not publish the association on the server %s", creds.IDServer)
return fmt.Errorf("could not publish the association on the server %s", creds.IDServer)
}
return nil

View file

@ -31,11 +31,11 @@ func ParseUsernameParam(usernameParam string, expectedServerName *gomatrixserver
lp, domain, err := gomatrixserverlib.SplitID('@', usernameParam)
if err != nil {
return "", errors.New("Invalid username")
return "", errors.New("invalid username")
}
if expectedServerName != nil && domain != *expectedServerName {
return "", errors.New("User ID does not belong to this server")
return "", errors.New("user ID does not belong to this server")
}
localpart = lp