fix: align meeting note payloads
This commit is contained in:
@@ -331,6 +331,7 @@ func (s *Store) Meetings(ctx context.Context, userID int64, cursor string, limit
|
||||
}
|
||||
for i := range items {
|
||||
items[i].Participants, _ = s.meetingParticipants(ctx, items[i].MeetingID)
|
||||
_ = s.hydrateMeetingUsers(ctx, &items[i])
|
||||
}
|
||||
return items, next, nil
|
||||
}
|
||||
@@ -345,6 +346,7 @@ func (s *Store) Meeting(ctx context.Context, userID int64, meetingID string) (*M
|
||||
return nil, err
|
||||
}
|
||||
meeting.Participants, _ = s.meetingParticipants(ctx, meeting.MeetingID)
|
||||
_ = s.hydrateMeetingUsers(ctx, &meeting)
|
||||
if !meetingVisible(meeting, userID) {
|
||||
return nil, ErrForbidden
|
||||
}
|
||||
@@ -791,6 +793,149 @@ func (s *Store) meetingParticipants(ctx context.Context, meetingID string) ([]Me
|
||||
return items, err
|
||||
}
|
||||
|
||||
func (s *Store) hydrateMeetingUsers(ctx context.Context, meeting *Meeting) error {
|
||||
if meeting == nil {
|
||||
return nil
|
||||
}
|
||||
seen := map[int64]bool{}
|
||||
userIDs := make([]int64, 0, len(meeting.Participants)+2)
|
||||
add := func(userID int64) {
|
||||
if userID > 0 && !seen[userID] {
|
||||
seen[userID] = true
|
||||
userIDs = append(userIDs, userID)
|
||||
}
|
||||
}
|
||||
add(meeting.OrganizerID)
|
||||
add(meeting.RecorderID)
|
||||
for _, participant := range meeting.Participants {
|
||||
add(participant.UserID)
|
||||
}
|
||||
summaries, err := s.UserSummaries(ctx, userIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
meeting.Organizer = summaryOrDefault(meeting.OrganizerID, summaries)
|
||||
meeting.Recorder = summaryOrDefault(meeting.RecorderID, summaries)
|
||||
for i := range meeting.Participants {
|
||||
meeting.Participants[i].User = summaryOrDefault(meeting.Participants[i].UserID, summaries)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) UserSummaries(ctx context.Context, userIDs []int64) (map[int64]UserSummary, error) {
|
||||
result := make(map[int64]UserSummary, len(userIDs))
|
||||
ids := uniquePositiveInt64s(userIDs)
|
||||
if len(ids) == 0 {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
query, args, err := sqlx.In(`SELECT user_id,display_name,IFNULL(avatar_file_id,'') AS avatar_file_id
|
||||
FROM im_org_members WHERE employment_state='active' AND user_id IN (?) ORDER BY user_id ASC,id ASC`, ids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var orgRows []struct {
|
||||
UserID int64 `db:"user_id"`
|
||||
DisplayName string `db:"display_name"`
|
||||
AvatarFileID string `db:"avatar_file_id"`
|
||||
}
|
||||
if err := s.db.SelectContext(ctx, &orgRows, s.db.Rebind(query), args...); err != nil && !isMissingTable(err) {
|
||||
return nil, err
|
||||
}
|
||||
for _, row := range orgRows {
|
||||
if _, ok := result[row.UserID]; ok {
|
||||
continue
|
||||
}
|
||||
result[row.UserID] = UserSummary{UserID: row.UserID, DisplayName: strings.TrimSpace(row.DisplayName), AvatarFileID: row.AvatarFileID}
|
||||
}
|
||||
|
||||
query, args, err = sqlx.In(`SELECT user_id,nickname AS display_name,IFNULL(avatar_file_id,'') AS avatar_file_id
|
||||
FROM im_user_profiles WHERE user_id IN (?) ORDER BY user_id ASC`, ids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var profileRows []struct {
|
||||
UserID int64 `db:"user_id"`
|
||||
DisplayName string `db:"display_name"`
|
||||
AvatarFileID string `db:"avatar_file_id"`
|
||||
}
|
||||
if err := s.db.SelectContext(ctx, &profileRows, s.db.Rebind(query), args...); err != nil && !isMissingTable(err) {
|
||||
return nil, err
|
||||
}
|
||||
for _, row := range profileRows {
|
||||
summary := result[row.UserID]
|
||||
if summary.UserID == 0 {
|
||||
summary.UserID = row.UserID
|
||||
}
|
||||
if summary.DisplayName == "" {
|
||||
summary.DisplayName = strings.TrimSpace(row.DisplayName)
|
||||
}
|
||||
if summary.AvatarFileID == "" {
|
||||
summary.AvatarFileID = row.AvatarFileID
|
||||
}
|
||||
result[row.UserID] = summary
|
||||
}
|
||||
|
||||
query, args, err = sqlx.In(`SELECT id AS user_id,
|
||||
COALESCE(
|
||||
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(public,'$.display_name')),''),
|
||||
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(public,'$.fn')),''),
|
||||
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(public,'$.nickname')),''),
|
||||
NULLIF(JSON_UNQUOTE(JSON_EXTRACT(public,'$.name')),''),
|
||||
''
|
||||
) AS display_name
|
||||
FROM im_users WHERE id IN (?)`, ids)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var userRows []struct {
|
||||
UserID int64 `db:"user_id"`
|
||||
DisplayName string `db:"display_name"`
|
||||
}
|
||||
if err := s.db.SelectContext(ctx, &userRows, s.db.Rebind(query), args...); err != nil && !isMissingTable(err) {
|
||||
return nil, err
|
||||
}
|
||||
for _, row := range userRows {
|
||||
summary := result[row.UserID]
|
||||
if summary.UserID == 0 {
|
||||
summary.UserID = row.UserID
|
||||
}
|
||||
if summary.DisplayName == "" {
|
||||
summary.DisplayName = strings.TrimSpace(row.DisplayName)
|
||||
}
|
||||
result[row.UserID] = summary
|
||||
}
|
||||
|
||||
for _, id := range ids {
|
||||
result[id] = summaryOrDefault(id, result)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func uniquePositiveInt64s(values []int64) []int64 {
|
||||
seen := map[int64]bool{}
|
||||
out := make([]int64, 0, len(values))
|
||||
for _, value := range values {
|
||||
if value <= 0 || seen[value] {
|
||||
continue
|
||||
}
|
||||
seen[value] = true
|
||||
out = append(out, value)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func summaryOrDefault(userID int64, summaries map[int64]UserSummary) UserSummary {
|
||||
if userID <= 0 {
|
||||
return UserSummary{}
|
||||
}
|
||||
summary := summaries[userID]
|
||||
if summary.UserID == 0 {
|
||||
summary.UserID = userID
|
||||
}
|
||||
return summary
|
||||
}
|
||||
|
||||
func (s *Store) meetingNoteFile(ctx context.Context, meetingID, noteFileID string) (*MeetingNoteFile, error) {
|
||||
var file MeetingNoteFile
|
||||
if err := s.db.GetContext(ctx, &file, `SELECT note_file_id,meeting_id,file_id,uploader_id,file_name,mime_type,file_size,file_etag,status,preview_status,preview_mode,preview_file_id,version,created_at,updated_at
|
||||
|
||||
@@ -35,6 +35,12 @@ type OrganizationMember struct {
|
||||
Version int `db:"version"`
|
||||
}
|
||||
|
||||
type UserSummary struct {
|
||||
UserID int64
|
||||
DisplayName string
|
||||
AvatarFileID string
|
||||
}
|
||||
|
||||
type AttendanceRule struct {
|
||||
RuleID string `db:"rule_id"`
|
||||
Name string `db:"name"`
|
||||
@@ -128,6 +134,8 @@ type Meeting struct {
|
||||
CanceledAt *time.Time `db:"canceled_at"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
Organizer UserSummary
|
||||
Recorder UserSummary
|
||||
Participants []MeetingParticipant
|
||||
}
|
||||
|
||||
@@ -136,6 +144,7 @@ type MeetingParticipant struct {
|
||||
UserID int64 `db:"user_id"`
|
||||
Response string `db:"response"`
|
||||
ResponseAt *time.Time `db:"response_at"`
|
||||
User UserSummary
|
||||
}
|
||||
|
||||
type MeetingNoteFile struct {
|
||||
|
||||
Reference in New Issue
Block a user