diff --git a/server/src/api/boards.go b/server/src/api/boards.go index 7b4f67d366..0b5f789e0b 100644 --- a/server/src/api/boards.go +++ b/server/src/api/boards.go @@ -365,8 +365,8 @@ func (s *Server) exportBoard(w http.ResponseWriter, r *http.Request) { author := note.Author.String() for _, session := range fullBoard.BoardSessions { - if session.User.ID == note.Author { - author = session.User.Name + if session.User == note.Author { + author = session.User.String() } } diff --git a/server/src/api/event_filter.go b/server/src/api/event_filter.go index 7c03a552ac..87f68fd277 100644 --- a/server/src/api/event_filter.go +++ b/server/src/api/event_filter.go @@ -12,7 +12,7 @@ import ( func isModerator(clientID uuid.UUID, sessions []*dto.BoardSession) bool { for _, session := range sessions { - if clientID == session.User.ID { + if clientID == session.User { if session.Role == types.SessionRoleModerator || session.Role == types.SessionRoleOwner { return true } @@ -290,7 +290,7 @@ func (boardSubscription *BoardSubscription) eventFilter(event *realtime.BoardEve return &ret } - if event.Type == realtime.BoardEventParticipantUpdated { + if event.Type == realtime.BoardEventParticipantSessionUpdated { participant, err := parseParticipantUpdated(event.Data) if err != nil { logger.Get().Errorw("unable to parse participantUpdated in event filter", "board", boardSubscription.boardSettings.ID, "session", userID, "err", err) @@ -299,7 +299,7 @@ func (boardSubscription *BoardSubscription) eventFilter(event *realtime.BoardEve if isMod { // Cache the changes of when a participant got updated for idx, user := range boardSubscription.boardParticipants { - if user.User.ID == participant.User.ID { + if participant.User == user.User { boardSubscription.boardParticipants[idx] = participant } } diff --git a/server/src/api/event_filter_test.go b/server/src/api/event_filter_test.go index 1d599a555b..57780be919 100644 --- a/server/src/api/event_filter_test.go +++ b/server/src/api/event_filter_test.go @@ -12,15 +12,15 @@ import ( var ( moderatorBoardSession = dto.BoardSession{ - User: dto.User{ID: uuid.New()}, + User: uuid.New(), Role: types.SessionRoleModerator, } ownerBoardSession = dto.BoardSession{ - User: dto.User{ID: uuid.New()}, + User: uuid.New(), Role: types.SessionRoleOwner, } participantBoardSession = dto.BoardSession{ - User: dto.User{ID: uuid.New()}, + User: uuid.New(), Role: types.SessionRoleParticipant, } boardSessions = []*dto.BoardSession{ @@ -44,7 +44,7 @@ var ( } aModeratorNote = dto.Note{ ID: uuid.New(), - Author: moderatorBoardSession.User.ID, + Author: moderatorBoardSession.User, Text: "Moderator Text", Position: dto.NotePosition{ Column: aSeeableColumn.ID, @@ -54,7 +54,7 @@ var ( } aParticipantNote = dto.Note{ ID: uuid.New(), - Author: participantBoardSession.User.ID, + Author: participantBoardSession.User, Text: "User Text", Position: dto.NotePosition{ Column: aSeeableColumn.ID, @@ -71,7 +71,7 @@ var ( } aOwnerNote = dto.Note{ ID: uuid.New(), - Author: ownerBoardSession.User.ID, + Author: ownerBoardSession.User, Text: "Owner Text", Position: dto.NotePosition{ Column: aHiddenColumn.ID, @@ -134,12 +134,12 @@ var ( initEvent = InitEvent{ Type: realtime.BoardEventInit, Data: dto.FullBoard{ - Board: &dto.Board{}, - Columns: []*dto.Column{&aSeeableColumn, &aHiddenColumn}, - Notes: []*dto.Note{&aOwnerNote, &aModeratorNote, &aParticipantNote}, - Votings: []*dto.Voting{votingData.Voting}, - Votes: []*dto.Vote{}, - BoardSessions: boardSessions, + Board: &dto.Board{}, + Columns: []*dto.Column{&aSeeableColumn, &aHiddenColumn}, + Notes: []*dto.Note{&aOwnerNote, &aModeratorNote, &aParticipantNote}, + Votings: []*dto.Voting{votingData.Voting}, + Votes: []*dto.Vote{}, + BoardSessions: boardSessions, BoardSessionRequests: []*dto.BoardSessionRequest{}, }, } @@ -170,7 +170,7 @@ func TestEventFilter(t *testing.T) { } func testIsModModerator(t *testing.T) { - isMod := isModerator(moderatorBoardSession.User.ID, boardSessions) + isMod := isModerator(moderatorBoardSession.User, boardSessions) assert.NotNil(t, isMod) assert.True(t, isMod) @@ -178,7 +178,7 @@ func testIsModModerator(t *testing.T) { } func testIsOwnerModerator(t *testing.T) { - isMod := isModerator(ownerBoardSession.User.ID, boardSessions) + isMod := isModerator(ownerBoardSession.User, boardSessions) assert.NotNil(t, isMod) assert.True(t, isMod) @@ -186,7 +186,7 @@ func testIsOwnerModerator(t *testing.T) { } func testIsParticipantModerator(t *testing.T) { - isMod := isModerator(participantBoardSession.User.ID, boardSessions) + isMod := isModerator(participantBoardSession.User, boardSessions) assert.NotNil(t, isMod) assert.False(t, isMod) @@ -240,7 +240,7 @@ func testColumnFilterAsParticipant(t *testing.T) { Type: realtime.BoardEventColumnsUpdated, Data: []*dto.Column{&aSeeableColumn}, } - returnedColumnEvent := boardSub.eventFilter(columnEvent, participantBoardSession.User.ID) + returnedColumnEvent := boardSub.eventFilter(columnEvent, participantBoardSession.User) assert.Equal(t, expectedColumnEvent, returnedColumnEvent) } @@ -250,7 +250,7 @@ func testColumnFilterAsOwner(t *testing.T) { Type: realtime.BoardEventColumnsUpdated, Data: []*dto.Column{&aSeeableColumn, &aHiddenColumn}, } - returnedColumnEvent := boardSub.eventFilter(columnEvent, ownerBoardSession.User.ID) + returnedColumnEvent := boardSub.eventFilter(columnEvent, ownerBoardSession.User) assert.Equal(t, expectedColumnEvent, returnedColumnEvent) } @@ -261,7 +261,7 @@ func testColumnFilterAsModerator(t *testing.T) { Data: []*dto.Column{&aSeeableColumn, &aHiddenColumn}, } - returnedColumnEvent := boardSub.eventFilter(columnEvent, moderatorBoardSession.User.ID) + returnedColumnEvent := boardSub.eventFilter(columnEvent, moderatorBoardSession.User) assert.Equal(t, expectedColumnEvent, returnedColumnEvent) } @@ -271,7 +271,7 @@ func testNoteFilterAsParticipant(t *testing.T) { Type: realtime.BoardEventNotesUpdated, Data: []*dto.Note{&aParticipantNote}, } - returnedNoteEvent := boardSub.eventFilter(noteEvent, participantBoardSession.User.ID) + returnedNoteEvent := boardSub.eventFilter(noteEvent, participantBoardSession.User) assert.Equal(t, expectedNoteEvent, returnedNoteEvent) } @@ -281,7 +281,7 @@ func testNoteFilterAsOwner(t *testing.T) { Type: realtime.BoardEventNotesUpdated, Data: []*dto.Note{&aParticipantNote, &aModeratorNote, &aOwnerNote}, } - returnedNoteEvent := boardSub.eventFilter(noteEvent, ownerBoardSession.User.ID) + returnedNoteEvent := boardSub.eventFilter(noteEvent, ownerBoardSession.User) assert.Equal(t, expectedNoteEvent, returnedNoteEvent) } @@ -291,7 +291,7 @@ func testNoteFilterAsModerator(t *testing.T) { Type: realtime.BoardEventNotesUpdated, Data: []*dto.Note{&aParticipantNote, &aModeratorNote, &aOwnerNote}, } - returnedNoteEvent := boardSub.eventFilter(noteEvent, moderatorBoardSession.User.ID) + returnedNoteEvent := boardSub.eventFilter(noteEvent, moderatorBoardSession.User) assert.Equal(t, expectedNoteEvent, returnedNoteEvent) } @@ -301,7 +301,7 @@ func testFilterVotingUpdatedAsOwner(t *testing.T) { Type: realtime.BoardEventVotingUpdated, Data: votingData, } - returnedVoteEvent := boardSub.eventFilter(votingEvent, ownerBoardSession.User.ID) + returnedVoteEvent := boardSub.eventFilter(votingEvent, ownerBoardSession.User) assert.NotNil(t, returnedVoteEvent) assert.Equal(t, expectedVotingEvent, returnedVoteEvent) @@ -312,7 +312,7 @@ func testFilterVotingUpdatedAsModerator(t *testing.T) { Type: realtime.BoardEventVotingUpdated, Data: votingData, } - returnedVoteEvent := boardSub.eventFilter(votingEvent, moderatorBoardSession.User.ID) + returnedVoteEvent := boardSub.eventFilter(votingEvent, moderatorBoardSession.User) assert.NotNil(t, returnedVoteEvent) assert.Equal(t, expectedVotingEvent, returnedVoteEvent) @@ -342,7 +342,7 @@ func testFilterVotingUpdatedAsParticipant(t *testing.T) { Type: realtime.BoardEventVotingUpdated, Data: expectedVoting, } - returnedVoteEvent := boardSub.eventFilter(votingEvent, participantBoardSession.User.ID) + returnedVoteEvent := boardSub.eventFilter(votingEvent, participantBoardSession.User) assert.NotNil(t, returnedVoteEvent) assert.Equal(t, expectedVotingEvent, returnedVoteEvent) @@ -350,14 +350,14 @@ func testFilterVotingUpdatedAsParticipant(t *testing.T) { func testInitFilterAsOwner(t *testing.T) { expectedInitEvent := initEvent - returnedInitEvent := eventInitFilter(initEvent, ownerBoardSession.User.ID) + returnedInitEvent := eventInitFilter(initEvent, ownerBoardSession.User) assert.Equal(t, expectedInitEvent, returnedInitEvent) } func testInitFilterAsModerator(t *testing.T) { expectedInitEvent := initEvent - returnedInitEvent := eventInitFilter(initEvent, moderatorBoardSession.User.ID) + returnedInitEvent := eventInitFilter(initEvent, moderatorBoardSession.User) assert.Equal(t, expectedInitEvent, returnedInitEvent) } @@ -382,16 +382,16 @@ func testInitFilterAsParticipant(t *testing.T) { expectedInitEvent := InitEvent{ Type: realtime.BoardEventInit, Data: dto.FullBoard{ - Board: &dto.Board{}, - Columns: []*dto.Column{&aSeeableColumn}, - Notes: []*dto.Note{&aParticipantNote}, - Votings: []*dto.Voting{&expectedVoting}, - Votes: []*dto.Vote{}, - BoardSessions: boardSessions, + Board: &dto.Board{}, + Columns: []*dto.Column{&aSeeableColumn}, + Notes: []*dto.Note{&aParticipantNote}, + Votings: []*dto.Voting{&expectedVoting}, + Votes: []*dto.Vote{}, + BoardSessions: boardSessions, BoardSessionRequests: []*dto.BoardSessionRequest{}, }, } - returnedInitEvent := eventInitFilter(initEvent, participantBoardSession.User.ID) + returnedInitEvent := eventInitFilter(initEvent, participantBoardSession.User) assert.Equal(t, expectedInitEvent, returnedInitEvent) } diff --git a/server/src/common/dto/board_sessions.go b/server/src/common/dto/board_sessions.go index eadd12ebbd..a2c44a8bf6 100644 --- a/server/src/common/dto/board_sessions.go +++ b/server/src/common/dto/board_sessions.go @@ -11,7 +11,7 @@ import ( // BoardSession is the response for all participant requests. type BoardSession struct { - User User `json:"user"` + User uuid.UUID `json:"user"` // Flag indicates whether user is online and connected to the board. Connected bool `json:"connected"` @@ -40,13 +40,7 @@ type BoardSession struct { } func (b *BoardSession) From(session database.BoardSession) *BoardSession { - user := User{ - ID: session.User, - Name: session.Name, - Avatar: session.Avatar, - AccountType: session.AccountType, - } - b.User = user + b.User = session.User b.Connected = session.Connected b.Ready = session.Ready b.RaisedHand = session.RaisedHand diff --git a/server/src/database/board_sessions.go b/server/src/database/board_sessions.go index 8f6efa75e5..1b7f6149fd 100644 --- a/server/src/database/board_sessions.go +++ b/server/src/database/board_sessions.go @@ -225,18 +225,19 @@ func (d *Database) GetBoardSessions(board uuid.UUID, filter ...filter.BoardSessi } // Gets all board sessions of a single user who he is currently connected to -func (d *Database) GetSingleUserConnectedBoards(user uuid.UUID) ([]BoardSession, error) { - var sessions []BoardSession +func (d *Database) GetSingleUserConnectedBoards(user uuid.UUID) ([]uuid.UUID, error) { + var connectedBoards []uuid.UUID err := d.db.NewSelect(). + Model(connectedBoards). TableExpr("board_sessions AS s"). - ColumnExpr("s.board, s.user, u.avatar, u.name, u.account_type, s.connected, s.show_hidden_columns, s.ready, s.raised_hand, s.role, s.banned"). + ColumnExpr("s.board"). Where("s.user = ?", user). Where("s.connected"). Join("INNER JOIN users AS u ON u.id = s.user"). - Scan(context.Background(), &sessions) + Scan(context.Background(), &connectedBoards) if err != nil { return nil, err } - return sessions, err + return connectedBoards, err } diff --git a/server/src/realtime/boards.go b/server/src/realtime/boards.go index b24b7b5a37..f02f5b82d1 100644 --- a/server/src/realtime/boards.go +++ b/server/src/realtime/boards.go @@ -11,27 +11,28 @@ import ( type BoardEventType string const ( - BoardEventInit BoardEventType = "INIT" - BoardEventBoardUpdated BoardEventType = "BOARD_UPDATED" - BoardEventBoardDeleted BoardEventType = "BOARD_DELETED" - BoardEventColumnsUpdated BoardEventType = "COLUMNS_UPDATED" - BoardEventColumnDeleted BoardEventType = "COLUMN_DELETED" - BoardEventNotesUpdated BoardEventType = "NOTES_UPDATED" - BoardEventNoteDeleted BoardEventType = "NOTE_DELETED" - BoardEventNotesSync BoardEventType = "NOTES_SYNC" - BoardEventReactionAdded BoardEventType = "REACTION_ADDED" - BoardEventReactionDeleted BoardEventType = "REACTION_DELETED" - BoardEventReactionUpdated BoardEventType = "REACTION_UPDATED" - BoardEventVotesUpdated BoardEventType = "VOTES_UPDATED" - BoardEventSessionRequestCreated BoardEventType = "REQUEST_CREATED" - BoardEventSessionRequestUpdated BoardEventType = "REQUEST_UPDATED" - BoardEventParticipantCreated BoardEventType = "PARTICIPANT_CREATED" - BoardEventParticipantUpdated BoardEventType = "PARTICIPANT_UPDATED" - BoardEventParticipantsUpdated BoardEventType = "PARTICIPANTS_UPDATED" - BoardEventVotingCreated BoardEventType = "VOTING_CREATED" - BoardEventVotingUpdated BoardEventType = "VOTING_UPDATED" - BoardEventBoardTimerUpdated BoardEventType = "BOARD_TIMER_UPDATED" - BoardEventBoardReactionAdded BoardEventType = "BOARD_REACTION_ADDED" + BoardEventInit BoardEventType = "INIT" + BoardEventBoardUpdated BoardEventType = "BOARD_UPDATED" + BoardEventBoardDeleted BoardEventType = "BOARD_DELETED" + BoardEventColumnsUpdated BoardEventType = "COLUMNS_UPDATED" + BoardEventColumnDeleted BoardEventType = "COLUMN_DELETED" + BoardEventNotesUpdated BoardEventType = "NOTES_UPDATED" + BoardEventNoteDeleted BoardEventType = "NOTE_DELETED" + BoardEventNotesSync BoardEventType = "NOTES_SYNC" + BoardEventReactionAdded BoardEventType = "REACTION_ADDED" + BoardEventReactionDeleted BoardEventType = "REACTION_DELETED" + BoardEventReactionUpdated BoardEventType = "REACTION_UPDATED" + BoardEventVotesUpdated BoardEventType = "VOTES_UPDATED" + BoardEventSessionRequestCreated BoardEventType = "REQUEST_CREATED" + BoardEventSessionRequestUpdated BoardEventType = "REQUEST_UPDATED" + BoardEventParticipantCreated BoardEventType = "PARTICIPANT_CREATED" + BoardEventParticipantUpdated BoardEventType = "PARTICIPANT_UPDATED" + BoardEventParticipantSessionUpdated BoardEventType = "PARTICIPANT_SESSION_UPDATED" + BoardEventParticipantsUpdated BoardEventType = "PARTICIPANTS_UPDATED" + BoardEventVotingCreated BoardEventType = "VOTING_CREATED" + BoardEventVotingUpdated BoardEventType = "VOTING_UPDATED" + BoardEventBoardTimerUpdated BoardEventType = "BOARD_TIMER_UPDATED" + BoardEventBoardReactionAdded BoardEventType = "BOARD_REACTION_ADDED" ) type BoardEvent struct { diff --git a/server/src/services/boards/sessions.go b/server/src/services/boards/sessions.go index a3c7da0988..347c8c503c 100644 --- a/server/src/services/boards/sessions.go +++ b/server/src/services/boards/sessions.go @@ -57,7 +57,7 @@ func (s *BoardSessionService) List(_ context.Context, boardID uuid.UUID, filter func (s *BoardSessionService) Connect(ctx context.Context, boardID, userID uuid.UUID) error { log := logger.FromContext(ctx) var connected = true - updatedSession, err := s.database.UpdateBoardSession(database.BoardSessionUpdate{ + session, err := s.database.UpdateBoardSession(database.BoardSessionUpdate{ Board: boardID, User: userID, Connected: &connected, @@ -67,7 +67,7 @@ func (s *BoardSessionService) Connect(ctx context.Context, boardID, userID uuid. log.Errorw("unable to connect to board session", "board", boardID, "user", userID, "error", err) return err } - s.UpdatedSession(boardID, updatedSession) + s.UpdatedSession(boardID, session) return err } @@ -75,7 +75,7 @@ func (s *BoardSessionService) Connect(ctx context.Context, boardID, userID uuid. func (s *BoardSessionService) Disconnect(ctx context.Context, boardID, userID uuid.UUID) error { log := logger.FromContext(ctx) var connected = false - updatedSession, err := s.database.UpdateBoardSession(database.BoardSessionUpdate{ + session, err := s.database.UpdateBoardSession(database.BoardSessionUpdate{ Board: boardID, User: userID, Connected: &connected, @@ -84,7 +84,7 @@ func (s *BoardSessionService) Disconnect(ctx context.Context, boardID, userID uu log.Errorw("unable to disconnect from board session", "board", boardID, "user", userID, "error", err) return err } - s.UpdatedSession(boardID, updatedSession) + s.UpdatedSession(boardID, session) return err } @@ -270,32 +270,21 @@ func (s *BoardSessionService) CreatedSession(board uuid.UUID, session database.B } } -func (s *BoardSessionService) UpdatedSession(board uuid.UUID, session database.BoardSession) { - connectedBoards, err := s.database.GetSingleUserConnectedBoards(session.User) +func (s *BoardSessionService) UpdatedSession(user uuid.UUID, session database.BoardSession) { + err := s.realtime.BroadcastToBoard(session.Board, realtime.BoardEvent{ + Type: realtime.BoardEventParticipantSessionUpdated, + Data: new(dto.BoardSession).From(session), + }) if err != nil { - return - } - for _, session := range connectedBoards { - userSession, err := s.database.GetBoardSession(session.Board, session.User) - if err != nil { - logger.Get().Errorw("unable to get board session of user", "board", session.Board, "user", session.User, "err", err) - return - } - err = s.realtime.BroadcastToBoard(session.Board, realtime.BoardEvent{ - Type: realtime.BoardEventParticipantUpdated, - Data: new(dto.BoardSession).From(userSession), - }) - if err != nil { - logger.Get().Errorw("unable to broadcast updated board session", "err", err) - } + logger.Get().Errorw("unable to broadcast updated board session", "err", err) } // Sync columns - columns, err := s.database.GetColumns(board) + columns, err := s.database.GetColumns(session.Board) if err != nil { logger.Get().Errorw("unable to get columns on a updatedsession call", "err", err) } - err = s.realtime.BroadcastToBoard(board, realtime.BoardEvent{ + err = s.realtime.BroadcastToBoard(session.Board, realtime.BoardEvent{ Type: realtime.BoardEventColumnsUpdated, Data: dto.Columns(columns), }) @@ -304,11 +293,11 @@ func (s *BoardSessionService) UpdatedSession(board uuid.UUID, session database.B } // Sync notes - notes, err := s.database.GetNotes(board) + notes, err := s.database.GetNotes(session.Board) if err != nil { logger.Get().Errorw("unable to get notes on a updatedsession call", "err", err) } - err = s.realtime.BroadcastToBoard(board, realtime.BoardEvent{ + err = s.realtime.BroadcastToBoard(session.Board, realtime.BoardEvent{ Type: realtime.BoardEventNotesSync, Data: dto.Notes(notes), }) diff --git a/server/src/services/users/users.go b/server/src/services/users/users.go index e947106ddb..b49d088d8d 100644 --- a/server/src/services/users/users.go +++ b/server/src/services/users/users.go @@ -94,18 +94,14 @@ func (s *UserService) Update(_ context.Context, body dto.UserUpdateRequest) (*dt func (s *UserService) UpdatedUser(user database.User) { connectedBoards, err := s.database.GetSingleUserConnectedBoards(user.ID) if err != nil { + logger.Get().Errorw("unable to retrieve all currently connected boards for single user in an updateduser call", "err", err) return } for _, session := range connectedBoards { - userSession, err := s.database.GetBoardSession(session.Board, session.User) - if err != nil { - logger.Get().Errorw("unable to get board session", "board", userSession.Board, "user", userSession.User.ID(), "err", err) - } - err = s.realtime.BroadcastToBoard(session.Board, realtime.BoardEvent{ + err = s.realtime.BroadcastToBoard(session, realtime.BoardEvent{ Type: realtime.BoardEventParticipantUpdated, - Data: new(dto.BoardSession).From(session), + Data: new(dto.User).From(user), }) - if err != nil { logger.Get().Errorw("unable to broadcast updated user", "err", err) }