From 8e91572ec9fffef980ba75b18ac8615fd7e99376 Mon Sep 17 00:00:00 2001 From: fabio Date: Thu, 8 Oct 2026 13:05:03 +0200 Subject: [PATCH] feat: enable data publishing permission and enrich participant data with user profiles --- videochat/livekit.go | 2 +- videochat/livekit_test.go | 4 ++-- videochat/participants.go | 45 ++++++++++++++++++++++++++++++++++----- 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/videochat/livekit.go b/videochat/livekit.go index d615479..1a6ce94 100644 --- a/videochat/livekit.go +++ b/videochat/livekit.go @@ -135,7 +135,7 @@ func signJoinToken(key, secret, identity, room string, owner bool) (string, erro grant := &lkauth.VideoGrant{RoomJoin: true, Room: room} grant.SetCanPublish(owner) grant.SetCanSubscribe(true) - grant.SetCanPublishData(false) + grant.SetCanPublishData(true) grant.SetCanUpdateOwnMetadata(false) return lkauth.NewAccessToken(key, secret). SetIdentity(identity). diff --git a/videochat/livekit_test.go b/videochat/livekit_test.go index 279a898..ef6da48 100644 --- a/videochat/livekit_test.go +++ b/videochat/livekit_test.go @@ -36,7 +36,7 @@ func TestJoinTokenPermissions(t *testing.T) { t.Fatal("unexpected token issuer or identity") } g := grants.Video - if g == nil || g.Room != "demo" || !g.RoomJoin || !g.GetCanPublish() || !g.GetCanSubscribe() || g.GetCanPublishData() || g.GetCanUpdateOwnMetadata() { + if g == nil || g.Room != "demo" || !g.RoomJoin || !g.GetCanPublish() || !g.GetCanSubscribe() || !g.GetCanPublishData() || g.GetCanUpdateOwnMetadata() { t.Fatalf("unexpected participant grants: %+v", g) } if g.RoomAdmin || g.RoomCreate || g.RoomList || g.RoomRecord { @@ -105,7 +105,7 @@ func TestViewerTokenCannotPublish(t *testing.T) { t.Fatal(err) } g := grants.Video - if g.GetCanPublish() || g.GetCanPublishData() || g.GetCanUpdateOwnMetadata() || !g.GetCanSubscribe() || g.RoomAdmin || g.RoomCreate { + if g.GetCanPublish() || !g.GetCanPublishData() || g.GetCanUpdateOwnMetadata() || !g.GetCanSubscribe() || g.RoomAdmin || g.RoomCreate { t.Fatalf("unsafe viewer permissions: %+v", g) } } diff --git a/videochat/participants.go b/videochat/participants.go index 6e7104a..347f2fc 100644 --- a/videochat/participants.go +++ b/videochat/participants.go @@ -10,10 +10,11 @@ import ( ) type Participant struct { - SID string `json:"sid"` - Identity string `json:"identity"` - Name string `json:"name"` - State string `json:"state"` + SID string `json:"sid"` + Identity string `json:"identity"` + Name string `json:"name"` + State string `json:"state"` + AvatarURL string `json:"avatar_url,omitempty"` } type ListParticipantsResponse struct { @@ -43,10 +44,44 @@ func ListParticipants(ctx context.Context, roomName string) (*ListParticipantsRe if err != nil { return nil, liveKitError(err) } + + identities := make([]string, 0, len(result.Participants)) + for _, p := range result.Participants { + identities = append(identities, p.Identity) + } + + avatars := make(map[string]string) + names := make(map[string]string) + if len(identities) > 0 { + rows, err := profilesDB.Query(ctx, ` + SELECT user_id::text, display_name, avatar_url + FROM user_profiles + WHERE user_id::text = ANY($1) + `, identities) + if err == nil { + defer rows.Close() + for rows.Next() { + var uid, dName, av string + if err := rows.Scan(&uid, &dName, &av); err == nil { + avatars[uid] = av + names[uid] = dName + } + } + } + } + response := &ListParticipantsResponse{Participants: make([]*Participant, 0, len(result.Participants))} for _, p := range result.Participants { + displayName := p.Name + if d, ok := names[p.Identity]; ok && d != "" { + displayName = d + } response.Participants = append(response.Participants, &Participant{ - SID: p.Sid, Identity: p.Identity, Name: p.Name, State: p.State.String(), + SID: p.Sid, + Identity: p.Identity, + Name: displayName, + State: p.State.String(), + AvatarURL: avatars[p.Identity], }) } return response, nil