support for synchronizing user's profile image for shared channels.
Этот коммит содержится в:
Doug Lauder
2021-04-22 17:48:09 -04:00
коммит произвёл GitHub
родитель 7c7c4716e6
Коммит ff657bfdef
13 изменённых файлов: 533 добавлений и 45 удалений

Просмотреть файл

@@ -230,6 +230,38 @@ func (_m *MockAppIface) GetOrCreateDirectChannel(userId string, otherUserId stri
return r0, r1
}
// GetProfileImage provides a mock function with given fields: user
func (_m *MockAppIface) GetProfileImage(user *model.User) ([]byte, bool, *model.AppError) {
ret := _m.Called(user)
var r0 []byte
if rf, ok := ret.Get(0).(func(*model.User) []byte); ok {
r0 = rf(user)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]byte)
}
}
var r1 bool
if rf, ok := ret.Get(1).(func(*model.User) bool); ok {
r1 = rf(user)
} else {
r1 = ret.Get(1).(bool)
}
var r2 *model.AppError
if rf, ok := ret.Get(2).(func(*model.User) *model.AppError); ok {
r2 = rf(user)
} else {
if ret.Get(2) != nil {
r2 = ret.Get(2).(*model.AppError)
}
}
return r0, r1, r2
}
// InvalidateCacheForUser provides a mock function with given fields: userID
func (_m *MockAppIface) InvalidateCacheForUser(userID string) {
_m.Called(userID)

Просмотреть файл

@@ -7,8 +7,10 @@ import (
"context"
"encoding/json"
"strings"
"time"
"github.com/mattermost/mattermost-server/v5/model"
"github.com/mattermost/mattermost-server/v5/services/remotecluster"
"github.com/mattermost/mattermost-server/v5/shared/mlog"
)
@@ -177,26 +179,35 @@ func (scs *Service) usersForPost(post *model.Post, reactions []*model.Reaction,
for _, id := range userIds {
user, err := scs.server.GetStore().User().Get(context.Background(), id)
if err == nil {
if sync, err2 := scs.shouldUserSync(user, channelID, rc); err2 != nil {
scs.server.GetLogger().Log(mlog.LvlSharedChannelServiceError, "Could not find user for post",
mlog.String("user_id", id),
mlog.Err(err2),
)
continue
} else if sync {
users = append(users, sanitizeUserForSync(user))
}
// if this was a mention then put the real username in place of the username+remotename, but only
// when sending to the remote that the user belongs to.
if user.RemoteId != nil && *user.RemoteId == rc.RemoteId {
fixMention(post, mentionMap, user)
}
} else {
if err != nil {
scs.server.GetLogger().Log(mlog.LvlSharedChannelServiceError, "Error checking if user should sync",
mlog.String("user_id", id),
mlog.Err(err),
)
continue
}
sync, syncImage, err2 := scs.shouldUserSync(user, channelID, rc)
if err2 != nil {
scs.server.GetLogger().Log(mlog.LvlSharedChannelServiceError, "Could not find user for post",
mlog.String("user_id", id),
mlog.Err(err2),
)
continue
}
if sync {
users = append(users, sanitizeUserForSync(user))
}
if syncImage {
scs.syncProfileImage(user, channelID, rc)
}
// if this was a mention then put the real username in place of the username+remotename, but only
// when sending to the remote that the user belongs to.
if user.RemoteId != nil && *user.RemoteId == rc.RemoteId {
fixMention(post, mentionMap, user)
}
}
return users
@@ -240,16 +251,16 @@ func sanitizeUserForSync(user *model.User) *model.User {
// shouldUserSync determines if a user needs to be synchronized.
// User should be synchronized if it has no entry in the SharedChannelUsers table for the specified channel,
// or there is an entry but the LastSyncAt is less than user.UpdateAt
func (scs *Service) shouldUserSync(user *model.User, channelID string, rc *model.RemoteCluster) (bool, error) {
func (scs *Service) shouldUserSync(user *model.User, channelID string, rc *model.RemoteCluster) (sync bool, syncImage bool, err error) {
// don't sync users with the remote they originated from.
if user.RemoteId != nil && *user.RemoteId == rc.RemoteId {
return false, nil
return false, false, nil
}
scu, err := scs.server.GetStore().SharedChannel().GetUser(user.Id, channelID, rc.RemoteId)
if err != nil {
if _, ok := err.(errNotFound); !ok {
return false, err
return false, false, err
}
// user not in the SharedChannelUsers table, so we must add them.
@@ -266,8 +277,52 @@ func (scs *Service) shouldUserSync(user *model.User, channelID string, rc *model
mlog.Err(err),
)
}
} else if scu.LastSyncAt >= user.UpdateAt {
return false, nil
return true, true, nil
}
return true, nil
return user.UpdateAt > scu.LastSyncAt, user.LastPictureUpdate > scu.LastSyncAt, nil
}
func (scs *Service) syncProfileImage(user *model.User, channelID string, rc *model.RemoteCluster) {
rcs := scs.server.GetRemoteClusterService()
if rcs == nil {
return
}
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
rcs.SendProfileImage(ctx, user.Id, rc, scs.app, func(userId string, rc *model.RemoteCluster, resp *remotecluster.Response, err error) {
if resp.IsSuccess() {
scs.server.GetLogger().Log(mlog.LvlSharedChannelServiceDebug, "Users profile image synchronized",
mlog.String("remote_id", rc.RemoteId),
mlog.String("user_id", user.Id),
)
scu, err := scs.server.GetStore().SharedChannel().GetUser(user.Id, channelID, rc.RemoteId)
if err != nil {
scs.server.GetLogger().Log(mlog.LvlSharedChannelServiceError, "Error fetching shared channel user while updating users LastSyncTime after profile image update",
mlog.String("remote_id", rc.RemoteId),
mlog.String("user_id", user.Id),
mlog.String("channel_id", channelID),
mlog.Err(err),
)
}
if err = scs.server.GetStore().SharedChannel().UpdateUserLastSyncAt(scu.Id, model.GetMillis()); err != nil {
scs.server.GetLogger().Log(mlog.LvlSharedChannelServiceError, "Error updating users LastSyncTime after profile image update",
mlog.String("remote_id", rc.RemoteId),
mlog.String("user_id", user.Id),
mlog.Err(err),
)
}
return
}
scs.server.GetLogger().Log(mlog.LvlSharedChannelServiceError, "Error synchronizing users profile image",
mlog.String("remote_id", rc.RemoteId),
mlog.String("user_id", user.Id),
mlog.String("Err", resp.Err),
)
})
}

Просмотреть файл

@@ -57,6 +57,7 @@ type AppIface interface {
CreateUploadSession(us *model.UploadSession) (*model.UploadSession, *model.AppError)
FileReader(path string) (filestore.ReadCloseSeeker, *model.AppError)
MentionsToTeamMembers(message, teamID string) model.UserMentionMap
GetProfileImage(user *model.User) ([]byte, bool, *model.AppError)
InvalidateCacheForUser(userID string)
NotifySharedChannelUserUpdate(user *model.User)
}