Merge branch 'hs/as-transaction-send-if-in-room' into hs/fix-appsevice-alias-queries-part-2

This commit is contained in:
Will Hunt 2021-03-03 16:16:43 +00:00
commit f1f4255e9c
7 changed files with 65 additions and 22 deletions

View file

@ -85,9 +85,6 @@ func (s *OutputRoomEventConsumer) onMessage(msg *sarama.ConsumerMessage) error {
}
if output.Type != api.OutputTypeNewRoomEvent {
log.WithField("type", output.Type).Debug(
"roomserver output log: ignoring unknown output type",
)
return nil
}
@ -114,6 +111,7 @@ func (s *OutputRoomEventConsumer) filterRoomserverEvents(
// Queue this event to be sent off to the application service
if err := s.asDB.StoreEvent(ctx, ws.AppService.ID, event); err != nil {
log.WithError(err).Warn("failed to insert incoming event into appservices database")
return err
} else {
// Tell our worker to send out new messages by updating remaining message
// count and waking them up with a broadcast
@ -126,25 +124,29 @@ func (s *OutputRoomEventConsumer) filterRoomserverEvents(
return nil
}
// appserviceHasMembershipInRoom returns a boolean depending on whether a given
// appserviceJoinedAtEvent returns a boolean depending on whether a given
// appservice has membership at the time a given event was created.
func (s *OutputRoomEventConsumer) appserviceHasMembershipForEvent(ctx context.Context, event *gomatrixserverlib.HeaderedEvent, appservice config.ApplicationService) bool {
// Check if any of the members in the room match the appservice
membershipReq := api.QueryStateAfterEventsRequest{
PrevEventIDs: []string{event.EventID()},
RoomID: event.RoomID(),
func (s *OutputRoomEventConsumer) appserviceJoinedAtEvent(ctx context.Context, event *gomatrixserverlib.HeaderedEvent, appservice config.ApplicationService) bool {
// TODO: This is only checking the current room state, not the state at
// the event in question. Pretty sure this is what Synapse does too, but
// until we have a lighter way of checking the state before the event that
// doesn't involve state res, then this is probably OK.
membershipReq := &api.QueryMembershipsForRoomRequest{
RoomID: event.RoomID(),
JoinedOnly: true,
}
var membershipRes api.QueryStateAfterEventsResponse
membershipRes := &api.QueryMembershipsForRoomResponse{}
// XXX: This could potentially race if the state for the event is not known yet
// e.g. the event came over federation but we do not have the full state persisted.
if err := s.rsAPI.QueryStateAfterEvents(ctx, &membershipReq, &membershipRes); err == nil {
for _, ev := range membershipRes.StateEvents {
if ev.Type() == gomatrixserverlib.MRoomMember {
var membership, _ = ev.Membership()
if membership == gomatrixserverlib.Join && appservice.IsInterestedInUserID(*ev.StateKey()) {
return true
}
if err := s.rsAPI.QueryMembershipsForRoom(ctx, membershipReq, membershipRes); err == nil {
for _, ev := range membershipRes.JoinEvents {
var membership gomatrixserverlib.MemberContent
if err = json.Unmarshal(ev.Content, &membership); err != nil || ev.StateKey == nil {
continue
}
if appservice.IsInterestedInUserID(*ev.StateKey) {
return true
}
}
} else {
@ -194,5 +196,5 @@ func (s *OutputRoomEventConsumer) appserviceIsInterestedInEvent(ctx context.Cont
}
// Check if any of the members in the room match the appservice
return s.appserviceHasMembershipForEvent(ctx, event, appservice)
return s.appserviceJoinedAtEvent(ctx, event, appservice)
}

View file

@ -62,7 +62,7 @@ func SetupTransactionWorkers(
func worker(db storage.Database, ws types.ApplicationServiceWorkerState) {
log.WithFields(log.Fields{
"appservice": ws.AppService.ID,
}).Info("starting application service")
}).Info("Starting application service")
ctx := context.Background()
// Create a HTTP client for sending requests to app services

View file

@ -103,8 +103,22 @@ func GetEvent(
}
}
var appService *config.ApplicationService
if device.AppserviceID != "" {
for _, as := range cfg.Derived.ApplicationServices {
if as.ID == device.AppserviceID {
appService = &as
break
}
}
}
for _, stateEvent := range stateResp.StateEvents {
if !stateEvent.StateKeyEquals(device.UserID) {
if appService != nil {
if !appService.IsInterestedInUserID(*stateEvent.StateKey()) {
continue
}
} else if !stateEvent.StateKeyEquals(device.UserID) {
continue
}
membership, err := stateEvent.Membership()

View file

@ -151,7 +151,9 @@ type QueryMembershipsForRoomRequest struct {
JoinedOnly bool `json:"joined_only"`
// ID of the room to fetch memberships from
RoomID string `json:"room_id"`
// ID of the user sending the request
// Optional - ID of the user sending the request, for checking if the
// user is allowed to see the memberships. If not specified then all
// room memberships will be returned.
Sender string `json:"sender"`
}

View file

@ -242,6 +242,27 @@ func (r *Queryer) QueryMembershipsForRoom(
return err
}
// If no sender is specified then we will just return the entire
// set of memberships for the room, regardless of whether a specific
// user is allowed to see them or not.
if request.Sender == "" {
var events []types.Event
var eventNIDs []types.EventNID
eventNIDs, err = r.DB.GetMembershipEventNIDsForRoom(ctx, info.RoomNID, request.JoinedOnly, false)
if err != nil {
return fmt.Errorf("r.DB.GetMembershipEventNIDsForRoom: %w", err)
}
events, err = r.DB.Events(ctx, eventNIDs)
if err != nil {
return fmt.Errorf("r.DB.Events: %w", err)
}
for _, event := range events {
clientEvent := gomatrixserverlib.ToClientEvent(event.Event, gomatrixserverlib.FormatAll)
response.JoinEvents = append(response.JoinEvents, clientEvent)
}
return nil
}
membershipEventNID, stillInRoom, isRoomforgotten, err := r.DB.GetMembership(ctx, info.RoomNID, request.Sender)
if err != nil {
return err

View file

@ -241,6 +241,9 @@ type Device struct {
LastSeenTS int64
LastSeenIP string
UserAgent string
// If the device is for an appservice user,
// this is the appservice ID.
AppserviceID string
}
// Account represents a Matrix account on this home server.

View file

@ -381,7 +381,8 @@ func (a *UserInternalAPI) queryAppServiceToken(ctx context.Context, token, appSe
// Use AS dummy device ID
ID: types.AppServiceDeviceID,
// AS dummy device has AS's token.
AccessToken: token,
AccessToken: token,
AppserviceID: appService.ID,
}
localpart, err := userutil.ParseUsernameParam(appServiceUserID, &a.ServerName)