Handle createRoom & sendPDUs
This commit is contained in:
parent
3d02c81031
commit
a5ba533cfb
|
@ -48,6 +48,7 @@ type createRoomRequest struct {
|
|||
RoomVersion gomatrixserverlib.RoomVersion `json:"room_version"`
|
||||
PowerLevelContentOverride json.RawMessage `json:"power_level_content_override"`
|
||||
IsDirect bool `json:"is_direct"`
|
||||
SenderID string `json:"sender_id"`
|
||||
}
|
||||
|
||||
func (r createRoomRequest) Validate() *util.JSONResponse {
|
||||
|
@ -107,6 +108,208 @@ type createRoomResponse struct {
|
|||
RoomAlias string `json:"room_alias,omitempty"` // in synapse not spec
|
||||
}
|
||||
|
||||
// CreateRoomCryptoIDs implements /createRoom
|
||||
func CreateRoomCryptoIDs(
|
||||
req *http.Request, device *api.Device,
|
||||
cfg *config.ClientAPI,
|
||||
profileAPI api.ClientUserAPI, rsAPI roomserverAPI.ClientRoomserverAPI,
|
||||
asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
) util.JSONResponse {
|
||||
var createRequest createRoomRequest
|
||||
resErr := httputil.UnmarshalJSONRequest(req, &createRequest)
|
||||
if resErr != nil {
|
||||
return *resErr
|
||||
}
|
||||
if resErr = createRequest.Validate(); resErr != nil {
|
||||
return *resErr
|
||||
}
|
||||
evTime, err := httputil.ParseTSParam(req)
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.InvalidParam(err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
return makeCreateRoomEvents(req.Context(), createRequest, device, cfg, profileAPI, rsAPI, asAPI, evTime)
|
||||
}
|
||||
|
||||
func makeCreateRoomEvents(
|
||||
ctx context.Context,
|
||||
createRequest createRoomRequest, device *api.Device,
|
||||
cfg *config.ClientAPI,
|
||||
profileAPI api.ClientUserAPI, rsAPI roomserverAPI.ClientRoomserverAPI,
|
||||
asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
evTime time.Time,
|
||||
) util.JSONResponse {
|
||||
userID, err := spec.NewUserID(device.UserID, true)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("invalid userID")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
if !cfg.Matrix.IsLocalServerName(userID.Domain()) {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusForbidden,
|
||||
JSON: spec.Forbidden(fmt.Sprintf("User domain %q not configured locally", userID.Domain())),
|
||||
}
|
||||
}
|
||||
|
||||
logger := util.GetLogger(ctx)
|
||||
|
||||
// TODO: Check room ID doesn't clash with an existing one, and we
|
||||
// probably shouldn't be using pseudo-random strings, maybe GUIDs?
|
||||
roomID, err := spec.NewRoomID(fmt.Sprintf("!%s:%s", util.RandomString(16), userID.Domain()))
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("invalid roomID")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
// Clobber keys: creator, room_version
|
||||
|
||||
roomVersion := rsAPI.DefaultRoomVersion()
|
||||
if createRequest.RoomVersion != "" {
|
||||
candidateVersion := gomatrixserverlib.RoomVersion(createRequest.RoomVersion)
|
||||
_, roomVersionError := roomserverVersion.SupportedRoomVersion(candidateVersion)
|
||||
if roomVersionError != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.UnsupportedRoomVersion(roomVersionError.Error()),
|
||||
}
|
||||
}
|
||||
roomVersion = candidateVersion
|
||||
}
|
||||
|
||||
logger.WithFields(log.Fields{
|
||||
"userID": userID.String(),
|
||||
"roomID": roomID.String(),
|
||||
"roomVersion": roomVersion,
|
||||
}).Info("Creating new room")
|
||||
|
||||
profile, err := appserviceAPI.RetrieveUserProfile(ctx, userID.String(), asAPI, profileAPI)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("appserviceAPI.RetrieveUserProfile failed")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{},
|
||||
}
|
||||
}
|
||||
|
||||
userDisplayName := profile.DisplayName
|
||||
userAvatarURL := profile.AvatarURL
|
||||
|
||||
keyID := cfg.Matrix.KeyID
|
||||
privateKey := cfg.Matrix.PrivateKey
|
||||
|
||||
req := roomserverAPI.PerformCreateRoomRequest{
|
||||
InvitedUsers: createRequest.Invite,
|
||||
RoomName: createRequest.Name,
|
||||
Visibility: createRequest.Visibility,
|
||||
Topic: createRequest.Topic,
|
||||
StatePreset: createRequest.Preset,
|
||||
CreationContent: createRequest.CreationContent,
|
||||
InitialState: createRequest.InitialState,
|
||||
RoomAliasName: createRequest.RoomAliasName,
|
||||
RoomVersion: roomVersion,
|
||||
PowerLevelContentOverride: createRequest.PowerLevelContentOverride,
|
||||
IsDirect: createRequest.IsDirect,
|
||||
|
||||
UserDisplayName: userDisplayName,
|
||||
UserAvatarURL: userAvatarURL,
|
||||
KeyID: keyID,
|
||||
PrivateKey: privateKey,
|
||||
EventTime: evTime,
|
||||
|
||||
SenderID: createRequest.SenderID,
|
||||
}
|
||||
|
||||
createEvents, err := rsAPI.PerformCreateRoomCryptoIDs(ctx, *userID, *roomID, &req)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("MakeCreateRoomEvents failed")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{Err: err.Error()},
|
||||
}
|
||||
}
|
||||
|
||||
response := createRoomCryptoIDsResponse{
|
||||
RoomID: roomID.String(),
|
||||
Version: string(roomVersion),
|
||||
PDUs: ToProtoEvents(ctx, createEvents, rsAPI),
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: 200,
|
||||
JSON: response,
|
||||
}
|
||||
}
|
||||
|
||||
type createRoomCryptoIDsResponse struct {
|
||||
RoomID string `json:"room_id"`
|
||||
Version string `json:"room_version"`
|
||||
PDUs []json.RawMessage `json:"pdus"`
|
||||
}
|
||||
|
||||
func ToProtoEvents(ctx context.Context, events []gomatrixserverlib.PDU, rsAPI roomserverAPI.ClientRoomserverAPI) []json.RawMessage {
|
||||
result := make([]json.RawMessage, len(events))
|
||||
for i, event := range events {
|
||||
result[i] = json.RawMessage(event.JSON())
|
||||
//fmt.Printf("\nProcessing %s event (%s)\n", events[i].Type(), events[i].EventID())
|
||||
//var rawJson interface{}
|
||||
//json.Unmarshal(events[i].JSON(), &rawJson)
|
||||
//fmt.Printf("JSON: %+v\n", rawJson)
|
||||
//result[i] = gomatrixserverlib.ProtoEvent{
|
||||
// SenderID: string(events[i].SenderID()),
|
||||
// RoomID: events[i].RoomID().String(),
|
||||
// Type: events[i].Type(),
|
||||
// StateKey: events[i].StateKey(),
|
||||
// PrevEvents: events[i].PrevEventIDs(),
|
||||
// AuthEvents: events[i].AuthEventIDs(),
|
||||
// Redacts: events[i].Redacts(),
|
||||
// Depth: events[i].Depth(),
|
||||
// Content: events[i].Content(),
|
||||
// Unsigned: events[i].Unsigned(),
|
||||
// Hashes: events[i].Hashes(),
|
||||
// OriginServerTimestamp: events[i].OriginServerTS(),
|
||||
//}
|
||||
|
||||
//roomVersion, _ := rsAPI.QueryRoomVersionForRoom(ctx, events[i].RoomID().String())
|
||||
//verImpl, _ := gomatrixserverlib.GetRoomVersion(roomVersion)
|
||||
//eventJSON, err := json.Marshal(result[i])
|
||||
//if err != nil {
|
||||
// util.GetLogger(ctx).WithError(err).Error("failed marshalling event")
|
||||
// continue
|
||||
//}
|
||||
//pdu, err := verImpl.NewEventFromUntrustedJSON(eventJSON)
|
||||
//if err != nil {
|
||||
// util.GetLogger(ctx).WithError(err).Error("failed making event from json")
|
||||
// continue
|
||||
//}
|
||||
//fmt.Printf("\nProcessing %s event (%s) - PDU\n", result[i].Type, pdu.EventID())
|
||||
//fmt.Printf(" EventID: %v - %v\n", events[i].EventID(), pdu.EventID())
|
||||
//fmt.Printf(" SenderID: %s - %s\n", events[i].SenderID(), pdu.SenderID())
|
||||
//fmt.Printf(" RoomID: %s - %s\n", events[i].RoomID().String(), pdu.RoomID().String())
|
||||
//fmt.Printf(" Type: %s - %s\n", events[i].Type(), pdu.Type())
|
||||
//fmt.Printf(" StateKey: %s - %s\n", *events[i].StateKey(), *pdu.StateKey())
|
||||
//fmt.Printf(" PrevEvents: %v - %v\n", events[i].PrevEventIDs(), pdu.PrevEventIDs())
|
||||
//fmt.Printf(" AuthEvents: %v - %v\n", events[i].AuthEventIDs(), pdu.AuthEventIDs())
|
||||
//fmt.Printf(" Redacts: %s - %s\n", events[i].Redacts(), pdu.Redacts())
|
||||
//fmt.Printf(" Depth: %d - %d\n", events[i].Depth(), pdu.Depth())
|
||||
//fmt.Printf(" Content: %v - %v\n", events[i].Content(), pdu.Content())
|
||||
//fmt.Printf(" Unsigned: %v - %v\n", events[i].Unsigned(), pdu.Unsigned())
|
||||
//fmt.Printf(" Hashes: %v - %v\n", events[i].Hashes(), pdu.Hashes())
|
||||
//fmt.Printf(" OriginServerTS: %d - %d\n", events[i].OriginServerTS(), pdu.OriginServerTS())
|
||||
//json.Unmarshal(eventJSON, &rawJson)
|
||||
//fmt.Printf("JSON: %+v\n", rawJson)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// CreateRoom implements /createRoom
|
||||
func CreateRoom(
|
||||
req *http.Request, device *api.Device,
|
||||
|
@ -132,7 +335,6 @@ func CreateRoom(
|
|||
return createRoom(req.Context(), createRequest, device, cfg, profileAPI, rsAPI, asAPI, evTime)
|
||||
}
|
||||
|
||||
// createRoom implements /createRoom
|
||||
func createRoom(
|
||||
ctx context.Context,
|
||||
createRequest createRoomRequest, device *api.Device,
|
||||
|
|
|
@ -312,6 +312,24 @@ func Setup(
|
|||
return CreateRoom(req, device, cfg, userAPI, rsAPI, asAPI)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
unstableMux.Handle("/org.matrix.msc_cryptoids/createRoom",
|
||||
httputil.MakeAuthAPI("createRoom", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
logrus.Info("Processing request to /org.matrix.msc_cryptoids/createRoom")
|
||||
return CreateRoomCryptoIDs(req, device, cfg, userAPI, rsAPI, asAPI)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
unstableMux.Handle("/org.matrix.msc_cryptoids/sendPDUs",
|
||||
httputil.MakeAuthAPI("send_pdus", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
logrus.Info("Processing request to /org.matrix.msc_cryptoids/sendPDUs")
|
||||
if r := rateLimits.Limit(req, device); r != nil {
|
||||
return *r
|
||||
}
|
||||
|
||||
// NOTE: when making events such as for create_room, multiple PDUs will need to be passed between the client & server.
|
||||
return SendPDUs(req, device, cfg, userAPI, rsAPI, asAPI)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/join/{roomIDOrAlias}",
|
||||
httputil.MakeAuthAPI(spec.Join, userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
if r := rateLimits.Limit(req, device); r != nil {
|
||||
|
@ -336,6 +354,7 @@ func Setup(
|
|||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
|
||||
if mscCfg.Enabled("msc2753") {
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/peek/{roomIDOrAlias}",
|
||||
httputil.MakeAuthAPI(spec.Peek, userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
if r := rateLimits.Limit(req, device); r != nil {
|
||||
|
@ -356,6 +375,7 @@ func Setup(
|
|||
return GetJoinedRooms(req, device, rsAPI)
|
||||
}, httputil.WithAllowGuests()),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/rooms/{roomID}/join",
|
||||
httputil.MakeAuthAPI(spec.Join, userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
if r := rateLimits.Limit(req, device); r != nil {
|
||||
|
@ -378,6 +398,7 @@ func Setup(
|
|||
return resp.(util.JSONResponse)
|
||||
}, httputil.WithAllowGuests()),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/rooms/{roomID}/leave",
|
||||
httputil.MakeAuthAPI("membership", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
if r := rateLimits.Limit(req, device); r != nil {
|
||||
|
@ -392,6 +413,7 @@ func Setup(
|
|||
)
|
||||
}, httputil.WithAllowGuests()),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/rooms/{roomID}/unpeek",
|
||||
httputil.MakeAuthAPI("unpeek", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -403,6 +425,7 @@ func Setup(
|
|||
)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/rooms/{roomID}/ban",
|
||||
httputil.MakeAuthAPI("membership", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -412,6 +435,7 @@ func Setup(
|
|||
return SendBan(req, userAPI, device, vars["roomID"], cfg, rsAPI, asAPI)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/rooms/{roomID}/invite",
|
||||
httputil.MakeAuthAPI("membership", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
if r := rateLimits.Limit(req, device); r != nil {
|
||||
|
@ -424,6 +448,7 @@ func Setup(
|
|||
return SendInvite(req, userAPI, device, vars["roomID"], cfg, rsAPI, asAPI)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/rooms/{roomID}/kick",
|
||||
httputil.MakeAuthAPI("membership", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -433,6 +458,7 @@ func Setup(
|
|||
return SendKick(req, userAPI, device, vars["roomID"], cfg, rsAPI, asAPI)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/rooms/{roomID}/unban",
|
||||
httputil.MakeAuthAPI("membership", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -442,6 +468,7 @@ func Setup(
|
|||
return SendUnban(req, userAPI, device, vars["roomID"], cfg, rsAPI, asAPI)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/rooms/{roomID}/send/{eventType}",
|
||||
httputil.MakeAuthAPI("send_message", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -451,6 +478,7 @@ func Setup(
|
|||
return SendEvent(req, device, vars["roomID"], vars["eventType"], nil, nil, cfg, rsAPI, nil)
|
||||
}, httputil.WithAllowGuests()),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/rooms/{roomID}/send/{eventType}/{txnID}",
|
||||
httputil.MakeAuthAPI("send_message", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -499,6 +527,7 @@ func Setup(
|
|||
return OnIncomingStateTypeRequest(req.Context(), device, rsAPI, vars["roomID"], vars["type"], vars["stateKey"], eventFormat)
|
||||
}, httputil.WithAllowGuests())).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/rooms/{roomID}/state/{eventType:[^/]+/?}",
|
||||
httputil.MakeAuthAPI("send_message", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -511,6 +540,7 @@ func Setup(
|
|||
}, httputil.WithAllowGuests()),
|
||||
).Methods(http.MethodPut, http.MethodOptions)
|
||||
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/rooms/{roomID}/state/{eventType}/{stateKey}",
|
||||
httputil.MakeAuthAPI("send_message", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -559,6 +589,7 @@ func Setup(
|
|||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/directory/room/{roomAlias}",
|
||||
httputil.MakeAuthAPI("directory_room", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -569,6 +600,7 @@ func Setup(
|
|||
}),
|
||||
).Methods(http.MethodPut, http.MethodOptions)
|
||||
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/directory/room/{roomAlias}",
|
||||
httputil.MakeAuthAPI("directory_room", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -588,6 +620,7 @@ func Setup(
|
|||
}),
|
||||
).Methods(http.MethodGet, http.MethodOptions)
|
||||
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/directory/list/room/{roomID}",
|
||||
httputil.MakeAuthAPI("directory_list", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -597,6 +630,7 @@ func Setup(
|
|||
return SetVisibility(req, rsAPI, device, vars["roomID"])
|
||||
}),
|
||||
).Methods(http.MethodPut, http.MethodOptions)
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/directory/list/appservice/{networkID}/{roomID}",
|
||||
httputil.MakeAuthAPI("directory_list", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -608,6 +642,7 @@ func Setup(
|
|||
).Methods(http.MethodPut, http.MethodOptions)
|
||||
|
||||
// Undocumented endpoint
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/directory/list/appservice/{networkID}/{roomID}",
|
||||
httputil.MakeAuthAPI("directory_list", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -648,6 +683,7 @@ func Setup(
|
|||
return SendTyping(req, device, vars["roomID"], vars["userID"], rsAPI, syncProducer)
|
||||
}),
|
||||
).Methods(http.MethodPut, http.MethodOptions)
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/rooms/{roomID}/redact/{eventID}",
|
||||
httputil.MakeAuthAPI("rooms_redact", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -657,6 +693,7 @@ func Setup(
|
|||
return SendRedaction(req, device, vars["roomID"], vars["eventID"], cfg, rsAPI, nil, nil)
|
||||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/rooms/{roomID}/redact/{eventID}/{txnId}",
|
||||
httputil.MakeAuthAPI("rooms_redact", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -668,6 +705,7 @@ func Setup(
|
|||
}),
|
||||
).Methods(http.MethodPut, http.MethodOptions)
|
||||
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/sendToDevice/{eventType}/{txnID}",
|
||||
httputil.MakeAuthAPI("send_to_device", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
@ -1144,6 +1182,7 @@ func Setup(
|
|||
}),
|
||||
).Methods(http.MethodPost, http.MethodOptions)
|
||||
|
||||
// TODO: update for cryptoIDs
|
||||
v3mux.Handle("/rooms/{roomID}/upgrade",
|
||||
httputil.MakeAuthAPI("rooms_upgrade", userAPI, func(req *http.Request, device *userapi.Device) util.JSONResponse {
|
||||
vars, err := httputil.URLDecodeMapValues(mux.Vars(req))
|
||||
|
|
140
clientapi/routing/send_pdus.go
Normal file
140
clientapi/routing/send_pdus.go
Normal file
|
@ -0,0 +1,140 @@
|
|||
// Copyright 2023 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"
|
||||
"net/http"
|
||||
|
||||
appserviceAPI "github.com/matrix-org/dendrite/appservice/api"
|
||||
"github.com/matrix-org/dendrite/clientapi/httputil"
|
||||
roomserverAPI "github.com/matrix-org/dendrite/roomserver/api"
|
||||
"github.com/matrix-org/dendrite/roomserver/types"
|
||||
"github.com/matrix-org/dendrite/setup/config"
|
||||
"github.com/matrix-org/dendrite/userapi/api"
|
||||
"github.com/matrix-org/gomatrixserverlib"
|
||||
"github.com/matrix-org/gomatrixserverlib/spec"
|
||||
"github.com/matrix-org/util"
|
||||
)
|
||||
|
||||
type sendPDUsRequest struct {
|
||||
Version string `json:"room_version"`
|
||||
PDUs []json.RawMessage `json:"pdus"`
|
||||
}
|
||||
|
||||
// SendPDUs implements /sendPDUs
|
||||
func SendPDUs(
|
||||
req *http.Request, device *api.Device,
|
||||
cfg *config.ClientAPI,
|
||||
profileAPI api.ClientUserAPI, rsAPI roomserverAPI.ClientRoomserverAPI,
|
||||
asAPI appserviceAPI.AppServiceInternalAPI,
|
||||
) util.JSONResponse {
|
||||
// TODO: cryptoIDs - should this include an "eventType"?
|
||||
// if it's a bulk send endpoint, I don't think that makes any sense since there are multiple event types
|
||||
// In that case, how do I know how to treat the events?
|
||||
// I could sort them all by roomID?
|
||||
// Then filter them down based on event type? (how do I collect groups of events such as for room creation?)
|
||||
// Possibly based on event hash tracking that I know were sent to the client?
|
||||
// For createRoom, I know what the possible list of events are, so try to find those and collect them to send to room creation.
|
||||
// Could also sort by depth... but that seems dangerous and depth may not be a field forever
|
||||
// Does it matter at all?
|
||||
// Can't I just forward all the events to the roomserver?
|
||||
// Do I need to do any specific processing on them?
|
||||
|
||||
var pdus sendPDUsRequest
|
||||
resErr := httputil.UnmarshalJSONRequest(req, &pdus)
|
||||
if resErr != nil {
|
||||
return *resErr
|
||||
}
|
||||
|
||||
userID, err := spec.NewUserID(device.UserID, true)
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusBadRequest,
|
||||
JSON: spec.InvalidParam(err.Error()),
|
||||
}
|
||||
}
|
||||
|
||||
inputs := make([]roomserverAPI.InputRoomEvent, 0, len(pdus.PDUs))
|
||||
for _, event := range pdus.PDUs {
|
||||
// TODO: cryptoIDs - event hash check?
|
||||
verImpl, err := gomatrixserverlib.GetRoomVersion(gomatrixserverlib.RoomVersion(pdus.Version))
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{Err: err.Error()},
|
||||
}
|
||||
}
|
||||
//eventJSON, err := json.Marshal(event)
|
||||
//if err != nil {
|
||||
// return util.JSONResponse{
|
||||
// Code: http.StatusInternalServerError,
|
||||
// JSON: spec.InternalServerError{Err: err.Error()},
|
||||
// }
|
||||
//}
|
||||
// TODO: cryptoIDs - how should we be converting to a PDU here?
|
||||
// if the hash matches an event we sent to the client, then the JSON should be good.
|
||||
// But how do we know how to fill out if the event is redacted if we use the trustedJSON function?
|
||||
// Also - untrusted JSON seems better - except it strips off the unsigned field?
|
||||
// Also - gmsl events don't store the `hashes` field... problem?
|
||||
|
||||
pdu, err := verImpl.NewEventFromUntrustedJSON(event)
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{Err: err.Error()},
|
||||
}
|
||||
}
|
||||
key, err := rsAPI.GetOrCreateUserRoomPrivateKey(req.Context(), *userID, pdu.RoomID())
|
||||
if err != nil {
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{Err: err.Error()},
|
||||
}
|
||||
}
|
||||
pdu = pdu.Sign(string(pdu.SenderID()), "ed25519:1", key)
|
||||
util.GetLogger(req.Context()).Infof("Processing %s event (%s)", pdu.Type(), pdu.EventID())
|
||||
switch pdu.Type() {
|
||||
case spec.MRoomCreate:
|
||||
}
|
||||
|
||||
// TODO: cryptoIDs - does it matter which order these are added?
|
||||
// yes - if the events are for room creation.
|
||||
// Could make this a client requirement? ie. events are processed based on the order they appear
|
||||
// We need to check event validity after processing each event.
|
||||
// ie. what if the client changes power levels that disallow further events they sent?
|
||||
// We should be doing this already as part of `SendInputRoomEvents`, but how should we pass this
|
||||
// failure back to the client?
|
||||
inputs = append(inputs, roomserverAPI.InputRoomEvent{
|
||||
Kind: roomserverAPI.KindNew,
|
||||
Event: &types.HeaderedEvent{PDU: pdu},
|
||||
Origin: userID.Domain(),
|
||||
SendAsServer: roomserverAPI.DoNotSendToOtherServers,
|
||||
})
|
||||
}
|
||||
|
||||
// send the events to the roomserver
|
||||
if err := roomserverAPI.SendInputRoomEvents(req.Context(), rsAPI, userID.Domain(), inputs, false); err != nil {
|
||||
util.GetLogger(req.Context()).WithError(err).Error("roomserverAPI.SendInputRoomEvents failed")
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusInternalServerError,
|
||||
JSON: spec.InternalServerError{Err: err.Error()},
|
||||
}
|
||||
}
|
||||
|
||||
return util.JSONResponse{
|
||||
Code: http.StatusOK,
|
||||
}
|
||||
}
|
2
go.mod
2
go.mod
|
@ -1,5 +1,7 @@
|
|||
module github.com/matrix-org/dendrite
|
||||
|
||||
replace github.com/matrix-org/gomatrixserverlib => ../../gomatrixserverlib/crypto-ids/
|
||||
|
||||
require (
|
||||
github.com/Arceliar/ironwood v0.0.0-20221025225125-45b4281814c2
|
||||
github.com/Arceliar/phony v0.0.0-20210209235338-dde1a8dca979
|
||||
|
|
|
@ -232,6 +232,7 @@ type ClientRoomserverAPI interface {
|
|||
GetRoomIDForAlias(ctx context.Context, req *GetRoomIDForAliasRequest, res *GetRoomIDForAliasResponse) error
|
||||
GetAliasesForRoomID(ctx context.Context, req *GetAliasesForRoomIDRequest, res *GetAliasesForRoomIDResponse) error
|
||||
|
||||
PerformCreateRoomCryptoIDs(ctx context.Context, userID spec.UserID, roomID spec.RoomID, createRequest *PerformCreateRoomRequest) ([]gomatrixserverlib.PDU, error)
|
||||
PerformCreateRoom(ctx context.Context, userID spec.UserID, roomID spec.RoomID, createRequest *PerformCreateRoomRequest) (string, *util.JSONResponse)
|
||||
// PerformRoomUpgrade upgrades a room to a newer version
|
||||
PerformRoomUpgrade(ctx context.Context, roomID string, userID spec.UserID, roomVersion gomatrixserverlib.RoomVersion) (newRoomID string, err error)
|
||||
|
|
|
@ -29,6 +29,8 @@ type PerformCreateRoomRequest struct {
|
|||
KeyID gomatrixserverlib.KeyID
|
||||
PrivateKey ed25519.PrivateKey
|
||||
EventTime time.Time
|
||||
|
||||
SenderID string
|
||||
}
|
||||
|
||||
type PerformJoinRequest struct {
|
||||
|
|
|
@ -44,6 +44,423 @@ type Creator struct {
|
|||
RSAPI api.RoomserverInternalAPI
|
||||
}
|
||||
|
||||
// PerformCreateRoomCryptoIDs handles all the steps necessary to create a new room.
|
||||
// nolint: gocyclo
|
||||
func (c *Creator) PerformCreateRoomCryptoIDs(ctx context.Context, userID spec.UserID, roomID spec.RoomID, createRequest *api.PerformCreateRoomRequest) ([]gomatrixserverlib.PDU, error) {
|
||||
verImpl, err := gomatrixserverlib.GetRoomVersion(createRequest.RoomVersion)
|
||||
if err != nil {
|
||||
return nil, spec.BadJSON("unknown room version")
|
||||
}
|
||||
|
||||
createContent := map[string]interface{}{}
|
||||
if len(createRequest.CreationContent) > 0 {
|
||||
if err = json.Unmarshal(createRequest.CreationContent, &createContent); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("json.Unmarshal for creation_content failed")
|
||||
return nil, spec.BadJSON("invalid create content")
|
||||
}
|
||||
}
|
||||
|
||||
senderID := spec.SenderID(createRequest.SenderID)
|
||||
|
||||
// TODO: cryptoIDs - should we be assigning a room NID yet?
|
||||
_, err = c.DB.AssignRoomNID(ctx, roomID, createRequest.RoomVersion)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("failed to assign roomNID")
|
||||
return nil, spec.InternalServerError{Err: err.Error()}
|
||||
}
|
||||
|
||||
if createRequest.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
|
||||
util.GetLogger(ctx).Infof("StoreUserRoomPublicKey - SenderID: %s UserID: %s RoomID: %s", senderID, userID.String(), roomID.String())
|
||||
bytes := spec.Base64Bytes{}
|
||||
err = bytes.Decode(string(senderID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(bytes) != ed25519.PublicKeySize {
|
||||
return nil, spec.BadJSON("SenderID is not a valid ed25519 public key")
|
||||
}
|
||||
|
||||
// TODO: cryptoIDs - Swap this out for only storing the public key
|
||||
key, keyErr := c.RSAPI.GetOrCreateUserRoomPrivateKey(ctx, userID, roomID)
|
||||
if keyErr != nil {
|
||||
util.GetLogger(ctx).WithError(keyErr).Error("GetOrCreateUserRoomPrivateKey failed")
|
||||
return nil, spec.InternalServerError{Err: keyErr.Error()}
|
||||
}
|
||||
senderID = spec.SenderIDFromPseudoIDKey(key)
|
||||
//err := c.RSAPI.StoreUserRoomPublicKey(ctx, senderID, userID, roomID)
|
||||
//if err != nil {
|
||||
// return nil, spec.InternalServerError{Err: err.Error()}
|
||||
//}
|
||||
}
|
||||
|
||||
createContent["creator"] = senderID
|
||||
createContent["room_version"] = createRequest.RoomVersion
|
||||
powerLevelContent := eventutil.InitialPowerLevelsContent(string(senderID))
|
||||
joinRuleContent := gomatrixserverlib.JoinRuleContent{
|
||||
JoinRule: spec.Invite,
|
||||
}
|
||||
historyVisibilityContent := gomatrixserverlib.HistoryVisibilityContent{
|
||||
HistoryVisibility: historyVisibilityShared,
|
||||
}
|
||||
|
||||
if createRequest.PowerLevelContentOverride != nil {
|
||||
// Merge powerLevelContentOverride fields by unmarshalling it atop the defaults
|
||||
err = json.Unmarshal(createRequest.PowerLevelContentOverride, &powerLevelContent)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("json.Unmarshal for power_level_content_override failed")
|
||||
return nil, spec.BadJSON("malformed power_level_content_override")
|
||||
}
|
||||
}
|
||||
|
||||
var guestsCanJoin bool
|
||||
switch createRequest.StatePreset {
|
||||
case spec.PresetPrivateChat:
|
||||
joinRuleContent.JoinRule = spec.Invite
|
||||
historyVisibilityContent.HistoryVisibility = historyVisibilityShared
|
||||
guestsCanJoin = true
|
||||
case spec.PresetTrustedPrivateChat:
|
||||
joinRuleContent.JoinRule = spec.Invite
|
||||
historyVisibilityContent.HistoryVisibility = historyVisibilityShared
|
||||
for _, invitee := range createRequest.InvitedUsers {
|
||||
powerLevelContent.Users[invitee] = 100
|
||||
}
|
||||
guestsCanJoin = true
|
||||
case spec.PresetPublicChat:
|
||||
joinRuleContent.JoinRule = spec.Public
|
||||
historyVisibilityContent.HistoryVisibility = historyVisibilityShared
|
||||
}
|
||||
|
||||
createEvent := gomatrixserverlib.FledglingEvent{
|
||||
Type: spec.MRoomCreate,
|
||||
Content: createContent,
|
||||
}
|
||||
powerLevelEvent := gomatrixserverlib.FledglingEvent{
|
||||
Type: spec.MRoomPowerLevels,
|
||||
Content: powerLevelContent,
|
||||
}
|
||||
joinRuleEvent := gomatrixserverlib.FledglingEvent{
|
||||
Type: spec.MRoomJoinRules,
|
||||
Content: joinRuleContent,
|
||||
}
|
||||
historyVisibilityEvent := gomatrixserverlib.FledglingEvent{
|
||||
Type: spec.MRoomHistoryVisibility,
|
||||
Content: historyVisibilityContent,
|
||||
}
|
||||
membershipEvent := gomatrixserverlib.FledglingEvent{
|
||||
Type: spec.MRoomMember,
|
||||
StateKey: string(senderID),
|
||||
}
|
||||
|
||||
memberContent := gomatrixserverlib.MemberContent{
|
||||
Membership: spec.Join,
|
||||
DisplayName: createRequest.UserDisplayName,
|
||||
AvatarURL: createRequest.UserAvatarURL,
|
||||
}
|
||||
|
||||
// If we are creating a room with pseudo IDs, create and sign the MXIDMapping
|
||||
if createRequest.RoomVersion == gomatrixserverlib.RoomVersionPseudoIDs {
|
||||
mapping := &gomatrixserverlib.MXIDMapping{
|
||||
UserRoomKey: senderID,
|
||||
UserID: userID.String(),
|
||||
}
|
||||
|
||||
identity, idErr := c.Cfg.Matrix.SigningIdentityFor(userID.Domain()) // we MUST use the server signing mxid_mapping
|
||||
if idErr != nil {
|
||||
logrus.WithError(idErr).WithField("domain", userID.Domain()).Error("unable to find signing identity for domain")
|
||||
return nil, spec.InternalServerError{Err: idErr.Error()}
|
||||
}
|
||||
|
||||
// Sign the mapping with the server identity
|
||||
if err = mapping.Sign(identity.ServerName, identity.KeyID, identity.PrivateKey); err != nil {
|
||||
return nil, spec.InternalServerError{Err: err.Error()}
|
||||
}
|
||||
memberContent.MXIDMapping = mapping
|
||||
}
|
||||
membershipEvent.Content = memberContent
|
||||
|
||||
var nameEvent *gomatrixserverlib.FledglingEvent
|
||||
var topicEvent *gomatrixserverlib.FledglingEvent
|
||||
var guestAccessEvent *gomatrixserverlib.FledglingEvent
|
||||
var aliasEvent *gomatrixserverlib.FledglingEvent
|
||||
|
||||
if createRequest.RoomName != "" {
|
||||
nameEvent = &gomatrixserverlib.FledglingEvent{
|
||||
Type: spec.MRoomName,
|
||||
Content: eventutil.NameContent{
|
||||
Name: createRequest.RoomName,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if createRequest.Topic != "" {
|
||||
topicEvent = &gomatrixserverlib.FledglingEvent{
|
||||
Type: spec.MRoomTopic,
|
||||
Content: eventutil.TopicContent{
|
||||
Topic: createRequest.Topic,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
if guestsCanJoin {
|
||||
guestAccessEvent = &gomatrixserverlib.FledglingEvent{
|
||||
Type: spec.MRoomGuestAccess,
|
||||
Content: eventutil.GuestAccessContent{
|
||||
GuestAccess: "can_join",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var roomAlias string
|
||||
if createRequest.RoomAliasName != "" {
|
||||
roomAlias = fmt.Sprintf("#%s:%s", createRequest.RoomAliasName, userID.Domain())
|
||||
// check it's free
|
||||
// TODO: This races but is better than nothing
|
||||
hasAliasReq := api.GetRoomIDForAliasRequest{
|
||||
Alias: roomAlias,
|
||||
IncludeAppservices: false,
|
||||
}
|
||||
|
||||
var aliasResp api.GetRoomIDForAliasResponse
|
||||
err = c.RSAPI.GetRoomIDForAlias(ctx, &hasAliasReq, &aliasResp)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("aliasAPI.GetRoomIDForAlias failed")
|
||||
return nil, spec.InternalServerError{Err: err.Error()}
|
||||
}
|
||||
if aliasResp.RoomID != "" {
|
||||
return nil, spec.RoomInUse("Room ID already exists.")
|
||||
}
|
||||
|
||||
aliasEvent = &gomatrixserverlib.FledglingEvent{
|
||||
Type: spec.MRoomCanonicalAlias,
|
||||
Content: eventutil.CanonicalAlias{
|
||||
Alias: roomAlias,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var initialStateEvents []gomatrixserverlib.FledglingEvent
|
||||
for i := range createRequest.InitialState {
|
||||
if createRequest.InitialState[i].StateKey != "" {
|
||||
initialStateEvents = append(initialStateEvents, createRequest.InitialState[i])
|
||||
continue
|
||||
}
|
||||
|
||||
switch createRequest.InitialState[i].Type {
|
||||
case spec.MRoomCreate:
|
||||
continue
|
||||
|
||||
case spec.MRoomPowerLevels:
|
||||
powerLevelEvent = createRequest.InitialState[i]
|
||||
|
||||
case spec.MRoomJoinRules:
|
||||
joinRuleEvent = createRequest.InitialState[i]
|
||||
|
||||
case spec.MRoomHistoryVisibility:
|
||||
historyVisibilityEvent = createRequest.InitialState[i]
|
||||
|
||||
case spec.MRoomGuestAccess:
|
||||
guestAccessEvent = &createRequest.InitialState[i]
|
||||
|
||||
case spec.MRoomName:
|
||||
nameEvent = &createRequest.InitialState[i]
|
||||
|
||||
case spec.MRoomTopic:
|
||||
topicEvent = &createRequest.InitialState[i]
|
||||
|
||||
default:
|
||||
initialStateEvents = append(initialStateEvents, createRequest.InitialState[i])
|
||||
}
|
||||
}
|
||||
|
||||
// send events into the room in order of:
|
||||
// 1- m.room.create
|
||||
// 2- room creator join member
|
||||
// 3- m.room.power_levels
|
||||
// 4- m.room.join_rules
|
||||
// 5- m.room.history_visibility
|
||||
// 6- m.room.canonical_alias (opt)
|
||||
// 7- m.room.guest_access (opt)
|
||||
// 8- other initial state items
|
||||
// 9- m.room.name (opt)
|
||||
// 10- m.room.topic (opt)
|
||||
// 11- invite events (opt) - with is_direct flag if applicable TODO
|
||||
// 12- 3pid invite events (opt) TODO
|
||||
// This differs from Synapse slightly. Synapse would vary the ordering of 3-7
|
||||
// depending on if those events were in "initial_state" or not. This made it
|
||||
// harder to reason about, hence sticking to a strict static ordering.
|
||||
eventsToMake := []gomatrixserverlib.FledglingEvent{
|
||||
createEvent, membershipEvent, powerLevelEvent, joinRuleEvent, historyVisibilityEvent,
|
||||
}
|
||||
if guestAccessEvent != nil {
|
||||
eventsToMake = append(eventsToMake, *guestAccessEvent)
|
||||
}
|
||||
eventsToMake = append(eventsToMake, initialStateEvents...)
|
||||
if nameEvent != nil {
|
||||
eventsToMake = append(eventsToMake, *nameEvent)
|
||||
}
|
||||
if topicEvent != nil {
|
||||
eventsToMake = append(eventsToMake, *topicEvent)
|
||||
}
|
||||
if aliasEvent != nil {
|
||||
// TODO: bit of a chicken and egg problem here as the alias doesn't exist and cannot until we have made the room.
|
||||
// This means we might fail creating the alias but say the canonical alias is something that doesn't exist.
|
||||
eventsToMake = append(eventsToMake, *aliasEvent)
|
||||
}
|
||||
|
||||
var builtEvents []gomatrixserverlib.PDU
|
||||
authEvents := gomatrixserverlib.NewAuthEvents(nil)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("rsapi.QuerySenderIDForUser failed")
|
||||
return nil, spec.InternalServerError{Err: err.Error()}
|
||||
}
|
||||
for i, e := range eventsToMake {
|
||||
depth := i + 1 // depth starts at 1
|
||||
|
||||
builder := verImpl.NewEventBuilderFromProtoEvent(&gomatrixserverlib.ProtoEvent{
|
||||
SenderID: string(senderID),
|
||||
RoomID: roomID.String(),
|
||||
Type: e.Type,
|
||||
StateKey: &e.StateKey,
|
||||
Depth: int64(depth),
|
||||
})
|
||||
err = builder.SetContent(e.Content)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("builder.SetContent failed")
|
||||
return nil, spec.InternalServerError{Err: err.Error()}
|
||||
}
|
||||
if i > 0 {
|
||||
builder.PrevEvents = []string{builtEvents[i-1].EventID()}
|
||||
}
|
||||
var ev gomatrixserverlib.PDU
|
||||
if err = builder.AddAuthEvents(&authEvents); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("AddAuthEvents failed")
|
||||
return nil, spec.InternalServerError{Err: err.Error()}
|
||||
}
|
||||
|
||||
ev, err = builder.BuildWithoutSigning(createRequest.EventTime, userID.Domain())
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("buildEvent failed")
|
||||
return nil, spec.InternalServerError{Err: err.Error()}
|
||||
}
|
||||
|
||||
if err = gomatrixserverlib.Allowed(ev, &authEvents, func(roomID spec.RoomID, senderID spec.SenderID) (*spec.UserID, error) {
|
||||
return c.RSAPI.QueryUserIDForSender(ctx, roomID, senderID)
|
||||
}); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("gomatrixserverlib.Allowed failed")
|
||||
return nil, spec.InternalServerError{Err: err.Error()}
|
||||
}
|
||||
|
||||
// Add the event to the list of auth events
|
||||
builtEvents = append(builtEvents, ev)
|
||||
err = authEvents.AddEvent(ev)
|
||||
if err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("authEvents.AddEvent failed")
|
||||
return nil, spec.InternalServerError{Err: err.Error()}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(#269): Reserve room alias while we create the room. This stops us
|
||||
// from creating the room but still failing due to the alias having already
|
||||
// been taken.
|
||||
if roomAlias != "" {
|
||||
aliasAlreadyExists, aliasErr := c.RSAPI.SetRoomAlias(ctx, senderID, roomID, roomAlias)
|
||||
if aliasErr != nil {
|
||||
util.GetLogger(ctx).WithError(aliasErr).Error("aliasAPI.SetRoomAlias failed")
|
||||
return nil, spec.InternalServerError{Err: aliasErr.Error()}
|
||||
}
|
||||
|
||||
if aliasAlreadyExists {
|
||||
return nil, spec.RoomInUse("Room alias already exists.")
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: cryptoIDs - this shouldn't really be done until the client calls /sendPDUs with these events
|
||||
// But that would require the visibility setting also being passed along
|
||||
if createRequest.Visibility == spec.Public {
|
||||
// expose this room in the published room list
|
||||
if err = c.RSAPI.PerformPublish(ctx, &api.PerformPublishRequest{
|
||||
RoomID: roomID.String(),
|
||||
Visibility: spec.Public,
|
||||
}); err != nil {
|
||||
util.GetLogger(ctx).WithError(err).Error("failed to publish room")
|
||||
return nil, spec.InternalServerError{Err: err.Error()}
|
||||
}
|
||||
}
|
||||
|
||||
// If this is a direct message then we should invite the participants.
|
||||
//if len(createRequest.InvitedUsers) > 0 {
|
||||
// Build some stripped state for the invite.
|
||||
//var globalStrippedState []gomatrixserverlib.InviteStrippedState
|
||||
//for _, event := range builtEvents {
|
||||
// // Chosen events from the spec:
|
||||
// // https://spec.matrix.org/v1.3/client-server-api/#stripped-state
|
||||
// switch event.Type() {
|
||||
// case spec.MRoomCreate:
|
||||
// fallthrough
|
||||
// case spec.MRoomName:
|
||||
// fallthrough
|
||||
// case spec.MRoomAvatar:
|
||||
// fallthrough
|
||||
// case spec.MRoomTopic:
|
||||
// fallthrough
|
||||
// case spec.MRoomCanonicalAlias:
|
||||
// fallthrough
|
||||
// case spec.MRoomEncryption:
|
||||
// fallthrough
|
||||
// case spec.MRoomMember:
|
||||
// fallthrough
|
||||
// case spec.MRoomJoinRules:
|
||||
// ev := event
|
||||
// globalStrippedState = append(
|
||||
// globalStrippedState,
|
||||
// gomatrixserverlib.NewInviteStrippedState(ev),
|
||||
// )
|
||||
// }
|
||||
//}
|
||||
|
||||
// Process the invites.
|
||||
//for _, invitee := range createRequest.InvitedUsers {
|
||||
//inviteeUserID, userIDErr := spec.NewUserID(invitee, true)
|
||||
//if userIDErr != nil {
|
||||
// util.GetLogger(ctx).WithError(userIDErr).Error("invalid UserID")
|
||||
// return nil, spec.InternalServerError{}
|
||||
//}
|
||||
|
||||
// TODO: cryptoIDs - these shouldn't be here
|
||||
// instead we should return proto invite events?
|
||||
//err = c.RSAPI.PerformInvite(ctx, &api.PerformInviteRequest{
|
||||
// InviteInput: api.InviteInput{
|
||||
// RoomID: roomID,
|
||||
// Inviter: userID,
|
||||
// Invitee: *inviteeUserID,
|
||||
// DisplayName: createRequest.UserDisplayName,
|
||||
// AvatarURL: createRequest.UserAvatarURL,
|
||||
// Reason: "",
|
||||
// IsDirect: createRequest.IsDirect,
|
||||
// KeyID: createRequest.KeyID,
|
||||
// PrivateKey: createRequest.PrivateKey,
|
||||
// EventTime: createRequest.EventTime,
|
||||
// },
|
||||
// InviteRoomState: globalStrippedState,
|
||||
// SendAsServer: string(userID.Domain()),
|
||||
//})
|
||||
//switch e := err.(type) {
|
||||
//case api.ErrInvalidID:
|
||||
// return nil, spec.Unknown(e.Error())
|
||||
//case api.ErrNotAllowed:
|
||||
// return nil, spec.Forbidden(e.Error())
|
||||
//case nil:
|
||||
//default:
|
||||
// util.GetLogger(ctx).WithError(err).Error("PerformInvite failed")
|
||||
// sentry.CaptureException(err)
|
||||
// return nil, spec.InternalServerError{}
|
||||
//}
|
||||
//}
|
||||
//}
|
||||
|
||||
return builtEvents, nil
|
||||
}
|
||||
|
||||
// PerformCreateRoom handles all the steps necessary to create a new room.
|
||||
// nolint: gocyclo
|
||||
func (c *Creator) PerformCreateRoom(ctx context.Context, userID spec.UserID, roomID spec.RoomID, createRequest *api.PerformCreateRoomRequest) (string, *util.JSONResponse) {
|
||||
|
|
|
@ -16,7 +16,8 @@ type RoomServer struct {
|
|||
}
|
||||
|
||||
func (c *RoomServer) Defaults(opts DefaultOpts) {
|
||||
c.DefaultRoomVersion = gomatrixserverlib.RoomVersionV10
|
||||
//c.DefaultRoomVersion = gomatrixserverlib.RoomVersionV10
|
||||
c.DefaultRoomVersion = gomatrixserverlib.RoomVersionPseudoIDs
|
||||
if opts.Generate {
|
||||
if !opts.SingleDatabase {
|
||||
c.Database.ConnectionString = "file:roomserver.db"
|
||||
|
|
Loading…
Reference in a new issue