From 7f03ffff55e5976d688288934da85505ae77993f Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Thu, 29 Aug 2024 14:53:27 +0200 Subject: [PATCH] Include actor information in room join/leave events for fed. sessions. --- api_backend.go | 16 ++++++++++- clientsession.go | 1 + federation_test.go | 66 ++++++++++++++++++++++++++++++++++++---------- hub.go | 1 + hub_test.go | 19 +++++++++++++ testclient_test.go | 14 ++++++---- 6 files changed, 97 insertions(+), 20 deletions(-) diff --git a/api_backend.go b/api_backend.go index c1daf37..2fd0bc9 100644 --- a/api_backend.go +++ b/api_backend.go @@ -296,12 +296,26 @@ type BackendClientRoomRequest struct { UserId string `json:"userid"` SessionId string `json:"sessionid"` - // For Nextcloud Talk with SIP support. + // For Nextcloud Talk with SIP support and for federated sessions. ActorId string `json:"actorid,omitempty"` ActorType string `json:"actortype,omitempty"` InCall int `json:"incall,omitempty"` } +func (r *BackendClientRoomRequest) UpdateFromSession(s Session) { + if s.ClientType() == HelloClientTypeFederation { + // Need to send additional data for requests of federated users. + if u, err := s.ParsedUserData(); err == nil && len(u) > 0 { + if actorType, found := getStringMapEntry[string](u, "actorType"); found { + if actorId, found := getStringMapEntry[string](u, "actorId"); found { + r.ActorId = actorId + r.ActorType = actorType + } + } + } + } +} + func NewBackendClientRoomRequest(roomid string, userid string, sessionid string) *BackendClientRequest { return &BackendClientRequest{ Type: "room", diff --git a/clientsession.go b/clientsession.go index a8265ab..9b5b9da 100644 --- a/clientsession.go +++ b/clientsession.go @@ -560,6 +560,7 @@ func (s *ClientSession) doUnsubscribeRoomEvents(notify bool) { go func(sid string) { ctx := context.Background() request := NewBackendClientRoomRequest(room.Id(), s.userId, sid) + request.Room.UpdateFromSession(s) request.Room.Action = "leave" var response map[string]interface{} if err := s.hub.backend.PerformJSONRequest(ctx, s.ParsedBackendUrl(), request, &response); err != nil { diff --git a/federation_test.go b/federation_test.go index 25b6be4..f672457 100644 --- a/federation_test.go +++ b/federation_test.go @@ -109,7 +109,12 @@ func Test_Federation(t *testing.T) { require.NotNil(room) now := time.Now() - token, err := client1.CreateHelloV2Token(testDefaultUserId+"2", now, now.Add(time.Minute)) + userdata := map[string]interface{}{ + "displayname": "Federated user", + "actorType": "federated_users", + "actorId": "the-federated-user-id", + } + token, err := client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"2", now, now.Add(time.Minute), userdata) require.NoError(err) msg := &ClientMessage{ @@ -424,18 +429,24 @@ func Test_Federation(t *testing.T) { hello4, err := client4.RunUntilHello(ctx) require.NoError(err) - token, err = client4.CreateHelloV2Token(testDefaultUserId+"4", now, now.Add(time.Minute)) + userdata = map[string]interface{}{ + "displayname": "Federated user 2", + "actorType": "federated_users", + "actorId": "the-other-federated-user-id", + } + token, err = client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"4", now, now.Add(time.Minute), userdata) require.NoError(err) msg = &ClientMessage{ Id: "join-room-fed", Type: "room", Room: &RoomClientMessage{ - RoomId: roomId, - SessionId: roomId + "-" + hello4.Hello.SessionId, + RoomId: federatedRoomId, + SessionId: federatedRoomId + "-" + hello4.Hello.SessionId, Federation: &RoomFederationMessage{ SignalingUrl: server1.URL, NextcloudUrl: server1.URL, + RoomId: roomId, Token: token, }, }, @@ -445,10 +456,10 @@ func Test_Federation(t *testing.T) { if message, err := client4.RunUntilMessage(ctx); assert.NoError(err) { assert.Equal(msg.Id, message.Id) require.Equal("room", message.Type) - require.Equal(roomId, message.Room.RoomId) + require.Equal(federatedRoomId, message.Room.RoomId) } - // The client1 will see the remote session id for client2. + // The client1 will see the remote session id for client4. var remoteSessionId4 string if message, err := client1.RunUntilMessage(ctx); assert.NoError(err) { assert.NoError(client1.checkSingleMessageJoined(message)) @@ -514,7 +525,12 @@ func Test_FederationJoinRoomTwice(t *testing.T) { assert.NoError(client1.RunUntilJoined(ctx, hello1.Hello)) now := time.Now() - token, err := client1.CreateHelloV2Token(testDefaultUserId+"2", now, now.Add(time.Minute)) + userdata := map[string]interface{}{ + "displayname": "Federated user", + "actorType": "federated_users", + "actorId": "the-federated-user-id", + } + token, err := client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"2", now, now.Add(time.Minute), userdata) require.NoError(err) msg := &ClientMessage{ @@ -620,7 +636,12 @@ func Test_FederationChangeRoom(t *testing.T) { assert.NoError(client1.RunUntilJoined(ctx, hello1.Hello)) now := time.Now() - token, err := client1.CreateHelloV2Token(testDefaultUserId+"2", now, now.Add(time.Minute)) + userdata := map[string]interface{}{ + "displayname": "Federated user", + "actorType": "federated_users", + "actorId": "the-federated-user-id", + } + token, err := client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"2", now, now.Add(time.Minute), userdata) require.NoError(err) msg := &ClientMessage{ @@ -734,6 +755,7 @@ func Test_FederationMedia(t *testing.T) { require.NoError(err) roomId := "test-room" + federatedRooId := roomId + "@federated" room1, err := client1.JoinRoom(ctx, roomId) require.NoError(err) require.Equal(roomId, room1.Room.RoomId) @@ -741,18 +763,24 @@ func Test_FederationMedia(t *testing.T) { assert.NoError(client1.RunUntilJoined(ctx, hello1.Hello)) now := time.Now() - token, err := client1.CreateHelloV2Token(testDefaultUserId+"2", now, now.Add(time.Minute)) + userdata := map[string]interface{}{ + "displayname": "Federated user", + "actorType": "federated_users", + "actorId": "the-federated-user-id", + } + token, err := client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"2", now, now.Add(time.Minute), userdata) require.NoError(err) msg := &ClientMessage{ Id: "join-room-fed", Type: "room", Room: &RoomClientMessage{ - RoomId: roomId, - SessionId: roomId + "-" + hello2.Hello.SessionId, + RoomId: federatedRooId, + SessionId: federatedRooId + "-" + hello2.Hello.SessionId, Federation: &RoomFederationMessage{ SignalingUrl: server1.URL, NextcloudUrl: server1.URL, + RoomId: roomId, Token: token, }, }, @@ -762,7 +790,7 @@ func Test_FederationMedia(t *testing.T) { if message, err := client2.RunUntilMessage(ctx); assert.NoError(err) { assert.Equal(msg.Id, message.Id) require.Equal("room", message.Type) - require.Equal(roomId, message.Room.RoomId) + require.Equal(federatedRooId, message.Room.RoomId) } // The client1 will see the remote session id for client2. @@ -832,7 +860,12 @@ func Test_FederationResume(t *testing.T) { assert.NoError(client1.RunUntilJoined(ctx, hello1.Hello)) now := time.Now() - token, err := client1.CreateHelloV2Token(testDefaultUserId+"2", now, now.Add(time.Minute)) + userdata := map[string]interface{}{ + "displayname": "Federated user", + "actorType": "federated_users", + "actorId": "the-federated-user-id", + } + token, err := client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"2", now, now.Add(time.Minute), userdata) require.NoError(err) msg := &ClientMessage{ @@ -960,7 +993,12 @@ func Test_FederationResumeNewSession(t *testing.T) { assert.NoError(client1.RunUntilJoined(ctx, hello1.Hello)) now := time.Now() - token, err := client1.CreateHelloV2Token(testDefaultUserId+"2", now, now.Add(time.Minute)) + userdata := map[string]interface{}{ + "displayname": "Federated user", + "actorType": "federated_users", + "actorId": "the-federated-user-id", + } + token, err := client1.CreateHelloV2TokenWithUserdata(testDefaultUserId+"2", now, now.Add(time.Minute), userdata) require.NoError(err) msg := &ClientMessage{ diff --git a/hub.go b/hub.go index a4ed39a..3808559 100644 --- a/hub.go +++ b/hub.go @@ -1695,6 +1695,7 @@ func (h *Hub) processRoom(sess Session, message *ClientMessage) { sessionId = session.PublicId() } request := NewBackendClientRoomRequest(roomId, session.UserId(), sessionId) + request.Room.UpdateFromSession(session) if err := h.backend.PerformJSONRequest(ctx, session.ParsedBackendUrl(), request, &room); err != nil { session.SendMessage(message.NewWrappedErrorServerMessage(err)) return diff --git a/hub_test.go b/hub_test.go index a3646ec..ee68e97 100644 --- a/hub_test.go +++ b/hub_test.go @@ -420,6 +420,25 @@ func processRoomRequest(t *testing.T, w http.ResponseWriter, r *http.Request, re } } + if strings.Contains(t.Name(), "Federation") { + // Check additional fields present for federated sessions. + if strings.Contains(request.Room.SessionId, "@federated") { + if actorType := request.Room.ActorType; actorType != ActorTypeFederatedUsers { + t.Errorf("expected actorType %s, received %+v", ActorTypeFederatedUsers, request.Room) + } + if actorId := request.Room.ActorId; actorId == "" { + t.Errorf("expected actorId, received %+v", request.Room) + } + } else { + if actorType := request.Room.ActorType; actorType != "" { + t.Errorf("expected empty actorType, received %+v", request.Room) + } + if actorId := request.Room.ActorId; actorId != "" { + t.Errorf("expected empty actorId, received %+v", request.Room) + } + } + } + // Allow joining any room. response := &BackendClientResponse{ Type: "room", diff --git a/testclient_test.go b/testclient_test.go index e65d1fa..2c02ad5 100644 --- a/testclient_test.go +++ b/testclient_test.go @@ -401,11 +401,7 @@ func (c *TestClient) SendHelloV2(userid string) error { return c.SendHelloV2WithTimes(userid, now, now.Add(time.Minute)) } -func (c *TestClient) CreateHelloV2Token(userid string, issuedAt time.Time, expiresAt time.Time) (string, error) { - userdata := map[string]string{ - "displayname": "Displayname " + userid, - } - +func (c *TestClient) CreateHelloV2TokenWithUserdata(userid string, issuedAt time.Time, expiresAt time.Time, userdata map[string]interface{}) (string, error) { data, err := json.Marshal(userdata) if err != nil { return "", err @@ -437,6 +433,14 @@ func (c *TestClient) CreateHelloV2Token(userid string, issuedAt time.Time, expir return token.SignedString(private) } +func (c *TestClient) CreateHelloV2Token(userid string, issuedAt time.Time, expiresAt time.Time) (string, error) { + userdata := map[string]interface{}{ + "displayname": "Displayname " + userid, + } + + return c.CreateHelloV2TokenWithUserdata(userid, issuedAt, expiresAt, userdata) +} + func (c *TestClient) SendHelloV2WithTimes(userid string, issuedAt time.Time, expiresAt time.Time) error { tokenString, err := c.CreateHelloV2Token(userid, issuedAt, expiresAt) if err != nil {