Add local room join (#169)

* Add local room join

* Update TODO
This commit is contained in:
Brendan Abolivier 2017-07-28 15:29:12 +01:00 committed by Mark Haines
parent 34165c7761
commit 7d17df6f51
2 changed files with 59 additions and 10 deletions

View file

@ -78,7 +78,7 @@ func Setup(
common.MakeAuthAPI("join", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse { common.MakeAuthAPI("join", deviceDB, func(req *http.Request, device *authtypes.Device) util.JSONResponse {
vars := mux.Vars(req) vars := mux.Vars(req)
return writers.JoinRoomByIDOrAlias( return writers.JoinRoomByIDOrAlias(
req, device, vars["roomIDOrAlias"], cfg, federation, producer, queryAPI, keyRing, accountDB, req, device, vars["roomIDOrAlias"], cfg, federation, producer, queryAPI, aliasAPI, keyRing, accountDB,
) )
}), }),
) )

View file

@ -42,6 +42,7 @@ func JoinRoomByIDOrAlias(
federation *gomatrixserverlib.FederationClient, federation *gomatrixserverlib.FederationClient,
producer *producers.RoomserverProducer, producer *producers.RoomserverProducer,
queryAPI api.RoomserverQueryAPI, queryAPI api.RoomserverQueryAPI,
aliasAPI api.RoomserverAliasAPI,
keyRing gomatrixserverlib.KeyRing, keyRing gomatrixserverlib.KeyRing,
accountDB *accounts.Database, accountDB *accounts.Database,
) util.JSONResponse { ) util.JSONResponse {
@ -64,7 +65,7 @@ func JoinRoomByIDOrAlias(
content["displayname"] = profile.DisplayName content["displayname"] = profile.DisplayName
content["avatar_url"] = profile.AvatarURL content["avatar_url"] = profile.AvatarURL
r := joinRoomReq{req, content, device.UserID, cfg, federation, producer, queryAPI, keyRing} r := joinRoomReq{req, content, device.UserID, cfg, federation, producer, queryAPI, aliasAPI, keyRing}
if strings.HasPrefix(roomIDOrAlias, "!") { if strings.HasPrefix(roomIDOrAlias, "!") {
return r.joinRoomByID() return r.joinRoomByID()
@ -86,6 +87,7 @@ type joinRoomReq struct {
federation *gomatrixserverlib.FederationClient federation *gomatrixserverlib.FederationClient
producer *producers.RoomserverProducer producer *producers.RoomserverProducer
queryAPI api.RoomserverQueryAPI queryAPI api.RoomserverQueryAPI
aliasAPI api.RoomserverAliasAPI
keyRing gomatrixserverlib.KeyRing keyRing gomatrixserverlib.KeyRing
} }
@ -111,11 +113,23 @@ func (r joinRoomReq) joinRoomByAlias(roomAlias string) util.JSONResponse {
} }
} }
if domain == r.cfg.Matrix.ServerName { if domain == r.cfg.Matrix.ServerName {
// TODO: Implement joining local room aliases. queryReq := api.GetAliasRoomIDRequest{Alias: roomAlias}
panic(fmt.Errorf("Joining local room aliases is not implemented")) var queryRes api.GetAliasRoomIDResponse
} else { if err = r.aliasAPI.GetAliasRoomID(&queryReq, &queryRes); err != nil {
return r.joinRoomByRemoteAlias(domain, roomAlias) return httputil.LogThenError(r.req, err)
} }
if len(queryRes.RoomID) > 0 {
return r.joinRoomUsingServers(queryRes.RoomID, []gomatrixserverlib.ServerName{r.cfg.Matrix.ServerName})
}
// If the response doesn't contain a non-empty string, return an error
return util.JSONResponse{
Code: 404,
JSON: jsonerror.NotFound("Room alias " + roomAlias + " not found."),
}
}
// If the room isn't local, use federation to join
return r.joinRoomByRemoteAlias(domain, roomAlias)
} }
func (r joinRoomReq) joinRoomByRemoteAlias( func (r joinRoomReq) joinRoomByRemoteAlias(
@ -140,7 +154,7 @@ func (r joinRoomReq) joinRoomByRemoteAlias(
func (r joinRoomReq) writeToBuilder(eb *gomatrixserverlib.EventBuilder, roomID string) { func (r joinRoomReq) writeToBuilder(eb *gomatrixserverlib.EventBuilder, roomID string) {
eb.Type = "m.room.member" eb.Type = "m.room.member"
eb.SetContent(r.content) // TODO: Set avatar_url / displayname eb.SetContent(r.content)
eb.SetUnsigned(struct{}{}) eb.SetUnsigned(struct{}{})
eb.Sender = r.userID eb.Sender = r.userID
eb.StateKey = &r.userID eb.StateKey = &r.userID
@ -170,9 +184,44 @@ func (r joinRoomReq) joinRoomUsingServers(
} }
if queryRes.RoomExists { if queryRes.RoomExists {
// TODO: Implement joining rooms that already the server is already in. // The room exists in the local database, so we just have to send a join
// This should just fall through to the usual event sending code. // membership event and return the room ID
panic(fmt.Errorf("Joining rooms that the server already in is not implemented")) // TODO: Check if the user is allowed in the room (has been invited if
// the room is invite-only)
eb.Depth = queryRes.Depth
eb.PrevEvents = queryRes.LatestEvents
authEvents := gomatrixserverlib.NewAuthEvents(nil)
for i := range queryRes.StateEvents {
authEvents.AddEvent(&queryRes.StateEvents[i])
}
refs, err := needed.AuthEventReferences(&authEvents)
if err != nil {
return httputil.LogThenError(r.req, err)
}
eb.AuthEvents = refs
now := time.Now()
eventID := fmt.Sprintf("$%s:%s", util.RandomString(16), r.cfg.Matrix.ServerName)
event, err := eb.Build(
eventID, now, r.cfg.Matrix.ServerName, r.cfg.Matrix.KeyID, r.cfg.Matrix.PrivateKey,
)
if err != nil {
return httputil.LogThenError(r.req, err)
}
if err := r.producer.SendEvents([]gomatrixserverlib.Event{event}, r.cfg.Matrix.ServerName); err != nil {
return httputil.LogThenError(r.req, err)
}
return util.JSONResponse{
Code: 200,
JSON: struct {
RoomID string `json:"room_id"`
}{roomID},
}
} }
if len(servers) == 0 { if len(servers) == 0 {