Handle cases where accepting invites doesn't work for historic rooms

This commit is contained in:
Neil Alexander 2020-05-13 15:06:42 +01:00
parent bdddd83753
commit acbf857d27
2 changed files with 46 additions and 20 deletions

View file

@ -121,6 +121,22 @@ func (r *RoomserverInternalAPI) performJoinRoomByID(
return fmt.Errorf("eb.SetContent: %w", err) return fmt.Errorf("eb.SetContent: %w", err)
} }
// First work out if this is in response to an existing invite.
// If it is then we avoid the situation where we might think we
// know about a room in the following section but don't know the
// latest state as all of our users have left.
isInvitePending, inviteSender, err := r.isInvitePending(ctx, req.RoomIDOrAlias, req.UserID)
if err == nil && isInvitePending {
// Add the server of the person who invited us to the server list,
// as they should be a fairly good bet.
if _, inviterDomain, ierr := gomatrixserverlib.SplitID('!', inviteSender); ierr == nil {
req.ServerNames = append(req.ServerNames, inviterDomain)
}
// Perform a federated room join.
return r.performFederatedJoinRoomByID(ctx, req, res)
}
// Try to construct an actual join event from the template. // Try to construct an actual join event from the template.
// If this succeeds then it is a sign that the room already exists // If this succeeds then it is a sign that the room already exists
// locally on the homeserver. // locally on the homeserver.
@ -178,21 +194,32 @@ func (r *RoomserverInternalAPI) performJoinRoomByID(
return fmt.Errorf("Room ID %q does not exist", req.RoomIDOrAlias) return fmt.Errorf("Room ID %q does not exist", req.RoomIDOrAlias)
} }
// Try joining by all of the supplied server names. // Perform a federated room join.
fedReq := fsAPI.PerformJoinRequest{ return r.performFederatedJoinRoomByID(ctx, req, res)
RoomID: req.RoomIDOrAlias, // the room ID to try and join
UserID: req.UserID, // the user ID joining the room
ServerNames: req.ServerNames, // the server to try joining with
Content: req.Content, // the membership event content
}
fedRes := fsAPI.PerformJoinResponse{}
err = r.fsAPI.PerformJoin(ctx, &fedReq, &fedRes)
if err != nil {
return fmt.Errorf("Error joining federated room: %q", err)
}
default: default:
return fmt.Errorf("Error joining room %q: %w", req.RoomIDOrAlias, err) // Something else went wrong.
return fmt.Errorf("Error joining local room: %q", err)
}
return nil
}
func (r *RoomserverInternalAPI) performFederatedJoinRoomByID(
ctx context.Context,
req *api.PerformJoinRequest,
res *api.PerformJoinResponse, // nolint:unparam
) error {
// Try joining by all of the supplied server names.
fedReq := fsAPI.PerformJoinRequest{
RoomID: req.RoomIDOrAlias, // the room ID to try and join
UserID: req.UserID, // the user ID joining the room
ServerNames: req.ServerNames, // the server to try joining with
Content: req.Content, // the membership event content
}
fedRes := fsAPI.PerformJoinResponse{}
if err := r.fsAPI.PerformJoin(ctx, &fedReq, &fedRes); err != nil {
return fmt.Errorf("Error joining federated room: %q", err)
} }
return nil return nil

View file

@ -38,7 +38,7 @@ func (r *RoomserverInternalAPI) performLeaveRoomByID(
) error { ) error {
// If there's an invite outstanding for the room then respond to // If there's an invite outstanding for the room then respond to
// that. // that.
isInvitePending, senderUser, err := r.isInvitePending(ctx, req, res) isInvitePending, senderUser, err := r.isInvitePending(ctx, req.RoomID, req.UserID)
if err == nil && isInvitePending { if err == nil && isInvitePending {
return r.performRejectInvite(ctx, req, res, senderUser) return r.performRejectInvite(ctx, req, res, senderUser)
} }
@ -160,23 +160,22 @@ func (r *RoomserverInternalAPI) performRejectInvite(
func (r *RoomserverInternalAPI) isInvitePending( func (r *RoomserverInternalAPI) isInvitePending(
ctx context.Context, ctx context.Context,
req *api.PerformLeaveRequest, roomID, userID string,
res *api.PerformLeaveResponse, // nolint:unparam
) (bool, string, error) { ) (bool, string, error) {
// Look up the room NID for the supplied room ID. // Look up the room NID for the supplied room ID.
roomNID, err := r.DB.RoomNID(ctx, req.RoomID) roomNID, err := r.DB.RoomNID(ctx, roomID)
if err != nil { if err != nil {
return false, "", fmt.Errorf("r.DB.RoomNID: %w", err) return false, "", fmt.Errorf("r.DB.RoomNID: %w", err)
} }
// Look up the state key NID for the supplied user ID. // Look up the state key NID for the supplied user ID.
targetUserNIDs, err := r.DB.EventStateKeyNIDs(ctx, []string{req.UserID}) targetUserNIDs, err := r.DB.EventStateKeyNIDs(ctx, []string{userID})
if err != nil { if err != nil {
return false, "", fmt.Errorf("r.DB.EventStateKeyNIDs: %w", err) return false, "", fmt.Errorf("r.DB.EventStateKeyNIDs: %w", err)
} }
targetUserNID, targetUserFound := targetUserNIDs[req.UserID] targetUserNID, targetUserFound := targetUserNIDs[userID]
if !targetUserFound { if !targetUserFound {
return false, "", fmt.Errorf("missing NID for user %q (%+v)", req.UserID, targetUserNIDs) return false, "", fmt.Errorf("missing NID for user %q (%+v)", userID, targetUserNIDs)
} }
// Let's see if we have an event active for the user in the room. If // Let's see if we have an event active for the user in the room. If