Files
mostlymatter/api4/resolver_channel.go
Agniva De Sarker c0eb0fd3c3 MM-43829: Default for user display_name preference (#20087)
We fall back to TeammateNameDisplay if a user display_name
preference is not found. This makes the logic consistent
with other parts of the app.

https://mattermost.atlassian.net/browse/MM-43829

```release-note
NONE
```
2022-04-29 13:36:04 +05:30

176 строки
4.4 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package api4
import (
"context"
"encoding/base64"
"fmt"
"sort"
"strings"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/web"
)
// channel is an internal graphQL wrapper struct to add resolver methods.
type channel struct {
model.Channel
PrettyDisplayName string
}
// match with api4.getTeam
func (ch *channel) Team(ctx context.Context) (*model.Team, error) {
if ch.TeamId == "" {
return nil, nil
}
return getGraphQLTeam(ctx, ch.TeamId)
}
// match with api4.getChannelStats
func (ch *channel) Stats(ctx context.Context) (*model.ChannelStats, error) {
c, err := getCtx(ctx)
if err != nil {
return nil, err
}
if !c.App.SessionHasPermissionToChannel(*c.AppContext.Session(), ch.Id, model.PermissionReadChannel) {
c.SetPermissionError(model.PermissionReadChannel)
return nil, c.Err
}
memberCount, appErr := c.App.GetChannelMemberCount(ch.Id)
if appErr != nil {
return nil, appErr
}
guestCount, appErr := c.App.GetChannelGuestCount(ch.Id)
if appErr != nil {
return nil, appErr
}
pinnedPostCount, appErr := c.App.GetChannelPinnedPostCount(ch.Id)
if appErr != nil {
return nil, appErr
}
return &model.ChannelStats{ChannelId: ch.Id, MemberCount: memberCount, GuestCount: guestCount, PinnedPostCount: pinnedPostCount}, nil
}
func (ch *channel) Cursor() *string {
cursor := string(channelCursorPrefix) + "-" + ch.Id
encoded := base64.StdEncoding.EncodeToString([]byte(cursor))
return model.NewString(encoded)
}
func parseChannelCursor(cursor string) (channelID string, ok bool) {
decoded, err := base64.StdEncoding.DecodeString(cursor)
if err != nil {
return "", false
}
parts := strings.Split(string(decoded), "-")
if len(parts) != 2 {
return "", false
}
if cursorPrefix(parts[0]) != channelCursorPrefix {
return "", false
}
return parts[1], true
}
func postProcessChannels(c *web.Context, channels []*model.Channel) ([]*channel, error) {
// This approach becomes effectively similar to a dataloader if the displayName computation
// were to be done at the field level per channel.
// Get DM/GM channelIDs
var channelIDs []string
for _, ch := range channels {
if ch.IsGroupOrDirect() {
channelIDs = append(channelIDs, ch.Id)
}
}
var nameFormat string
var userInfo map[string][]*model.User
var err error
// Avoiding unnecessary queries unless necessary.
if len(channelIDs) > 0 {
userInfo, err = c.App.Srv().Store.Channel().GetMembersInfoByChannelIds(channelIDs)
if err != nil {
return nil, err
}
user := &model.User{Id: c.AppContext.Session().UserId}
nameFormat = c.App.GetNotificationNameFormat(user)
}
// Convert to the wrapper format.
res := make([]*channel, 0, len(channels))
for _, ch := range channels {
prettyName := ch.DisplayName
if ch.IsGroupOrDirect() {
// get users slice for channel id
users := userInfo[ch.Id]
if users == nil {
return nil, fmt.Errorf("user info not found for channel id: %s", ch.Id)
}
prettyName = getPrettyDNForUsers(nameFormat, users, c.AppContext.Session().UserId)
}
res = append(res, &channel{Channel: *ch, PrettyDisplayName: prettyName})
}
return res, nil
}
func getPrettyDNForUsers(displaySetting string, users []*model.User, omitUserId string) string {
displayNames := make([]string, 0, len(users))
// TODO: optimize this logic.
// Name computation happens repeatedly for the same user from
// multiple channels.
for _, u := range users {
if u.Id == omitUserId {
continue
}
displayNames = append(displayNames, getPrettyDNForUser(displaySetting, u))
}
sort.Strings(displayNames)
result := strings.Join(displayNames, ", ")
if result == "" {
// Self DM
result = getPrettyDNForUser(displaySetting, users[0])
}
return result
}
func getPrettyDNForUser(displaySetting string, user *model.User) string {
var displayName string
switch displaySetting {
case "nickname_full_name":
displayName = user.Nickname
if strings.TrimSpace(displayName) == "" {
displayName = user.GetFullName()
}
if strings.TrimSpace(displayName) == "" {
displayName = user.Username
}
case "full_name":
displayName = user.GetFullName()
if strings.TrimSpace(displayName) == "" {
displayName = user.Username
}
default: // the "username" case also falls under this one.
displayName = user.Username
}
return displayName
}