Merge branch 'master' into MM-45118_my_top_dms

Этот коммит содержится в:
Mattermod
2022-08-05 09:56:52 +03:00
коммит произвёл GitHub
родитель 45e434cc26 14246abdef
Коммит 4fc8ef0125
87 изменённых файлов: 966 добавлений и 493 удалений

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

@@ -17,7 +17,7 @@ jobs:
setup:
working_directory: ~/mattermost/mattermost-server
docker:
- image: mattermost/mattermost-build-webapp:20210524_node-16
- image: mattermost/mattermost-build-webapp:20220802_node-16.10.0@sha256:3272aa759f10c2ef1719ed08cc82ddb07224bec5be86f09800c72f5e2a623c3d
resource_class: xlarge
# Use `--retry-all-errors` instead of `until` after curl version >= 7.71.0; `retry` will not work, since it only retries on transient errors, 403 is not one of them.
steps:

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

@@ -117,7 +117,7 @@ func setupTestHelper(dbStore store.Store, searchEngine *searchengine.Broker, ent
if includeCache {
// Adds the cache layer to the test store
options = append(options, app.StoreOverride(func(s *app.Server) store.Store {
lcl, err2 := localcachelayer.NewLocalCacheLayer(dbStore, s.Metrics, s.Cluster, s.CacheProvider)
lcl, err2 := localcachelayer.NewLocalCacheLayer(dbStore, s.GetMetrics(), s.Cluster, s.CacheProvider)
if err2 != nil {
panic(err2)
}
@@ -218,7 +218,7 @@ func setupTestHelper(dbStore store.Store, searchEngine *searchengine.Broker, ent
return th
}
func SetupEnterprise(tb testing.TB) *TestHelper {
func SetupEnterprise(tb testing.TB, options ...app.Option) *TestHelper {
if testing.Short() {
tb.SkipNow()
}
@@ -232,7 +232,7 @@ func SetupEnterprise(tb testing.TB) *TestHelper {
dbStore.MarkSystemRanUnitTests()
mainHelper.PreloadMigrations()
searchEngine := mainHelper.GetSearchEngine()
th := setupTestHelper(dbStore, searchEngine, true, true, nil, nil)
th := setupTestHelper(dbStore, searchEngine, true, true, nil, options)
th.InitLogin()
return th
}
@@ -322,8 +322,8 @@ func SetupWithStoreMock(tb testing.TB) *TestHelper {
return th
}
func SetupEnterpriseWithStoreMock(tb testing.TB) *TestHelper {
th := setupTestHelper(testlib.GetMockStoreForSetupFunctions(), nil, true, false, nil, nil)
func SetupEnterpriseWithStoreMock(tb testing.TB, options ...app.Option) *TestHelper {
th := setupTestHelper(testlib.GetMockStoreForSetupFunctions(), nil, true, false, nil, options)
statusMock := mocks.StatusStore{}
statusMock.On("UpdateExpiredDNDStatuses").Return([]*model.Status{}, nil)
statusMock.On("Get", "user1").Return(&model.Status{UserId: "user1", Status: model.StatusOnline}, nil)

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

@@ -187,7 +187,7 @@ func getBots(c *Context, w http.ResponseWriter, r *http.Request) {
}
if err := json.NewEncoder(w).Encode(bots); err != nil {
mlog.Warn("Error while writing response", mlog.Err(err))
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
}
@@ -227,7 +227,7 @@ func updateBotActive(c *Context, w http.ResponseWriter, active bool) {
auditRec.AddEventObjectType("bot")
if err := json.NewEncoder(w).Encode(bot); err != nil {
mlog.Warn("Error while writing response", mlog.Err(err))
c.Logger.Warn("Error while writing response", mlog.Err(err))
}
}

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

@@ -212,14 +212,6 @@ func TestRequestTrialLicense(t *testing.T) {
CheckForbiddenStatus(t, resp)
})
t.Run("blank site url", func(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SiteURL = "" })
defer th.App.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.SiteURL = "http://localhost:8065/" })
resp, err := th.SystemAdminClient.RequestTrialLicense(1000)
CheckErrorID(t, err, "api.license.request_trial_license.no-site-url.app_error")
CheckBadRequestStatus(t, resp)
})
t.Run("trial license user count less than current users", func(t *testing.T) {
nUsers := 1
license := model.NewTestLicense()

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

@@ -3172,11 +3172,6 @@ func unfollowThreadByUser(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
if !c.App.SessionHasPermissionToChannelByPost(*c.AppContext.Session(), c.Params.ThreadId, model.PermissionReadChannel) {
c.SetPermissionError(model.PermissionReadChannel)
return
}
err := c.App.UpdateThreadFollowForUser(c.Params.UserId, c.Params.TeamId, c.Params.ThreadId, false)
if err != nil {
c.Err = err

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

@@ -117,7 +117,7 @@ func (a *App) MessageExport() einterfaces.MessageExportInterface {
return a.ch.MessageExport
}
func (a *App) Metrics() einterfaces.MetricsInterface {
return a.ch.srv.Metrics
return a.ch.srv.GetMetrics()
}
func (a *App) Notification() einterfaces.NotificationInterface {
return a.ch.Notification

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

@@ -37,12 +37,12 @@ import (
// AppIface is extracted from App struct and contains all it's exported methods. It's provided to allow partial interface passing and app layers creation.
type AppIface interface {
// @openTracingParams args
ExecuteCommand(c *request.Context, args *model.CommandArgs) (*model.CommandResponse, *model.AppError)
ExecuteCommand(c request.CTX, args *model.CommandArgs) (*model.CommandResponse, *model.AppError)
// @openTracingParams teamID
// previous ListCommands now ListAutocompleteCommands
ListAutocompleteCommands(teamID string, T i18n.TranslateFunc) ([]*model.Command, *model.AppError)
// @openTracingParams teamID, skipSlackParsing
CreateCommandPost(c *request.Context, post *model.Post, teamID string, response *model.CommandResponse, skipSlackParsing bool) (*model.Post, *model.AppError)
CreateCommandPost(c request.CTX, post *model.Post, teamID string, response *model.CommandResponse, skipSlackParsing bool) (*model.Post, *model.AppError)
// AddChannelMember adds a user to a channel. It is a wrapper over AddUserToChannel.
AddChannelMember(c request.CTX, userID string, channel *model.Channel, opts ChannelMemberOpts) (*model.ChannelMember, *model.AppError)
// AddCursorIdsForPostList adds NextPostId and PrevPostId as cursor to the PostList.
@@ -84,7 +84,7 @@ type AppIface interface {
// ConvertUserToBot converts a user to bot.
ConvertUserToBot(user *model.User) (*model.Bot, *model.AppError)
// CreateBot creates the given bot and corresponding user.
CreateBot(c *request.Context, bot *model.Bot) (*model.Bot, *model.AppError)
CreateBot(c request.CTX, bot *model.Bot) (*model.Bot, *model.AppError)
// CreateChannelScheme creates a new Scheme of scope channel and assigns it to the channel.
CreateChannelScheme(c request.CTX, channel *model.Channel) (*model.Scheme, *model.AppError)
// CreateDefaultMemberships adds users to teams and channels based on their group memberships and how those groups
@@ -132,7 +132,7 @@ type AppIface interface {
// any ensureBotOptions hence it is not required for now.
// TODO: Once the focalboard migration completed, we should add this logic to the app and
// let plugin-api use the same code
EnsureBot(c *request.Context, productID string, bot *model.Bot) (string, error)
EnsureBot(c request.CTX, productID string, bot *model.Bot) (string, error)
// Expand announcements in incoming webhooks from Slack. Those announcements
// can be found in the text attribute, or in the pretext, text, title and value
// attributes of the attachment structure. The Slack attachment structure is
@@ -250,7 +250,7 @@ type AppIface interface {
MentionsToPublicChannels(c request.CTX, message, teamID string) model.ChannelMentionMap
// MentionsToTeamMembers returns all the @ mentions found in message that
// belong to users in the specified team, linking them to their users
MentionsToTeamMembers(message, teamID string) model.UserMentionMap
MentionsToTeamMembers(c request.CTX, message, teamID string) model.UserMentionMap
// MoveChannel method is prone to data races if someone joins to channel during the move process. However this
// function is only exposed to sysadmins and the possibility of this edge case is relatively small.
MoveChannel(c request.CTX, team *model.Team, channel *model.Channel, user *model.User) *model.AppError
@@ -328,7 +328,7 @@ type AppIface interface {
SyncPlugins() *model.AppError
// SyncRolesAndMembership updates the SchemeAdmin status and membership of all of the members of the given
// syncable.
SyncRolesAndMembership(c *request.Context, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool)
SyncRolesAndMembership(c request.CTX, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool)
// SyncSyncableRoles updates the SchemeAdmin field value of the given syncable's members based on the configuration of
// the member's group memberships and the configuration of those groups to the syncable. This method should only
// be invoked on group-synced (aka group-constrained) syncables.
@@ -354,7 +354,7 @@ type AppIface interface {
// This to be used for places we check the users password when they are already logged in
DoubleCheckPassword(user *model.User, password string) *model.AppError
// UpdateBotActive marks a bot as active or inactive, along with its corresponding user.
UpdateBotActive(c *request.Context, botUserId string, active bool) (*model.Bot, *model.AppError)
UpdateBotActive(c request.CTX, botUserId string, active bool) (*model.Bot, *model.AppError)
// UpdateBotOwner changes a bot's owner to the given value.
UpdateBotOwner(botUserId, newOwnerId string) (*model.Bot, *model.AppError)
// UpdateChannel updates a given channel by its Id. It also publishes the CHANNEL_UPDATED event.
@@ -374,7 +374,7 @@ type AppIface interface {
// UpdateWebConnUserActivity sets the LastUserActivityAt of the hub for the given session.
UpdateWebConnUserActivity(session model.Session, activityAt int64)
// UploadFile uploads a single file in form of a completely constructed byte array for a channel.
UploadFile(c *request.Context, data []byte, channelID string, filename string) (*model.FileInfo, *model.AppError)
UploadFile(c request.CTX, data []byte, channelID string, filename string) (*model.FileInfo, *model.AppError)
// UploadFileX uploads a single file as specified in t. It applies the upload
// constraints, executes plugins and image processing logic as needed. It
// returns a filled-out FileInfo and an optional error. A plugin may reject the
@@ -402,12 +402,12 @@ type AppIface interface {
AddSessionToCache(session *model.Session)
AddStatusCache(status *model.Status)
AddStatusCacheSkipClusterSend(status *model.Status)
AddTeamMember(c *request.Context, teamID, userID string) (*model.TeamMember, *model.AppError)
AddTeamMember(c request.CTX, teamID, userID string) (*model.TeamMember, *model.AppError)
AddTeamMemberByInviteId(c *request.Context, inviteId, userID string) (*model.TeamMember, *model.AppError)
AddTeamMemberByToken(c *request.Context, userID, tokenID string) (*model.TeamMember, *model.AppError)
AddTeamMembers(c *request.Context, teamID string, userIDs []string, userRequestorId string, graceful bool) ([]*model.TeamMemberWithError, *model.AppError)
AddTeamsToRetentionPolicy(policyID string, teamIDs []string) *model.AppError
AddUserToTeam(c *request.Context, teamID string, userID string, userRequestorId string) (*model.Team, *model.TeamMember, *model.AppError)
AddUserToTeam(c request.CTX, teamID string, userID string, userRequestorId string) (*model.Team, *model.TeamMember, *model.AppError)
AddUserToTeamByInviteId(c *request.Context, inviteId string, userID string) (*model.Team, *model.TeamMember, *model.AppError)
AddUserToTeamByTeamId(c *request.Context, teamID string, user *model.User) *model.AppError
AddUserToTeamByToken(c *request.Context, userID string, tokenID string) (*model.Team, *model.TeamMember, *model.AppError)
@@ -428,10 +428,10 @@ type AppIface interface {
AutocompleteUsersInChannel(teamID string, channelID string, term string, options *model.UserSearchOptions) (*model.UserAutocompleteInChannel, *model.AppError)
AutocompleteUsersInTeam(teamID string, term string, options *model.UserSearchOptions) (*model.UserAutocompleteInTeam, *model.AppError)
BroadcastStatus(status *model.Status)
BuildPostReactions(postID string) (*[]ReactionImportData, *model.AppError)
BuildPostReactions(ctx request.CTX, postID string) (*[]ReactionImportData, *model.AppError)
BuildPushNotificationMessage(c request.CTX, contentsConfig string, post *model.Post, user *model.User, channel *model.Channel, channelName string, senderName string, explicitMention bool, channelWideMention bool, replyToThreadType string) (*model.PushNotification, *model.AppError)
BuildSamlMetadataObject(idpMetadata []byte) (*model.SamlMetadataResponse, *model.AppError)
BulkExport(writer io.Writer, outPath string, opts model.BulkExportOpts) *model.AppError
BulkExport(ctx request.CTX, writer io.Writer, outPath string, opts model.BulkExportOpts) *model.AppError
BulkImport(c *request.Context, jsonlReader io.Reader, attachmentsReader *zip.Reader, dryRun bool, workers int) (*model.AppError, int)
BulkImportWithPath(c *request.Context, jsonlReader io.Reader, attachmentsReader *zip.Reader, dryRun bool, workers int, importPath string) (*model.AppError, int)
CancelJob(jobId string) *model.AppError
@@ -449,13 +449,13 @@ type AppIface interface {
CheckUserPostflightAuthenticationCriteria(user *model.User) *model.AppError
CheckUserPreflightAuthenticationCriteria(user *model.User, mfaToken string) *model.AppError
CheckWebConn(userID, connectionID string) *CheckConnResult
ClearChannelMembersCache(c request.CTX, channelID string)
ClearChannelMembersCache(c request.CTX, channelID string) error
ClearLatestVersionCache()
ClearSessionCacheForAllUsers()
ClearSessionCacheForAllUsersSkipClusterSend()
ClearSessionCacheForUser(userID string)
ClearSessionCacheForUserSkipClusterSend(userID string)
ClearTeamMembersCache(teamID string)
ClearTeamMembersCache(teamID string) error
ClientConfig() map[string]string
ClientConfigHash() string
Cloud() einterfaces.CloudInterface
@@ -484,7 +484,7 @@ type AppIface interface {
CreateOutgoingWebhook(hook *model.OutgoingWebhook) (*model.OutgoingWebhook, *model.AppError)
CreatePasswordRecoveryToken(userID, email string) (*model.Token, *model.AppError)
CreatePost(c request.CTX, post *model.Post, channel *model.Channel, triggerWebhooks, setOnline bool) (savedPost *model.Post, err *model.AppError)
CreatePostAsUser(c *request.Context, post *model.Post, currentSessionId string, setOnline bool) (*model.Post, *model.AppError)
CreatePostAsUser(c request.CTX, post *model.Post, currentSessionId string, setOnline bool) (*model.Post, *model.AppError)
CreatePostMissingChannel(c request.CTX, post *model.Post, triggerWebhooks bool) (*model.Post, *model.AppError)
CreateRetentionPolicy(policy *model.RetentionPolicyWithTeamAndChannelIDs) (*model.RetentionPolicyWithTeamAndChannelCounts, *model.AppError)
CreateRole(role *model.Role) (*model.Role, *model.AppError)
@@ -545,7 +545,7 @@ type AppIface interface {
DoPostActionWithCookie(c *request.Context, postID, actionId, userID, selectedOption string, cookie *model.PostActionCookie) (string, *model.AppError)
DoSystemConsoleRolesCreationMigration()
DoUploadFile(c *request.Context, now time.Time, rawTeamId string, rawChannelId string, rawUserId string, rawFilename string, data []byte) (*model.FileInfo, *model.AppError)
DoUploadFileExpectModification(c *request.Context, now time.Time, rawTeamId string, rawChannelId string, rawUserId string, rawFilename string, data []byte) (*model.FileInfo, []byte, *model.AppError)
DoUploadFileExpectModification(c request.CTX, now time.Time, rawTeamId string, rawChannelId string, rawUserId string, rawFilename string, data []byte) (*model.FileInfo, []byte, *model.AppError)
DownloadFromURL(downloadURL string) ([]byte, error)
EnableUserAccessToken(token *model.UserAccessToken) *model.AppError
EnvironmentConfig(filter func(reflect.StructField) bool) map[string]any
@@ -837,8 +837,8 @@ type AppIface interface {
GetWarnMetricsStatus() (map[string]*model.WarnMetricStatus, *model.AppError)
HTTPService() httpservice.HTTPService
Handle404(w http.ResponseWriter, r *http.Request)
HandleCommandResponse(c *request.Context, command *model.Command, args *model.CommandArgs, response *model.CommandResponse, builtIn bool) (*model.CommandResponse, *model.AppError)
HandleCommandResponsePost(c *request.Context, command *model.Command, args *model.CommandArgs, response *model.CommandResponse, builtIn bool) (*model.Post, *model.AppError)
HandleCommandResponse(c request.CTX, command *model.Command, args *model.CommandArgs, response *model.CommandResponse, builtIn bool) (*model.CommandResponse, *model.AppError)
HandleCommandResponsePost(c request.CTX, command *model.Command, args *model.CommandArgs, response *model.CommandResponse, builtIn bool) (*model.Post, *model.AppError)
HandleCommandWebhook(c *request.Context, hookID string, response *model.CommandResponse) *model.AppError
HandleImages(previewPathList []string, thumbnailPathList []string, fileData [][]byte)
HandleIncomingWebhook(c *request.Context, hookID string, req *model.IncomingWebhookRequest) *model.AppError
@@ -874,7 +874,7 @@ type AppIface interface {
JoinUserToTeam(c request.CTX, team *model.Team, user *model.User, userRequestorId string) (*model.TeamMember, *model.AppError)
Ldap() einterfaces.LdapInterface
LeaveChannel(c request.CTX, channelID string, userID string) *model.AppError
LeaveTeam(c *request.Context, team *model.Team, user *model.User, requestorId string) *model.AppError
LeaveTeam(c request.CTX, team *model.Team, user *model.User, requestorId string) *model.AppError
License() *model.License
LimitedClientConfig() map[string]string
ListAllCommands(teamID string, T i18n.TranslateFunc) ([]*model.Command, *model.AppError)
@@ -955,7 +955,7 @@ type AppIface interface {
RemoveTeamIcon(teamID string) *model.AppError
RemoveTeamsFromRetentionPolicy(policyID string, teamIDs []string) *model.AppError
RemoveUserFromChannel(c request.CTX, userIDToRemove string, removerUserId string, channel *model.Channel) *model.AppError
RemoveUserFromTeam(c *request.Context, teamID string, userID string, requestorId string) *model.AppError
RemoveUserFromTeam(c request.CTX, teamID string, userID string, requestorId string) *model.AppError
RemoveUsersFromChannelNotMemberOfTeam(c request.CTX, remover *model.User, channel *model.Channel, team *model.Team) *model.AppError
RequestLicenseAndAckWarnMetric(c *request.Context, warnMetricId string, isBot bool) *model.AppError
ResetPasswordFromToken(c request.CTX, userSuppliedTokenString, newPassword string) *model.AppError
@@ -1077,7 +1077,7 @@ type AppIface interface {
TotalWebsocketConnections() int
TriggerWebhook(c request.CTX, payload *model.OutgoingWebhookPayload, hook *model.OutgoingWebhook, post *model.Post, channel *model.Channel)
UnregisterPluginCommand(pluginID, teamID, trigger string)
UpdateActive(c *request.Context, user *model.User, active bool) (*model.User, *model.AppError)
UpdateActive(c request.CTX, user *model.User, active bool) (*model.User, *model.AppError)
UpdateChannelMemberNotifyProps(c request.CTX, data map[string]string, channelID string, userID string) (*model.ChannelMember, *model.AppError)
UpdateChannelMemberRoles(c request.CTX, channelID string, userID string, newRoles string) (*model.ChannelMember, *model.AppError)
UpdateChannelMemberSchemeRoles(c request.CTX, channelID string, userID string, isSchemeGuest bool, isSchemeUser bool, isSchemeAdmin bool) (*model.ChannelMember, *model.AppError)
@@ -1122,7 +1122,7 @@ type AppIface interface {
UpdateThreadReadForUserByPost(c request.CTX, currentSessionId, userID, teamID, threadID, postID string) (*model.ThreadResponse, *model.AppError)
UpdateThreadsReadForUser(userID, teamID string) *model.AppError
UpdateUser(c request.CTX, user *model.User, sendNotifications bool) (*model.User, *model.AppError)
UpdateUserActive(c *request.Context, userID string, active bool) *model.AppError
UpdateUserActive(c request.CTX, userID string, active bool) *model.AppError
UpdateUserAsUser(c request.CTX, user *model.User, asAdmin bool) (*model.User, *model.AppError)
UpdateUserAuth(userID string, userAuth *model.UserAuth) (*model.UserAuth, *model.AppError)
UpdateUserRoles(c request.CTX, userID string, newRoles string, sendWebSocketEvent bool) (*model.User, *model.AppError)

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

@@ -38,7 +38,7 @@ func (w *botServiceWrapper) EnsureBot(c *request.Context, productID string, bot
// any ensureBotOptions hence it is not required for now.
// TODO: Once the focalboard migration completed, we should add this logic to the app and
// let plugin-api use the same code
func (a *App) EnsureBot(c *request.Context, productID string, bot *model.Bot) (string, error) {
func (a *App) EnsureBot(c request.CTX, productID string, bot *model.Bot) (string, error) {
if bot == nil {
return "", errors.New("passed a nil bot")
}
@@ -77,7 +77,7 @@ func (a *App) EnsureBot(c *request.Context, productID string, bot *model.Bot) (s
return "", fmt.Errorf("failed to set plugin key: %w", err)
}
} else {
a.Srv().Log.Error("Product attempted to use an account that already exists. Convert user to a bot "+
c.Logger().Error("Product attempted to use an account that already exists. Convert user to a bot "+
"account in the CLI by running 'mattermost user convert <username> --bot'. If the user is an "+
"existing user account you want to preserve, change its username and restart the Mattermost server, "+
"after which the plugin will create a bot account with that name. For more information about bot "+
@@ -103,7 +103,7 @@ func (a *App) EnsureBot(c *request.Context, productID string, bot *model.Bot) (s
}
// CreateBot creates the given bot and corresponding user.
func (a *App) CreateBot(c *request.Context, bot *model.Bot) (*model.Bot, *model.AppError) {
func (a *App) CreateBot(c request.CTX, bot *model.Bot) (*model.Bot, *model.AppError) {
vErr := bot.IsValidCreate()
if vErr != nil {
return nil, vErr
@@ -391,7 +391,7 @@ func (a *App) GetBots(options *model.BotGetOptions) (model.BotList, *model.AppEr
}
// UpdateBotActive marks a bot as active or inactive, along with its corresponding user.
func (a *App) UpdateBotActive(c *request.Context, botUserId string, active bool) (*model.Bot, *model.AppError) {
func (a *App) UpdateBotActive(c request.CTX, botUserId string, active bool) (*model.Bot, *model.AppError) {
user, nErr := a.Srv().Store.User().Get(context.Background(), botUserId)
if nErr != nil {
var nfErr *store.ErrNotFound
@@ -498,7 +498,7 @@ func (a *App) UpdateBotOwner(botUserId, newOwnerId string) (*model.Bot, *model.A
}
// disableUserBots disables all bots owned by the given user.
func (a *App) disableUserBots(c *request.Context, userID string) *model.AppError {
func (a *App) disableUserBots(c request.CTX, userID string) *model.AppError {
perPage := 20
for {
options := &model.BotGetOptions{
@@ -516,7 +516,7 @@ func (a *App) disableUserBots(c *request.Context, userID string) *model.AppError
for _, bot := range userBots {
_, err := a.UpdateBotActive(c, bot.UserId, false)
if err != nil {
mlog.Warn("Unable to deactivate bot.", mlog.String("bot_user_id", bot.UserId), mlog.Err(err))
c.Logger().Warn("Unable to deactivate bot.", mlog.String("bot_user_id", bot.UserId), mlog.Err(err))
}
}
@@ -531,7 +531,7 @@ func (a *App) disableUserBots(c *request.Context, userID string) *model.AppError
return nil
}
func (a *App) notifySysadminsBotOwnerDeactivated(c *request.Context, userID string) *model.AppError {
func (a *App) notifySysadminsBotOwnerDeactivated(c request.CTX, userID string) *model.AppError {
perPage := 25
botOptions := &model.BotGetOptions{
OwnerId: userID,

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

@@ -91,17 +91,10 @@ func (a *App) JoinDefaultChannels(c request.CTX, teamID string, user *model.User
}
}
var err *model.AppError
for _, channelName := range a.DefaultChannelNames(c) {
channel, channelErr := a.Srv().Store.Channel().GetByName(teamID, channelName, true)
if channelErr != nil {
var nfErr *store.ErrNotFound
switch {
case errors.As(err, &nfErr):
err = model.NewAppError("JoinDefaultChannels", "app.channel.get_by_name.missing.app_error", nil, nfErr.Error(), http.StatusNotFound)
default:
err = model.NewAppError("JoinDefaultChannels", "app.channel.get_by_name.existing.app_error", nil, channelErr.Error(), http.StatusInternalServerError)
}
c.Logger().Warn("No default channel with this name", mlog.String("channelName", channelName), mlog.String("teamID", teamID), mlog.Err(channelErr))
continue
}
@@ -661,7 +654,7 @@ func (a *App) UpdateChannel(c request.CTX, channel *model.Channel) (*model.Chann
messageWs := model.NewWebSocketEvent(model.WebsocketEventChannelUpdated, "", channel.Id, "", nil)
channelJSON, jsonErr := json.Marshal(channel)
if jsonErr != nil {
c.Logger().Warn("Failed to encode channel to JSON", mlog.Err(jsonErr))
return nil, model.NewAppError("UpdateChannel", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
messageWs.Add("channel", string(channelJSON))
a.Publish(messageWs)
@@ -1019,7 +1012,9 @@ func (a *App) PatchChannelModerationsForChannel(c request.CTX, channel *model.Ch
if err != nil {
return nil, err
}
a.sendUpdatedRoleEvent(adminRole)
if appErr := a.sendUpdatedRoleEvent(adminRole); appErr != nil {
return nil, appErr
}
message := model.NewWebSocketEvent(model.WebsocketEventChannelSchemeUpdated, "", channel.Id, "", nil)
a.Publish(message)
@@ -1285,7 +1280,7 @@ func (a *App) UpdateChannelMemberNotifyProps(c request.CTX, data map[string]stri
evt := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", member.UserId, nil)
memberJSON, jsonErr := json.Marshal(member)
if jsonErr != nil {
c.Logger().Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr))
return nil, model.NewAppError("UpdateChannelMemberNotifyProps", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
evt.Add("channelMember", string(memberJSON))
a.Publish(evt)
@@ -1314,7 +1309,7 @@ func (a *App) updateChannelMember(c request.CTX, member *model.ChannelMember) (*
evt := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", member.UserId, nil)
memberJSON, jsonErr := json.Marshal(member)
if jsonErr != nil {
c.Logger().Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr))
return nil, model.NewAppError("updateChannelMember", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
evt.Add("channelMember", string(memberJSON))
a.Publish(evt)
@@ -1587,7 +1582,7 @@ func (a *App) AddChannelMember(c request.CTX, userID string, channel *model.Chan
if opts.UserRequestorID == "" || userID == opts.UserRequestorID {
if err := a.postJoinChannelMessage(c, user, channel); err != nil {
mlog.Error("Failed to post join channel message", mlog.Err(err))
return nil, err
}
} else {
a.Srv().Go(func() {
@@ -2513,11 +2508,9 @@ func (a *App) RemoveUserFromChannel(c request.CTX, userIDToRemove string, remove
return err
}
} else {
a.Srv().Go(func() {
if err := a.postRemoveFromChannelMessage(c, removerUserId, user, channel); err != nil {
mlog.Error("Failed to post user removal message", mlog.Err(err))
}
})
if err := a.postRemoveFromChannelMessage(c, removerUserId, user, channel); err != nil {
c.Logger().Error("Failed to post user removal message", mlog.Err(err))
}
}
return nil
@@ -2701,7 +2694,7 @@ func (a *App) markChannelAsUnreadFromPostCRTUnsupported(c request.CTX, postID st
if a.IsCRTEnabledForUser(c, userID) {
payload, jsonErr := json.Marshal(thread)
if jsonErr != nil {
c.Logger().Warn("Failed to encode thread to JSON")
return nil, model.NewAppError("MarkChannelAsUnreadFromPost", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
message := model.NewWebSocketEvent(model.WebsocketEventThreadUpdated, channel.TeamId, "", userID, nil)
message.Add("thread", string(payload))
@@ -3268,7 +3261,7 @@ func (a *App) setChannelsMuted(c request.CTX, channelIDs []string, userID string
memberJSON, jsonErr := json.Marshal(member)
if jsonErr != nil {
c.Logger().Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr))
return nil, model.NewAppError("setChannelsMuted", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
evt.Add("channelMember", string(memberJSON))
@@ -3369,21 +3362,22 @@ func (a *App) forEachChannelMember(c request.CTX, channelID string, f func(model
return nil
}
func (a *App) ClearChannelMembersCache(c request.CTX, channelID string) {
func (a *App) ClearChannelMembersCache(c request.CTX, channelID string) error {
clearSessionCache := func(channelMember model.ChannelMember) error {
a.ClearSessionCacheForUser(channelMember.UserId)
message := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", channelMember.UserId, nil)
memberJSON, jsonErr := json.Marshal(channelMember)
if jsonErr != nil {
c.Logger().Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr))
return jsonErr
}
message.Add("channelMember", string(memberJSON))
a.Publish(message)
return nil
}
if err := a.forEachChannelMember(c, channelID, clearSessionCache); err != nil {
c.Logger().Warn("error clearing cache for channel members", mlog.String("channel_id", channelID))
return fmt.Errorf("error clearing cache for channel members: channel_id: %s, error: %v", channelID, err)
}
return nil
}
func (a *App) GetMemberCountsByGroup(ctx context.Context, channelID string, includeTimezones bool) ([]*model.ChannelMemberCountByGroup, *model.AppError) {

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

@@ -151,7 +151,7 @@ func (a *App) UpdateSidebarCategories(c request.CTX, userID, teamID string, cate
updatedCategoriesJSON, jsonErr := json.Marshal(updatedCategories)
if jsonErr != nil {
c.Logger().Warn("Failed to encode original categories to JSON", mlog.Err(jsonErr))
return nil, model.NewAppError("UpdateSidebarCategories", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
message.Add("updatedCategories", string(updatedCategoriesJSON))

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

@@ -347,6 +347,33 @@ func TestJoinDefaultChannelsExperimentalDefaultChannels(t *testing.T) {
}
}
func TestJoinDefaultChannelsExperimentalDefaultChannelsMissing(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
basicChannel2 := th.CreateChannel(th.Context, th.BasicTeam)
defer th.App.PermanentDeleteChannel(th.Context, basicChannel2)
defaultChannelList := []string{th.BasicChannel.Name, basicChannel2.Name, "thischanneldoesnotexist", basicChannel2.Name}
th.App.Config().TeamSettings.ExperimentalDefaultChannels = defaultChannelList
user := th.CreateUser()
require.Nil(t, th.App.JoinDefaultChannels(th.Context, th.BasicTeam.Id, user, false, ""))
for _, channelName := range defaultChannelList {
if channelName == "thischanneldoesnotexist" {
continue // skip the non-existent channel
}
channel, err := th.App.GetChannelByName(th.Context, channelName, th.BasicTeam.Id, false)
require.Nil(t, err, "Expected nil, didn't receive nil")
member, err := th.App.GetChannelMember(th.Context, channel.Id, user.Id)
require.NotNil(t, member, "Expected member object, got nil")
require.Nil(t, err, "Expected nil object, didn't receive nil")
}
}
func TestCreateChannelPublicCreatesChannelMemberHistoryRecord(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
@@ -2065,7 +2092,7 @@ func TestClearChannelMembersCache(t *testing.T) {
mockStore.On("Channel").Return(&mockChannelStore)
mockStore.On("GetDBSchemaVersion").Return(1, nil)
th.App.ClearChannelMembersCache(th.Context, "channelID")
require.NoError(t, th.App.ClearChannelMembersCache(th.Context, "channelID"))
}
func TestGetMemberCountsByGroup(t *testing.T) {

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

@@ -33,7 +33,7 @@ var atMentionRegexp = regexp.MustCompile(`\B@[[:alnum:]][[:alnum:]\.\-_:]*`)
type CommandProvider interface {
GetTrigger() string
GetCommand(a *App, T i18n.TranslateFunc) *model.Command
DoCommand(a *App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse
DoCommand(a *App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse
}
var commandProviders = make(map[string]CommandProvider)
@@ -52,7 +52,7 @@ func GetCommandProvider(name string) CommandProvider {
}
// @openTracingParams teamID, skipSlackParsing
func (a *App) CreateCommandPost(c *request.Context, post *model.Post, teamID string, response *model.CommandResponse, skipSlackParsing bool) (*model.Post, *model.AppError) {
func (a *App) CreateCommandPost(c request.CTX, post *model.Post, teamID string, response *model.CommandResponse, skipSlackParsing bool) (*model.Post, *model.AppError) {
if skipSlackParsing {
post.Message = response.Text
} else {
@@ -180,7 +180,7 @@ func (a *App) ListAllCommands(teamID string, T i18n.TranslateFunc) ([]*model.Com
}
// @openTracingParams args
func (a *App) ExecuteCommand(c *request.Context, args *model.CommandArgs) (*model.CommandResponse, *model.AppError) {
func (a *App) ExecuteCommand(c request.CTX, args *model.CommandArgs) (*model.CommandResponse, *model.AppError) {
trigger := ""
message := ""
index := strings.IndexFunc(args.Command, unicode.IsSpace)
@@ -198,7 +198,7 @@ func (a *App) ExecuteCommand(c *request.Context, args *model.CommandArgs) (*mode
clientTriggerId, triggerId, appErr := model.GenerateTriggerId(args.UserId, a.AsymmetricSigningKey())
if appErr != nil {
mlog.Warn("error occurred in generating trigger Id for a user ", mlog.Err(appErr))
c.Logger().Warn("error occurred in generating trigger Id for a user ", mlog.Err(appErr))
}
args.TriggerId = triggerId
@@ -235,7 +235,7 @@ func (a *App) ExecuteCommand(c *request.Context, args *model.CommandArgs) (*mode
// MentionsToTeamMembers returns all the @ mentions found in message that
// belong to users in the specified team, linking them to their users
func (a *App) MentionsToTeamMembers(message, teamID string) model.UserMentionMap {
func (a *App) MentionsToTeamMembers(c request.CTX, message, teamID string) model.UserMentionMap {
type mentionMapItem struct {
Name string
Id string
@@ -253,7 +253,7 @@ func (a *App) MentionsToTeamMembers(message, teamID string) model.UserMentionMap
var nfErr *store.ErrNotFound
if nErr != nil && !errors.As(nErr, &nfErr) {
mlog.Warn("Failed to retrieve user @"+mention, mlog.Err(nErr))
c.Logger().Warn("Failed to retrieve user @"+mention, mlog.Err(nErr))
return
}
@@ -347,7 +347,7 @@ func (a *App) MentionsToPublicChannels(c request.CTX, message, teamID string) mo
// tryExecuteBuiltInCommand attempts to run a built in command based on the given arguments. If no such command can be
// found, returns nil for all arguments.
func (a *App) tryExecuteBuiltInCommand(c *request.Context, args *model.CommandArgs, trigger string, message string) (*model.Command, *model.CommandResponse) {
func (a *App) tryExecuteBuiltInCommand(c request.CTX, args *model.CommandArgs, trigger string, message string) (*model.Command, *model.CommandResponse) {
provider := GetCommandProvider(trigger)
if provider == nil {
return nil, nil
@@ -443,7 +443,7 @@ func (a *App) tryExecuteCustomCommand(c request.CTX, args *model.CommandArgs, tr
return nil, nil, nil
}
mlog.Debug("Executing command", mlog.String("command", trigger), mlog.String("user_id", args.UserId))
c.Logger().Debug("Executing command", mlog.String("command", trigger), mlog.String("user_id", args.UserId))
p := url.Values{}
p.Set("token", cmd.Token)
@@ -462,7 +462,7 @@ func (a *App) tryExecuteCustomCommand(c request.CTX, args *model.CommandArgs, tr
p.Set("trigger_id", args.TriggerId)
userMentionMap := a.MentionsToTeamMembers(message, team.Id)
userMentionMap := a.MentionsToTeamMembers(c, message, team.Id)
for key, values := range userMentionMap.ToURLValues() {
p[key] = values
}
@@ -536,7 +536,7 @@ func (a *App) DoCommandRequest(cmd *model.Command, p url.Values) (*model.Command
return cmd, response, nil
}
func (a *App) HandleCommandResponse(c *request.Context, command *model.Command, args *model.CommandArgs, response *model.CommandResponse, builtIn bool) (*model.CommandResponse, *model.AppError) {
func (a *App) HandleCommandResponse(c request.CTX, command *model.Command, args *model.CommandArgs, response *model.CommandResponse, builtIn bool) (*model.CommandResponse, *model.AppError) {
trigger := ""
if args.Command != "" {
parts := strings.Split(args.Command, " ")
@@ -570,7 +570,7 @@ func (a *App) HandleCommandResponse(c *request.Context, command *model.Command,
return response, nil
}
func (a *App) HandleCommandResponsePost(c *request.Context, command *model.Command, args *model.CommandArgs, response *model.CommandResponse, builtIn bool) (*model.Post, *model.AppError) {
func (a *App) HandleCommandResponsePost(c request.CTX, command *model.Command, args *model.CommandArgs, response *model.CommandResponse, builtIn bool) (*model.Post, *model.AppError) {
post := &model.Post{}
post.ChannelId = args.ChannelId
post.RootId = args.RootId

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

@@ -659,7 +659,7 @@ func (p *testCommandProvider) GetCommand(a *App, T i18n.TranslateFunc) *model.Co
}
}
func (p *testCommandProvider) DoCommand(a *App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (p *testCommandProvider) DoCommand(a *App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
return &model.CommandResponse{
Text: "I do nothing!",
ResponseType: model.CommandResponseTypeEphemeral,

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

@@ -79,12 +79,12 @@ func (w *configWrapper) SaveConfig(newCfg *model.Config, sendConfigChangeCluster
}
if w.srv.startMetrics && *w.Config().MetricsSettings.Enable {
if w.srv.Metrics != nil {
w.srv.Metrics.Register()
if w.srv.GetMetrics() != nil {
w.srv.GetMetrics().Register()
}
w.srv.SetupMetricsServer()
w.srv.platform.RestartMetrics() // TODO: remove when this moved to the platform service
} else {
w.srv.StopMetricsServer()
w.srv.platform.ShutdownMetrics() // TODO: remove when this moved to the platform service
}
if w.srv.Cluster != nil {

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

@@ -82,7 +82,7 @@ func (a *App) CreateEmoji(sessionUserId string, emoji *model.Emoji, multiPartIma
message := model.NewWebSocketEvent(model.WebsocketEventEmojiAdded, "", "", "", nil)
emojiJSON, jsonErr := json.Marshal(emoji)
if jsonErr != nil {
mlog.Warn("Failed to encode emoji to JSON", mlog.Err(jsonErr))
return nil, model.NewAppError("CreateEmoji", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
message.Add("emoji", string(emojiJSON))
a.Publish(message)

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

@@ -112,10 +112,6 @@ func RegisterLicenseInterface(f func(*Server) einterfaces.LicenseInterface) {
}
func (s *Server) initEnterprise() {
if metricsInterface != nil {
s.Metrics = metricsInterface(s)
}
if clusterInterface != nil && s.Cluster == nil {
s.Cluster = clusterInterface(s)
}

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

@@ -15,6 +15,7 @@ import (
"github.com/pkg/errors"
"github.com/mattermost/mattermost-server/v6/app/request"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/store"
@@ -61,7 +62,7 @@ var exportablePreferences = map[ComparablePreference]string{{
}: "EmailInterval",
}
func (a *App) BulkExport(writer io.Writer, outPath string, opts model.BulkExportOpts) *model.AppError {
func (a *App) BulkExport(ctx request.CTX, writer io.Writer, outPath string, opts model.BulkExportOpts) *model.AppError {
var zipWr *zip.Writer
if opts.CreateArchive {
var err error
@@ -74,52 +75,52 @@ func (a *App) BulkExport(writer io.Writer, outPath string, opts model.BulkExport
}
}
mlog.Info("Bulk export: exporting version")
ctx.Logger().Info("Bulk export: exporting version")
if err := a.exportVersion(writer); err != nil {
return err
}
mlog.Info("Bulk export: exporting teams")
ctx.Logger().Info("Bulk export: exporting teams")
teamNames, err := a.exportAllTeams(writer)
if err != nil {
return err
}
mlog.Info("Bulk export: exporting channels")
ctx.Logger().Info("Bulk export: exporting channels")
if err = a.exportAllChannels(writer, teamNames); err != nil {
return err
}
mlog.Info("Bulk export: exporting users")
ctx.Logger().Info("Bulk export: exporting users")
if err = a.exportAllUsers(writer); err != nil {
return err
}
mlog.Info("Bulk export: exporting posts")
attachments, err := a.exportAllPosts(writer, opts.IncludeAttachments)
ctx.Logger().Info("Bulk export: exporting posts")
attachments, err := a.exportAllPosts(ctx, writer, opts.IncludeAttachments)
if err != nil {
return err
}
mlog.Info("Bulk export: exporting emoji")
ctx.Logger().Info("Bulk export: exporting emoji")
emojiPaths, err := a.exportCustomEmoji(writer, outPath, "exported_emoji", !opts.CreateArchive)
if err != nil {
return err
}
mlog.Info("Bulk export: exporting direct channels")
ctx.Logger().Info("Bulk export: exporting direct channels")
if err = a.exportAllDirectChannels(writer); err != nil {
return err
}
mlog.Info("Bulk export: exporting direct posts")
directAttachments, err := a.exportAllDirectPosts(writer, opts.IncludeAttachments)
ctx.Logger().Info("Bulk export: exporting direct posts")
directAttachments, err := a.exportAllDirectPosts(ctx, writer, opts.IncludeAttachments)
if err != nil {
return err
}
if opts.IncludeAttachments {
mlog.Info("Bulk export: exporting file attachments")
ctx.Logger().Info("Bulk export: exporting file attachments")
for _, attachment := range attachments {
if err := a.exportFile(outPath, *attachment.Path, zipWr); err != nil {
return err
@@ -383,7 +384,7 @@ func (a *App) buildUserNotifyProps(notifyProps model.StringMap) *UserNotifyProps
}
}
func (a *App) exportAllPosts(writer io.Writer, withAttachments bool) ([]AttachmentImportData, *model.AppError) {
func (a *App) exportAllPosts(ctx request.CTX, writer io.Writer, withAttachments bool) ([]AttachmentImportData, *model.AppError) {
var attachments []AttachmentImportData
afterId := strings.Repeat("0", 26)
@@ -407,7 +408,7 @@ func (a *App) exportAllPosts(writer io.Writer, withAttachments bool) ([]Attachme
postLine := ImportLineForPost(post)
replies, replyAttachments, err := a.buildPostReplies(post.Id, withAttachments)
replies, replyAttachments, err := a.buildPostReplies(ctx, post.Id, withAttachments)
if err != nil {
return nil, err
}
@@ -419,7 +420,7 @@ func (a *App) exportAllPosts(writer io.Writer, withAttachments bool) ([]Attachme
postLine.Post.Replies = &replies
postLine.Post.Reactions = &[]ReactionImportData{}
if post.HasReactions {
postLine.Post.Reactions, err = a.BuildPostReactions(post.Id)
postLine.Post.Reactions, err = a.BuildPostReactions(ctx, post.Id)
if err != nil {
return nil, err
}
@@ -444,7 +445,7 @@ func (a *App) exportAllPosts(writer io.Writer, withAttachments bool) ([]Attachme
}
}
func (a *App) buildPostReplies(postID string, withAttachments bool) ([]ReplyImportData, []AttachmentImportData, *model.AppError) {
func (a *App) buildPostReplies(ctx request.CTX, postID string, withAttachments bool) ([]ReplyImportData, []AttachmentImportData, *model.AppError) {
var replies []ReplyImportData
var attachments []AttachmentImportData
@@ -457,7 +458,7 @@ func (a *App) buildPostReplies(postID string, withAttachments bool) ([]ReplyImpo
replyImportObject := ImportReplyFromPost(reply)
if reply.HasReactions {
var appErr *model.AppError
replyImportObject.Reactions, appErr = a.BuildPostReactions(reply.Id)
replyImportObject.Reactions, appErr = a.BuildPostReactions(ctx, reply.Id)
if appErr != nil {
return nil, nil, appErr
}
@@ -479,7 +480,7 @@ func (a *App) buildPostReplies(postID string, withAttachments bool) ([]ReplyImpo
return replies, attachments, nil
}
func (a *App) BuildPostReactions(postID string) (*[]ReactionImportData, *model.AppError) {
func (a *App) BuildPostReactions(ctx request.CTX, postID string) (*[]ReactionImportData, *model.AppError) {
var reactionsOfPost []ReactionImportData
reactions, nErr := a.Srv().Store.Reaction().GetForPost(postID, true)
@@ -492,7 +493,7 @@ func (a *App) BuildPostReactions(postID string) (*[]ReactionImportData, *model.A
if err != nil {
var nfErr *store.ErrNotFound
if errors.As(err, &nfErr) { // this is a valid case, the user that reacted might've been deleted by now
mlog.Info("Skipping reactions by user since the entity doesn't exist anymore", mlog.String("user_id", reaction.UserId))
ctx.Logger().Info("Skipping reactions by user since the entity doesn't exist anymore", mlog.String("user_id", reaction.UserId))
continue
}
return nil, model.NewAppError("BuildPostReactions", "app.user.get.app_error", nil, err.Error(), http.StatusInternalServerError)
@@ -634,7 +635,7 @@ func (a *App) exportAllDirectChannels(writer io.Writer) *model.AppError {
return nil
}
func (a *App) exportAllDirectPosts(writer io.Writer, withAttachments bool) ([]AttachmentImportData, *model.AppError) {
func (a *App) exportAllDirectPosts(ctx request.CTX, writer io.Writer, withAttachments bool) ([]AttachmentImportData, *model.AppError) {
var attachments []AttachmentImportData
afterId := strings.Repeat("0", 26)
for {
@@ -670,7 +671,7 @@ func (a *App) exportAllDirectPosts(writer io.Writer, withAttachments bool) ([]At
}
// Do the Replies.
replies, replyAttachments, err := a.buildPostReplies(post.Id, withAttachments)
replies, replyAttachments, err := a.buildPostReplies(ctx, post.Id, withAttachments)
if err != nil {
return nil, err
}

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

@@ -42,7 +42,7 @@ func TestReactionsOfPost(t *testing.T) {
th.App.SaveReactionForPost(th.Context, &reactionObject)
th.App.SaveReactionForPost(th.Context, &reactionObjectDeleted)
reactionsOfPost, err := th.App.BuildPostReactions(post.Id)
reactionsOfPost, err := th.App.BuildPostReactions(th.Context, post.Id)
require.Nil(t, err)
assert.Equal(t, reactionObject.EmojiName, *(*reactionsOfPost)[0].EmojiName)
@@ -179,7 +179,7 @@ func TestExportAllUsers(t *testing.T) {
require.Nil(t, err)
var b bytes.Buffer
err = th1.App.BulkExport(&b, "somePath", model.BulkExportOpts{})
err = th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{})
require.Nil(t, err)
th2 := Setup(t)
@@ -227,7 +227,7 @@ func TestExportDMChannel(t *testing.T) {
th1.CreateDmChannel(th1.BasicUser2)
var b bytes.Buffer
err := th1.App.BulkExport(&b, "somePath", model.BulkExportOpts{})
err := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{})
require.Nil(t, err)
channels, nErr := th1.App.Srv().Store.Channel().GetAllDirectChannelsForExportAfter(1000, "00000000")
@@ -268,7 +268,7 @@ func TestExportDMChannel(t *testing.T) {
th1.App.PermanentDeleteUser(th1.Context, th1.BasicUser)
var b bytes.Buffer
err := th1.App.BulkExport(&b, "somePath", model.BulkExportOpts{})
err := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{})
require.Nil(t, err)
th2 := Setup(t).InitBasic()
@@ -292,7 +292,7 @@ func TestExportDMChannelToSelf(t *testing.T) {
th1.CreateDmChannel(th1.BasicUser)
var b bytes.Buffer
err := th1.App.BulkExport(&b, "somePath", model.BulkExportOpts{})
err := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{})
require.Nil(t, err)
channels, nErr := th1.App.Srv().Store.Channel().GetAllDirectChannelsForExportAfter(1000, "00000000")
@@ -330,7 +330,7 @@ func TestExportGMChannel(t *testing.T) {
th1.CreateGroupChannel(th1.Context, user1, user2)
var b bytes.Buffer
err := th1.App.BulkExport(&b, "somePath", model.BulkExportOpts{})
err := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{})
require.Nil(t, err)
channels, nErr := th1.App.Srv().Store.Channel().GetAllDirectChannelsForExportAfter(1000, "00000000")
@@ -362,7 +362,7 @@ func TestExportGMandDMChannels(t *testing.T) {
th1.CreateGroupChannel(th1.Context, user1, user2)
var b bytes.Buffer
err := th1.App.BulkExport(&b, "somePath", model.BulkExportOpts{})
err := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{})
require.Nil(t, err)
channels, nErr := th1.App.Srv().Store.Channel().GetAllDirectChannelsForExportAfter(1000, "00000000")
@@ -445,7 +445,7 @@ func TestExportDMandGMPost(t *testing.T) {
assert.Equal(t, 4, len(posts))
var b bytes.Buffer
appErr := th1.App.BulkExport(&b, "somePath", model.BulkExportOpts{})
appErr := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{})
require.Nil(t, appErr)
th1.TearDown()
@@ -520,7 +520,7 @@ func TestExportPostWithProps(t *testing.T) {
require.NotEmpty(t, posts[1].Props)
var b bytes.Buffer
appErr := th1.App.BulkExport(&b, "somePath", model.BulkExportOpts{})
appErr := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{})
require.Nil(t, appErr)
th1.TearDown()
@@ -558,7 +558,7 @@ func TestExportDMPostWithSelf(t *testing.T) {
th1.CreatePost(dmChannel)
var b bytes.Buffer
err := th1.App.BulkExport(&b, "somePath", model.BulkExportOpts{})
err := th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{})
require.Nil(t, err)
posts, nErr := th1.App.Srv().Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000")
@@ -626,7 +626,7 @@ func TestBulkExport(t *testing.T) {
IncludeAttachments: true,
CreateArchive: true,
}
appErr = th.App.BulkExport(exportFile, dir, opts)
appErr = th.App.BulkExport(th.Context, exportFile, dir, opts)
require.Nil(t, appErr)
th.TearDown()
@@ -663,7 +663,7 @@ func TestBuildPostReplies(t *testing.T) {
}
t.Run("basic post", func(t *testing.T) {
data, attachments, err := th.App.buildPostReplies(th.BasicPost.Id, true)
data, attachments, err := th.App.buildPostReplies(th.Context, th.BasicPost.Id, true)
require.Nil(t, err)
require.Empty(t, data)
require.Empty(t, attachments)
@@ -671,7 +671,7 @@ func TestBuildPostReplies(t *testing.T) {
t.Run("root post with attachments and no replies", func(t *testing.T) {
post := createPostWithAttachments(th, 5, "")
data, attachments, err := th.App.buildPostReplies(post.Id, true)
data, attachments, err := th.App.buildPostReplies(th.Context, post.Id, true)
require.Nil(t, err)
require.Empty(t, data)
require.Empty(t, attachments)
@@ -680,7 +680,7 @@ func TestBuildPostReplies(t *testing.T) {
t.Run("root post with attachments and a reply", func(t *testing.T) {
post := createPostWithAttachments(th, 5, "")
createPostWithAttachments(th, 0, post.Id)
data, attachments, err := th.App.buildPostReplies(post.Id, true)
data, attachments, err := th.App.buildPostReplies(th.Context, post.Id, true)
require.Nil(t, err)
require.Len(t, data, 1)
require.Empty(t, attachments)
@@ -690,7 +690,7 @@ func TestBuildPostReplies(t *testing.T) {
post := createPostWithAttachments(th, 5, "")
reply1 := createPostWithAttachments(th, 2, post.Id)
reply2 := createPostWithAttachments(th, 3, post.Id)
data, attachments, err := th.App.buildPostReplies(post.Id, true)
data, attachments, err := th.App.buildPostReplies(th.Context, post.Id, true)
require.Nil(t, err)
require.Len(t, data, 2)
require.Len(t, attachments, 5)
@@ -717,7 +717,7 @@ func TestExportDeletedTeams(t *testing.T) {
require.Nil(t, err)
var b bytes.Buffer
err = th1.App.BulkExport(&b, "somePath", model.BulkExportOpts{})
err = th1.App.BulkExport(th1.Context, &b, "somePath", model.BulkExportOpts{})
require.Nil(t, err)
th2 := Setup(t)

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

@@ -453,7 +453,7 @@ func GeneratePublicLinkHash(fileID, salt string) string {
}
// UploadFile uploads a single file in form of a completely constructed byte array for a channel.
func (a *App) UploadFile(c *request.Context, data []byte, channelID string, filename string) (*model.FileInfo, *model.AppError) {
func (a *App) UploadFile(c request.CTX, data []byte, channelID string, filename string) (*model.FileInfo, *model.AppError) {
_, err := a.GetChannel(c, channelID)
if err != nil && channelID != "" {
return nil, model.NewAppError("UploadFile", "api.file.upload_file.incorrect_channelId.app_error",
@@ -853,7 +853,7 @@ func (t UploadFileTask) newAppError(id string, httpStatus int, extra ...any) *mo
return model.NewAppError("uploadFileTask", id, params, "", httpStatus)
}
func (a *App) DoUploadFileExpectModification(c *request.Context, now time.Time, rawTeamId string, rawChannelId string, rawUserId string, rawFilename string, data []byte) (*model.FileInfo, []byte, *model.AppError) {
func (a *App) DoUploadFileExpectModification(c request.CTX, now time.Time, rawTeamId string, rawChannelId string, rawUserId string, rawFilename string, data []byte) (*model.FileInfo, []byte, *model.AppError) {
filename := filepath.Base(rawFilename)
teamID := filepath.Base(rawTeamId)
channelID := filepath.Base(rawChannelId)

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

@@ -9,7 +9,6 @@ import (
"net/http"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/store"
)
@@ -139,7 +138,7 @@ func (a *App) CreateGroupWithUserIds(group *model.GroupWithUserIds) (*model.Grou
case errors.As(err, &invErr):
return nil, model.NewAppError("CreateGroupWithUserIds", "app.group.id.app_error", nil, invErr.Error(), http.StatusBadRequest)
case errors.As(err, &dupKey):
return nil, model.NewAppError("CreateGroup", "app.custom_group.unique_name", nil, dupKey.Error(), http.StatusBadRequest)
return nil, model.NewAppError("CreateGroupWithUserIds", "app.custom_group.unique_name", nil, dupKey.Error(), http.StatusBadRequest)
default:
return nil, model.NewAppError("CreateGroupWithUserIds", "app.insert_error", nil, err.Error(), http.StatusInternalServerError)
}
@@ -153,7 +152,7 @@ func (a *App) CreateGroupWithUserIds(group *model.GroupWithUserIds) (*model.Grou
group.MemberCount = model.NewInt(int(count))
groupJSON, jsonErr := json.Marshal(newGroup)
if jsonErr != nil {
mlog.Warn("Failed to encode group to JSON", mlog.Err(jsonErr))
return nil, model.NewAppError("CreateGroupWithUserIds", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
messageWs.Add("group", string(groupJSON))
a.Publish(messageWs)
@@ -172,13 +171,13 @@ func (a *App) UpdateGroup(group *model.Group) (*model.Group, *model.AppError) {
if err == nil {
count, countErr := a.Srv().Store.Group().GetMemberCount(updatedGroup.Id)
if countErr != nil {
return nil, model.NewAppError("CreateGroupWithUserIds", "app.group.id.app_error", nil, countErr.Error(), http.StatusBadRequest)
return nil, model.NewAppError("UpdateGroup", "app.group.id.app_error", nil, countErr.Error(), http.StatusBadRequest)
}
updatedGroup.MemberCount = model.NewInt(int(count))
messageWs := model.NewWebSocketEvent(model.WebsocketEventReceivedGroup, "", "", "", nil)
groupJSON, jsonErr := json.Marshal(updatedGroup)
if jsonErr != nil {
mlog.Warn("Failed to encode group to JSON", mlog.Err(jsonErr))
return nil, model.NewAppError("UpdateGroup", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
messageWs.Add("group", string(groupJSON))
a.Publish(messageWs)
@@ -272,7 +271,9 @@ func (a *App) UpsertGroupMember(groupID string, userID string) (*model.GroupMemb
}
}
a.publishGroupMemberEvent(model.WebsocketEventGroupMemberAdd, groupMember)
if appErr := a.publishGroupMemberEvent(model.WebsocketEventGroupMemberAdd, groupMember); appErr != nil {
return nil, appErr
}
return groupMember, nil
}
@@ -289,7 +290,9 @@ func (a *App) DeleteGroupMember(groupID string, userID string) (*model.GroupMemb
}
}
a.publishGroupMemberEvent(model.WebsocketEventGroupMemberDelete, groupMember)
if appErr := a.publishGroupMemberEvent(model.WebsocketEventGroupMemberDelete, groupMember); appErr != nil {
return nil, appErr
}
return groupMember, nil
}
@@ -743,7 +746,9 @@ func (a *App) UpsertGroupMembers(groupID string, userIDs []string) ([]*model.Gro
}
for _, groupMember := range members {
a.publishGroupMemberEvent(model.WebsocketEventGroupMemberAdd, groupMember)
if appErr := a.publishGroupMemberEvent(model.WebsocketEventGroupMemberAdd, groupMember); appErr != nil {
return nil, appErr
}
}
return members, nil
@@ -765,18 +770,21 @@ func (a *App) DeleteGroupMembers(groupID string, userIDs []string) ([]*model.Gro
}
for _, groupMember := range members {
a.publishGroupMemberEvent(model.WebsocketEventGroupMemberDelete, groupMember)
if appErr := a.publishGroupMemberEvent(model.WebsocketEventGroupMemberDelete, groupMember); appErr != nil {
return nil, appErr
}
}
return members, nil
}
func (a *App) publishGroupMemberEvent(eventName string, groupMember *model.GroupMember) {
func (a *App) publishGroupMemberEvent(eventName string, groupMember *model.GroupMember) *model.AppError {
messageWs := model.NewWebSocketEvent(eventName, "", "", groupMember.UserId, nil)
groupMemberJSON, jsonErr := json.Marshal(groupMember)
if jsonErr != nil {
mlog.Warn("failed to encode group member to JSON", mlog.Err(jsonErr))
return model.NewAppError("publishGroupMemberEvent", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
messageWs.Add("group_member", string(groupMemberJSON))
a.Publish(messageWs)
return nil
}

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

@@ -70,7 +70,7 @@ func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer boo
if includeCacheLayer {
// Adds the cache layer to the test store
options = append(options, StoreOverride(func(s *Server) store.Store {
lcl, err2 := localcachelayer.NewLocalCacheLayer(dbStore, s.Metrics, s.Cluster, s.CacheProvider)
lcl, err2 := localcachelayer.NewLocalCacheLayer(dbStore, s.GetMetrics(), s.Cluster, s.CacheProvider)
if err2 != nil {
panic(err2)
}

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

@@ -521,7 +521,7 @@ func (a *App) importUser(c request.CTX, data *UserImportData, dryRun bool) *mode
pref := model.Preference{UserId: savedUser.Id, Category: model.PreferenceCategoryTutorialSteps, Name: savedUser.Id, Value: "0"}
if err := a.Srv().Store.Preference().Save(model.Preferences{pref}); err != nil {
mlog.Warn("Encountered error saving tutorial preference", mlog.Err(err))
c.Logger().Warn("Encountered error saving tutorial preference", mlog.Err(err))
}
} else {
@@ -584,14 +584,14 @@ func (a *App) importUser(c request.CTX, data *UserImportData, dryRun bool) *mode
}
if err != nil {
mlog.Warn("Unable to open the profile image.", mlog.Err(err))
c.Logger().Warn("Unable to open the profile image.", mlog.Err(err))
} else {
defer file.Close()
if limitErr := checkImageLimits(file, *a.Config().FileSettings.MaxImageResolution); limitErr != nil {
return model.NewAppError("SetProfileImage", "api.user.upload_profile_user.check_image_limits.app_error", nil, "", http.StatusBadRequest)
}
if err := a.SetProfileImageFromFile(c, savedUser.Id, file); err != nil {
mlog.Warn("Unable to set the profile image from a file.", mlog.Err(err))
c.Logger().Warn("Unable to set the profile image from a file.", mlog.Err(err))
}
}
}
@@ -1137,7 +1137,7 @@ func (a *App) importReplies(c *request.Context, data []ReplyImportData, post *mo
reply.Message = *replyData.Message
reply.CreateAt = *replyData.CreateAt
if reply.CreateAt < post.CreateAt {
mlog.Warn("Reply CreateAt is before parent post CreateAt, setting it to parent post CreateAt", mlog.Int64("reply_create_at", reply.CreateAt), mlog.Int64("parent_create_at", post.CreateAt))
c.Logger().Warn("Reply CreateAt is before parent post CreateAt, setting it to parent post CreateAt", mlog.Int64("reply_create_at", reply.CreateAt), mlog.Int64("parent_create_at", post.CreateAt))
reply.CreateAt = post.CreateAt
}
if replyData.Type != nil {

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

@@ -71,10 +71,6 @@ func (w *licenseWrapper) RequestTrialLicense(requesterID string, users int, term
}
}
if *w.srv.Config().ServiceSettings.SiteURL == "" {
return model.NewAppError("RequestTrialLicense", "api.license.request_trial_license.no-site-url.app_error", nil, "", http.StatusBadRequest)
}
trialLicenseRequest := &model.TrialLicenseRequest{
ServerID: w.srv.TelemetryId(),
Name: requester.GetDisplayName(model.ShowFullName),

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

@@ -383,7 +383,7 @@ func (a *OpenTracingAppLayer) AddStatusCacheSkipClusterSend(status *model.Status
a.app.AddStatusCacheSkipClusterSend(status)
}
func (a *OpenTracingAppLayer) AddTeamMember(c *request.Context, teamID string, userID string) (*model.TeamMember, *model.AppError) {
func (a *OpenTracingAppLayer) AddTeamMember(c request.CTX, teamID string, userID string) (*model.TeamMember, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.AddTeamMember")
@@ -515,7 +515,7 @@ func (a *OpenTracingAppLayer) AddUserToChannel(c request.CTX, user *model.User,
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) AddUserToTeam(c *request.Context, teamID string, userID string, userRequestorId string) (*model.Team, *model.TeamMember, *model.AppError) {
func (a *OpenTracingAppLayer) AddUserToTeam(c request.CTX, teamID string, userID string, userRequestorId string) (*model.Team, *model.TeamMember, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.AddUserToTeam")
@@ -951,7 +951,7 @@ func (a *OpenTracingAppLayer) BroadcastStatus(status *model.Status) {
a.app.BroadcastStatus(status)
}
func (a *OpenTracingAppLayer) BuildPostReactions(postID string) (*[]app.ReactionImportData, *model.AppError) {
func (a *OpenTracingAppLayer) BuildPostReactions(ctx request.CTX, postID string) (*[]app.ReactionImportData, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.BuildPostReactions")
@@ -963,7 +963,7 @@ func (a *OpenTracingAppLayer) BuildPostReactions(postID string) (*[]app.Reaction
}()
defer span.Finish()
resultVar0, resultVar1 := a.app.BuildPostReactions(postID)
resultVar0, resultVar1 := a.app.BuildPostReactions(ctx, postID)
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
@@ -1017,7 +1017,7 @@ func (a *OpenTracingAppLayer) BuildSamlMetadataObject(idpMetadata []byte) (*mode
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) BulkExport(writer io.Writer, outPath string, opts model.BulkExportOpts) *model.AppError {
func (a *OpenTracingAppLayer) BulkExport(ctx request.CTX, writer io.Writer, outPath string, opts model.BulkExportOpts) *model.AppError {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.BulkExport")
@@ -1029,7 +1029,7 @@ func (a *OpenTracingAppLayer) BulkExport(writer io.Writer, outPath string, opts
}()
defer span.Finish()
resultVar0 := a.app.BulkExport(writer, outPath, opts)
resultVar0 := a.app.BulkExport(ctx, writer, outPath, opts)
if resultVar0 != nil {
span.LogFields(spanlog.Error(resultVar0))
@@ -1469,7 +1469,7 @@ func (a *OpenTracingAppLayer) CheckWebConn(userID string, connectionID string) *
return resultVar0
}
func (a *OpenTracingAppLayer) ClearChannelMembersCache(c request.CTX, channelID string) {
func (a *OpenTracingAppLayer) ClearChannelMembersCache(c request.CTX, channelID string) error {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.ClearChannelMembersCache")
@@ -1481,7 +1481,14 @@ func (a *OpenTracingAppLayer) ClearChannelMembersCache(c request.CTX, channelID
}()
defer span.Finish()
a.app.ClearChannelMembersCache(c, channelID)
resultVar0 := a.app.ClearChannelMembersCache(c, channelID)
if resultVar0 != nil {
span.LogFields(spanlog.Error(resultVar0))
ext.Error.Set(span, true)
}
return resultVar0
}
func (a *OpenTracingAppLayer) ClearLatestVersionCache() {
@@ -1559,7 +1566,7 @@ func (a *OpenTracingAppLayer) ClearSessionCacheForUserSkipClusterSend(userID str
a.app.ClearSessionCacheForUserSkipClusterSend(userID)
}
func (a *OpenTracingAppLayer) ClearTeamMembersCache(teamID string) {
func (a *OpenTracingAppLayer) ClearTeamMembersCache(teamID string) error {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.ClearTeamMembersCache")
@@ -1571,7 +1578,14 @@ func (a *OpenTracingAppLayer) ClearTeamMembersCache(teamID string) {
}()
defer span.Finish()
a.app.ClearTeamMembersCache(teamID)
resultVar0 := a.app.ClearTeamMembersCache(teamID)
if resultVar0 != nil {
span.LogFields(spanlog.Error(resultVar0))
ext.Error.Set(span, true)
}
return resultVar0
}
func (a *OpenTracingAppLayer) ClientConfig() map[string]string {
@@ -1857,7 +1871,7 @@ func (a *OpenTracingAppLayer) CopyFileInfos(userID string, fileIDs []string) ([]
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) CreateBot(c *request.Context, bot *model.Bot) (*model.Bot, *model.AppError) {
func (a *OpenTracingAppLayer) CreateBot(c request.CTX, bot *model.Bot) (*model.Bot, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CreateBot")
@@ -1967,7 +1981,7 @@ func (a *OpenTracingAppLayer) CreateCommand(cmd *model.Command) (*model.Command,
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) CreateCommandPost(c *request.Context, post *model.Post, teamID string, response *model.CommandResponse, skipSlackParsing bool) (*model.Post, *model.AppError) {
func (a *OpenTracingAppLayer) CreateCommandPost(c request.CTX, post *model.Post, teamID string, response *model.CommandResponse, skipSlackParsing bool) (*model.Post, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CreateCommandPost")
@@ -2323,7 +2337,7 @@ func (a *OpenTracingAppLayer) CreatePost(c request.CTX, post *model.Post, channe
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) CreatePostAsUser(c *request.Context, post *model.Post, currentSessionId string, setOnline bool) (*model.Post, *model.AppError) {
func (a *OpenTracingAppLayer) CreatePostAsUser(c request.CTX, post *model.Post, currentSessionId string, setOnline bool) (*model.Post, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CreatePostAsUser")
@@ -3838,7 +3852,7 @@ func (a *OpenTracingAppLayer) DoUploadFile(c *request.Context, now time.Time, ra
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) DoUploadFileExpectModification(c *request.Context, now time.Time, rawTeamId string, rawChannelId string, rawUserId string, rawFilename string, data []byte) (*model.FileInfo, []byte, *model.AppError) {
func (a *OpenTracingAppLayer) DoUploadFileExpectModification(c request.CTX, now time.Time, rawTeamId string, rawChannelId string, rawUserId string, rawFilename string, data []byte) (*model.FileInfo, []byte, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.DoUploadFileExpectModification")
@@ -3948,7 +3962,7 @@ func (a *OpenTracingAppLayer) EnableUserAccessToken(token *model.UserAccessToken
return resultVar0
}
func (a *OpenTracingAppLayer) EnsureBot(c *request.Context, productID string, bot *model.Bot) (string, error) {
func (a *OpenTracingAppLayer) EnsureBot(c request.CTX, productID string, bot *model.Bot) (string, error) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.EnsureBot")
@@ -3987,7 +4001,7 @@ func (a *OpenTracingAppLayer) EnvironmentConfig(filter func(reflect.StructField)
return resultVar0
}
func (a *OpenTracingAppLayer) ExecuteCommand(c *request.Context, args *model.CommandArgs) (*model.CommandResponse, *model.AppError) {
func (a *OpenTracingAppLayer) ExecuteCommand(c request.CTX, args *model.CommandArgs) (*model.CommandResponse, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.ExecuteCommand")
@@ -10997,7 +11011,7 @@ func (a *OpenTracingAppLayer) Handle404(w http.ResponseWriter, r *http.Request)
a.app.Handle404(w, r)
}
func (a *OpenTracingAppLayer) HandleCommandResponse(c *request.Context, command *model.Command, args *model.CommandArgs, response *model.CommandResponse, builtIn bool) (*model.CommandResponse, *model.AppError) {
func (a *OpenTracingAppLayer) HandleCommandResponse(c request.CTX, command *model.Command, args *model.CommandArgs, response *model.CommandResponse, builtIn bool) (*model.CommandResponse, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.HandleCommandResponse")
@@ -11019,7 +11033,7 @@ func (a *OpenTracingAppLayer) HandleCommandResponse(c *request.Context, command
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) HandleCommandResponsePost(c *request.Context, command *model.Command, args *model.CommandArgs, response *model.CommandResponse, builtIn bool) (*model.Post, *model.AppError) {
func (a *OpenTracingAppLayer) HandleCommandResponsePost(c request.CTX, command *model.Command, args *model.CommandArgs, response *model.CommandResponse, builtIn bool) (*model.Post, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.HandleCommandResponsePost")
@@ -11753,7 +11767,7 @@ func (a *OpenTracingAppLayer) LeaveChannel(c request.CTX, channelID string, user
return resultVar0
}
func (a *OpenTracingAppLayer) LeaveTeam(c *request.Context, team *model.Team, user *model.User, requestorId string) *model.AppError {
func (a *OpenTracingAppLayer) LeaveTeam(c request.CTX, team *model.Team, user *model.User, requestorId string) *model.AppError {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.LeaveTeam")
@@ -12173,7 +12187,7 @@ func (a *OpenTracingAppLayer) MentionsToPublicChannels(c request.CTX, message st
return resultVar0
}
func (a *OpenTracingAppLayer) MentionsToTeamMembers(message string, teamID string) model.UserMentionMap {
func (a *OpenTracingAppLayer) MentionsToTeamMembers(c request.CTX, message string, teamID string) model.UserMentionMap {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.MentionsToTeamMembers")
@@ -12185,7 +12199,7 @@ func (a *OpenTracingAppLayer) MentionsToTeamMembers(message string, teamID strin
}()
defer span.Finish()
resultVar0 := a.app.MentionsToTeamMembers(message, teamID)
resultVar0 := a.app.MentionsToTeamMembers(c, message, teamID)
return resultVar0
}
@@ -13708,7 +13722,7 @@ func (a *OpenTracingAppLayer) RemoveUserFromChannel(c request.CTX, userIDToRemov
return resultVar0
}
func (a *OpenTracingAppLayer) RemoveUserFromTeam(c *request.Context, teamID string, userID string, requestorId string) *model.AppError {
func (a *OpenTracingAppLayer) RemoveUserFromTeam(c request.CTX, teamID string, userID string, requestorId string) *model.AppError {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.RemoveUserFromTeam")
@@ -16175,7 +16189,7 @@ func (a *OpenTracingAppLayer) SyncPlugins() *model.AppError {
return resultVar0
}
func (a *OpenTracingAppLayer) SyncRolesAndMembership(c *request.Context, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) {
func (a *OpenTracingAppLayer) SyncRolesAndMembership(c request.CTX, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SyncRolesAndMembership")
@@ -16496,7 +16510,7 @@ func (a *OpenTracingAppLayer) UnregisterPluginCommand(pluginID string, teamID st
a.app.UnregisterPluginCommand(pluginID, teamID, trigger)
}
func (a *OpenTracingAppLayer) UpdateActive(c *request.Context, user *model.User, active bool) (*model.User, *model.AppError) {
func (a *OpenTracingAppLayer) UpdateActive(c request.CTX, user *model.User, active bool) (*model.User, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateActive")
@@ -16518,7 +16532,7 @@ func (a *OpenTracingAppLayer) UpdateActive(c *request.Context, user *model.User,
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) UpdateBotActive(c *request.Context, botUserId string, active bool) (*model.Bot, *model.AppError) {
func (a *OpenTracingAppLayer) UpdateBotActive(c request.CTX, botUserId string, active bool) (*model.Bot, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateBotActive")
@@ -17585,7 +17599,7 @@ func (a *OpenTracingAppLayer) UpdateUser(c request.CTX, user *model.User, sendNo
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) UpdateUserActive(c *request.Context, userID string, active bool) *model.AppError {
func (a *OpenTracingAppLayer) UpdateUserActive(c request.CTX, userID string, active bool) *model.AppError {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UpdateUserActive")
@@ -17791,7 +17805,7 @@ func (a *OpenTracingAppLayer) UploadEmojiImage(id string, imageData *multipart.F
return resultVar0
}
func (a *OpenTracingAppLayer) UploadFile(c *request.Context, data []byte, channelID string, filename string) (*model.FileInfo, *model.AppError) {
func (a *OpenTracingAppLayer) UploadFile(c request.CTX, data []byte, channelID string, filename string) (*model.FileInfo, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.UploadFile")

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

@@ -3,14 +3,34 @@
package platform
import (
"errors"
"github.com/mattermost/mattermost-server/v6/config"
"github.com/mattermost/mattermost-server/v6/einterfaces"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
)
// ServiceConfig is used to initialize the PlatformService.
// The mandatory fields will be checked during the initialization of the service.
type ServiceConfig struct {
// Mandatory fields
ConfigStore *config.Store
Logger *mlog.Logger
StartMetrics bool // TODO: find an elegant way to start/stop metrics server by default
// Optional fields
Metrics einterfaces.MetricsInterface
Cluster einterfaces.ClusterInterface
}
func (c *ServiceConfig) validate() error {
// Mandatory fields need to be checked here
if c.ConfigStore == nil {
return errors.New("ConfigStore is required")
}
if c.Logger == nil {
return errors.New("Logger is required")
}
return nil
}

184
app/platform/metrics.go Обычный файл
Просмотреть файл

@@ -0,0 +1,184 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package platform
import (
"context"
"fmt"
"net"
"net/http"
"net/http/pprof"
"runtime"
"sync"
"text/template"
"time"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/mattermost/mattermost-server/v6/einterfaces"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/pkg/errors"
)
const TimeToWaitForConnectionsToCloseOnServerShutdown = time.Second
type platformMetrics struct {
server *http.Server
router *mux.Router
lock sync.Mutex
logger *mlog.Logger
metricsImpl einterfaces.MetricsInterface
cfgFn func() *model.Config
}
// resetMetrics resets the metrics server. Clears the metrics if the metrics are disabled by the config.
func (ps *PlatformService) resetMetrics(metricsImpl einterfaces.MetricsInterface, cfgFn func() *model.Config) error {
if !*cfgFn().MetricsSettings.Enable {
if ps.metrics != nil {
return ps.metrics.stopMetricsServer()
}
return nil
}
if ps.metrics != nil {
if err := ps.metrics.stopMetricsServer(); err != nil {
return err
}
}
ps.metrics = &platformMetrics{
cfgFn: cfgFn,
metricsImpl: metricsImpl,
logger: ps.logger,
}
if err := ps.metrics.initMetricsRouter(); err != nil {
return err
}
if metricsImpl != nil {
metricsImpl.Register()
}
return ps.metrics.startMetricsServer()
}
func (pm *platformMetrics) stopMetricsServer() error {
pm.lock.Lock()
defer pm.lock.Unlock()
if pm.server != nil {
ctx, cancel := context.WithTimeout(context.Background(), TimeToWaitForConnectionsToCloseOnServerShutdown)
defer cancel()
if err := pm.server.Shutdown(ctx); err != nil {
return fmt.Errorf("could not shutdown metrics server: %v", err)
}
pm.logger.Info("Metrics and profiling server is stopped")
}
return nil
}
func (pm *platformMetrics) startMetricsServer() error {
var notify chan struct{}
pm.lock.Lock()
defer func() {
if notify != nil {
<-notify
}
pm.lock.Unlock()
}()
l, err := net.Listen("tcp", *pm.cfgFn().MetricsSettings.ListenAddress)
if err != nil {
return err
}
notify = make(chan struct{})
pm.server = &http.Server{
Handler: handlers.RecoveryHandler(handlers.PrintRecoveryStack(true))(pm.router),
ReadTimeout: time.Duration(*pm.cfgFn().ServiceSettings.ReadTimeout) * time.Second,
WriteTimeout: time.Duration(*pm.cfgFn().ServiceSettings.WriteTimeout) * time.Second,
}
go func() {
close(notify)
if err := pm.server.Serve(l); err != nil && err != http.ErrServerClosed {
pm.logger.Critical(err.Error())
}
}()
pm.logger.Info("Metrics and profiling server is started", mlog.String("address", l.Addr().String()))
return nil
}
func (pm *platformMetrics) initMetricsRouter() error {
pm.router = mux.NewRouter()
runtime.SetBlockProfileRate(*pm.cfgFn().MetricsSettings.BlockProfileRate)
metricsPage := `
<html>
<body>{{if .}}
<div><a href="/metrics">Metrics</a></div>{{end}}
<div><a href="/debug/pprof/">Profiling Root</a></div>
<div><a href="/debug/pprof/cmdline">Profiling Command Line</a></div>
<div><a href="/debug/pprof/symbol">Profiling Symbols</a></div>
<div><a href="/debug/pprof/goroutine">Profiling Goroutines</a></div>
<div><a href="/debug/pprof/heap">Profiling Heap</a></div>
<div><a href="/debug/pprof/threadcreate">Profiling Threads</a></div>
<div><a href="/debug/pprof/block">Profiling Blocking</a></div>
<div><a href="/debug/pprof/trace">Profiling Execution Trace</a></div>
<div><a href="/debug/pprof/profile">Profiling CPU</a></div>
</body>
</html>
`
metricsPageTmpl, err := template.New("page").Parse(metricsPage)
if err != nil {
return errors.Wrap(err, "failed to create template")
}
rootHandler := func(w http.ResponseWriter, r *http.Request) {
metricsPageTmpl.Execute(w, pm.metricsImpl != nil)
}
pm.router.HandleFunc("/", rootHandler)
pm.router.StrictSlash(true)
pm.router.Handle("/debug", http.RedirectHandler("/", http.StatusMovedPermanently))
pm.router.HandleFunc("/debug/pprof/", pprof.Index)
pm.router.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
pm.router.HandleFunc("/debug/pprof/profile", pprof.Profile)
pm.router.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
pm.router.HandleFunc("/debug/pprof/trace", pprof.Trace)
// Manually add support for paths linked to by index page at /debug/pprof/
pm.router.Handle("/debug/pprof/goroutine", pprof.Handler("goroutine"))
pm.router.Handle("/debug/pprof/heap", pprof.Handler("heap"))
pm.router.Handle("/debug/pprof/threadcreate", pprof.Handler("threadcreate"))
pm.router.Handle("/debug/pprof/block", pprof.Handler("block"))
return nil
}
func (ps *PlatformService) HandleMetrics(route string, h http.Handler) {
if ps.metrics != nil {
ps.metrics.router.Handle(route, h)
}
}
func (ps *PlatformService) RestartMetrics() error {
return ps.resetMetrics(ps.serviceConfig.Metrics, ps.serviceConfig.ConfigStore.Get)
}
func (ps *PlatformService) Metrics() einterfaces.MetricsInterface {
if ps.metrics == nil {
return nil
}
return ps.metrics.metricsImpl
}

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

@@ -3,17 +3,49 @@
package platform
import (
"github.com/mattermost/mattermost-server/v6/config"
"github.com/mattermost/mattermost-server/v6/einterfaces"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
)
// PlatformService is the service for the platform related tasks. It is
// responsible for non-entity related functionalities that are required
// by a product such as database access, configuration access, licensing etc.
type PlatformService struct {
serviceConfig ServiceConfig
configStore *config.Store
logger *mlog.Logger
metrics *platformMetrics
cluster einterfaces.ClusterInterface
}
// New creates a new PlatformService.
func New(c ServiceConfig) (*PlatformService, error) {
if err := c.validate(); err != nil {
func New(sc ServiceConfig) (*PlatformService, error) {
if err := sc.validate(); err != nil {
return nil, err
}
return &PlatformService{}, nil
ps := &PlatformService{
serviceConfig: sc,
configStore: sc.ConfigStore,
logger: sc.Logger,
cluster: sc.Cluster,
}
if err := ps.resetMetrics(sc.Metrics, ps.configStore.Get); err != nil {
return nil, err
}
return ps, nil
}
func (ps *PlatformService) ShutdownMetrics() error {
if ps.metrics != nil {
return ps.metrics.stopMetricsServer()
}
return nil
}

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

@@ -226,7 +226,7 @@ func (ch *Channels) initPlugins(c *request.Context, pluginDir, webappPluginDir s
return New(ServerConnector(ch)).NewPluginAPI(c, manifest)
}
env, err := plugin.NewEnvironment(newAPIFunc, NewDriverImpl(ch.srv), pluginDir, webappPluginDir, ch.srv.Log, ch.srv.Metrics)
env, err := plugin.NewEnvironment(newAPIFunc, NewDriverImpl(ch.srv), pluginDir, webappPluginDir, ch.srv.Log, ch.srv.GetMetrics())
if err != nil {
mlog.Error("Failed to start up plugins", mlog.Err(err))
return

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

@@ -1821,7 +1821,7 @@ func (*MockSlashCommandProvider) GetCommand(a *App, T i18n.TranslateFunc) *model
}
}
func (mscp *MockSlashCommandProvider) DoCommand(a *App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (mscp *MockSlashCommandProvider) DoCommand(a *App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
mscp.Args = args
mscp.Message = message
return &model.CommandResponse{

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

@@ -117,7 +117,7 @@ func (a *App) PluginCommandsForTeam(teamID string) []*model.Command {
// tryExecutePluginCommand attempts to run a command provided by a plugin based on the given arguments. If no such
// command can be found, returns nil for all arguments.
func (a *App) tryExecutePluginCommand(c *request.Context, args *model.CommandArgs) (*model.Command, *model.CommandResponse, *model.AppError) {
func (a *App) tryExecutePluginCommand(c request.CTX, args *model.CommandArgs) (*model.Command, *model.CommandResponse, *model.AppError) {
parts := strings.Split(args.Command, " ")
trigger := parts[0][1:]
trigger = strings.ToLower(trigger)
@@ -150,7 +150,7 @@ func (a *App) tryExecutePluginCommand(c *request.Context, args *model.CommandArg
return matched.Command, nil, model.NewAppError("ExecutePluginCommand", "model.plugin_command.error.app_error", nil, "err="+err.Error(), http.StatusInternalServerError)
}
for username, userID := range a.MentionsToTeamMembers(args.Command, args.TeamId) {
for username, userID := range a.MentionsToTeamMembers(c, args.Command, args.TeamId) {
args.AddUserMention(username, userID)
}

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

@@ -46,7 +46,7 @@ func (s *postServiceWrapper) CreatePost(ctx *request.Context, post *model.Post)
return s.app.CreatePostMissingChannel(ctx, post, true)
}
func (a *App) CreatePostAsUser(c *request.Context, post *model.Post, currentSessionId string, setOnline bool) (*model.Post, *model.AppError) {
func (a *App) CreatePostAsUser(c request.CTX, post *model.Post, currentSessionId string, setOnline bool) (*model.Post, *model.AppError) {
// Check that channel has not been deleted
channel, errCh := a.Srv().Store.Channel().Get(post.ChannelId, true)
if errCh != nil {
@@ -83,7 +83,7 @@ func (a *App) CreatePostAsUser(c *request.Context, post *model.Post, currentSess
isCRTReply := post.RootId != "" && a.IsCRTEnabledForUser(c, post.UserId)
if !fromWebhook && !fromBot && !isCRTReply {
if _, err := a.MarkChannelsAsViewed(c, []string{post.ChannelId}, post.UserId, currentSessionId, true); err != nil {
mlog.Warn(
c.Logger().Warn(
"Encountered error updating last viewed",
mlog.String("channel_id", post.ChannelId),
mlog.String("user_id", post.UserId),
@@ -1251,7 +1251,7 @@ func (a *App) DeletePost(c request.CTX, postID, deleteByID string) (*model.Post,
postJSON, jsonErr := json.Marshal(post)
if jsonErr != nil {
mlog.Warn("Failed to encode post to JSON")
return nil, model.NewAppError("DeletePost", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
userMessage := model.NewWebSocketEvent(model.WebsocketEventPostDeleted, "", post.ChannelId, "", nil)

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

@@ -9,7 +9,6 @@ import (
"net/http"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
)
func (a *App) GetPreferencesForUser(userID string) (model.Preferences, *model.AppError) {
@@ -69,7 +68,7 @@ func (a *App) UpdatePreferences(userID string, preferences model.Preferences) *m
message = model.NewWebSocketEvent(model.WebsocketEventPreferencesChanged, "", "", userID, nil)
prefsJSON, jsonErr := json.Marshal(preferences)
if jsonErr != nil {
mlog.Warn("Failed to encode to JSON", mlog.Err(jsonErr))
return model.NewAppError("UpdatePreferences", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
message.Add("preferences", string(prefsJSON))
a.Publish(message)
@@ -103,7 +102,7 @@ func (a *App) DeletePreferences(userID string, preferences model.Preferences) *m
message = model.NewWebSocketEvent(model.WebsocketEventPreferencesDeleted, "", "", userID, nil)
prefsJSON, jsonErr := json.Marshal(preferences)
if jsonErr != nil {
mlog.Warn("Failed to encode to JSON", mlog.Err(jsonErr))
return model.NewAppError("DeletePreferences", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
message.Add("preferences", string(prefsJSON))
a.Publish(message)

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

@@ -12,7 +12,6 @@ import (
"strings"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
"github.com/mattermost/mattermost-server/v6/store"
"github.com/mattermost/mattermost-server/v6/utils"
)
@@ -138,7 +137,9 @@ func (a *App) PatchRole(role *model.Role, patch *model.RolePatch) (*model.Role,
return nil, err
}
a.sendUpdatedRoleEvent(role)
if appErr := a.sendUpdatedRoleEvent(role); appErr != nil {
return nil, appErr
}
return role, err
}
@@ -225,7 +226,10 @@ func (a *App) UpdateRole(role *model.Role) (*model.Role, *model.AppError) {
for _, ir := range impactedRoles {
if ir.Name != role.Name {
a.sendUpdatedRoleEvent(ir)
appErr = a.sendUpdatedRoleEvent(ir)
if appErr != nil {
return nil, appErr
}
}
}
@@ -254,17 +258,15 @@ func (a *App) CheckRolesExist(roleNames []string) *model.AppError {
return nil
}
func (a *App) sendUpdatedRoleEvent(role *model.Role) {
func (a *App) sendUpdatedRoleEvent(role *model.Role) *model.AppError {
message := model.NewWebSocketEvent(model.WebsocketEventRoleUpdated, "", "", "", nil)
roleJSON, jsonErr := json.Marshal(role)
if jsonErr != nil {
mlog.Warn("Failed to encode role to JSON", mlog.Err(jsonErr))
return model.NewAppError("sendUpdatedRoleEvent", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
message.Add("role", string(roleJSON))
a.Srv().Go(func() {
a.Publish(message)
})
a.Publish(message)
return nil
}
func RemoveRoles(rolesToRemove []string, roles string) string {

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

@@ -9,10 +9,8 @@ import (
"crypto/tls"
"fmt"
"hash/maphash"
"html/template"
"net"
"net/http"
"net/http/pprof"
"net/url"
"os"
"os/exec"
@@ -27,7 +25,6 @@ import (
"github.com/getsentry/sentry-go"
sentryhttp "github.com/getsentry/sentry-go/http"
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/pkg/errors"
"github.com/rs/cors"
@@ -35,6 +32,7 @@ import (
"github.com/mattermost/mattermost-server/v6/app/email"
"github.com/mattermost/mattermost-server/v6/app/featureflag"
"github.com/mattermost/mattermost-server/v6/app/platform"
"github.com/mattermost/mattermost-server/v6/app/request"
"github.com/mattermost/mattermost-server/v6/app/teams"
"github.com/mattermost/mattermost-server/v6/app/users"
@@ -131,10 +129,6 @@ type Server struct {
localModeServer *http.Server
metricsServer *http.Server
metricsRouter *mux.Router
metricsLock sync.Mutex
didFinishListen chan struct{}
goroutineCount int32
@@ -177,6 +171,7 @@ type Server struct {
configStore *configWrapper
filestore filestore.FileBackend
platform *platform.PlatformService
telemetryService *telemetry.TelemetryService
userService *users.UserService
teamService *teams.TeamService
@@ -200,7 +195,6 @@ type Server struct {
Cluster einterfaces.ClusterInterface
Cloud einterfaces.CloudInterface
Metrics einterfaces.MetricsInterface
LicenseManager einterfaces.LicenseInterface
CacheProvider cache.Provider
@@ -286,6 +280,22 @@ func NewServer(options ...Option) (*Server, error) {
// Depends on step 3 (s.SearchEngine must be non-nil)
s.initEnterprise()
platformCfg := platform.ServiceConfig{
ConfigStore: s.configStore.Store,
Logger: s.Log,
StartMetrics: s.startMetrics,
Cluster: s.Cluster,
}
if metricsInterface != nil {
platformCfg.Metrics = metricsInterface(s)
}
ps, sErr := platform.New(platformCfg)
if sErr != nil {
return nil, errors.Wrap(sErr, "failed to initialize platform")
}
s.platform = ps
// Step 5: Cache provider.
// At the moment we only have this implementation
// in the future the cache provider will be built based on the loaded config
@@ -298,11 +308,11 @@ func NewServer(options ...Option) (*Server, error) {
// Depends on Step 1 (config), 4 (metrics, cluster) and 5 (cacheProvider).
if s.newStore == nil {
s.newStore = func() (store.Store, error) {
s.sqlStore = sqlstore.New(s.Config().SqlSettings, s.Metrics)
s.sqlStore = sqlstore.New(s.Config().SqlSettings, s.GetMetrics())
lcl, err2 := localcachelayer.NewLocalCacheLayer(
retrylayer.New(s.sqlStore),
s.Metrics,
s.GetMetrics(),
s.Cluster,
s.CacheProvider,
)
@@ -327,7 +337,7 @@ func NewServer(options ...Option) (*Server, error) {
return timerlayer.New(
searchStore,
s.Metrics,
s.GetMetrics(),
), nil
}
}
@@ -343,7 +353,7 @@ func NewServer(options ...Option) (*Server, error) {
SessionStore: s.Store.Session(),
OAuthStore: s.Store.OAuth(),
ConfigFn: s.Config,
Metrics: s.Metrics,
Metrics: s.GetMetrics(),
Cluster: s.Cluster,
LicenseFn: s.License,
})
@@ -620,7 +630,9 @@ func NewServer(options ...Option) (*Server, error) {
}
if s.startMetrics {
s.SetupMetricsServer()
if err := s.platform.RestartMetrics(); err != nil {
return nil, errors.Wrap(err, "failed to start metrics")
}
}
s.AddLicenseListener(func(oldLicense, newLicense *model.License) {
@@ -632,7 +644,9 @@ func NewServer(options ...Option) (*Server, error) {
return
}
s.SetupMetricsServer()
if err := s.platform.RestartMetrics(); err != nil {
s.Log.Error("Failed to reset metrics server", mlog.Err(err))
}
})
s.SearchEngine.UpdateConfig(s.Config())
@@ -701,24 +715,6 @@ func NewServer(options ...Option) (*Server, error) {
return s, nil
}
func (s *Server) SetupMetricsServer() {
if !*s.Config().MetricsSettings.Enable {
return
}
s.StopMetricsServer()
if err := s.InitMetricsRouter(); err != nil {
mlog.Error("Error initiating metrics router.", mlog.Err(err))
}
if s.Metrics != nil {
s.Metrics.Register()
}
s.startMetricsServer()
}
func maxInt(a, b int) int {
if a > b {
return a
@@ -951,11 +947,11 @@ func (s *Server) startInterClusterServices(license *model.License) error {
}
func (s *Server) enableLoggingMetrics() {
if s.Metrics == nil {
if s.GetMetrics() == nil {
return
}
s.Log.SetMetricsCollector(s.Metrics.GetLoggerMetricsCollector(), mlog.DefaultMetricsUpdateFreqMillis)
s.Log.SetMetricsCollector(s.GetMetrics().GetLoggerMetricsCollector(), mlog.DefaultMetricsUpdateFreqMillis)
// logging config needs to be reloaded when metrics collector is added or changed.
if err := s.initLogging(); err != nil {
@@ -991,7 +987,7 @@ func (s *Server) StopHTTPServer() {
}
func (s *Server) Shutdown() {
mlog.Info("Stopping Server...")
s.Log.Info("Stopping Server...")
defer sentry.Flush(2 * time.Second)
@@ -1002,24 +998,24 @@ func (s *Server) Shutdown() {
if s.tracer != nil {
if err := s.tracer.Close(); err != nil {
mlog.Warn("Unable to cleanly shutdown opentracing client", mlog.Err(err))
s.Log.Warn("Unable to cleanly shutdown opentracing client", mlog.Err(err))
}
}
err := s.telemetryService.Shutdown()
if err != nil {
mlog.Warn("Unable to cleanly shutdown telemetry client", mlog.Err(err))
s.Log.Warn("Unable to cleanly shutdown telemetry client", mlog.Err(err))
}
s.serviceMux.RLock()
if s.sharedChannelService != nil {
if err = s.sharedChannelService.Shutdown(); err != nil {
mlog.Error("Error shutting down shared channel services", mlog.Err(err))
s.Log.Error("Error shutting down shared channel services", mlog.Err(err))
}
}
if s.remoteClusterService != nil {
if err = s.remoteClusterService.Shutdown(); err != nil {
mlog.Error("Error shutting down intercluster services", mlog.Err(err))
s.Log.Error("Error shutting down intercluster services", mlog.Err(err))
}
}
s.serviceMux.RUnlock()
@@ -1046,7 +1042,9 @@ func (s *Server) Shutdown() {
s.Cluster.StopInterNodeCommunication()
}
s.StopMetricsServer()
if err = s.platform.ShutdownMetrics(); err != nil {
s.Log.Warn("Failed to stop metrics server", mlog.Err(err))
}
// This must be done after the cluster is stopped.
if s.Jobs != nil {
@@ -1054,10 +1052,10 @@ func (s *Server) Shutdown() {
// before stopping them as both calls essentially become no-ops
// if nothing is running.
if err = s.Jobs.StopWorkers(); err != nil && !errors.Is(err, jobs.ErrWorkersNotRunning) {
mlog.Warn("Failed to stop job server workers", mlog.Err(err))
s.Log.Warn("Failed to stop job server workers", mlog.Err(err))
}
if err = s.Jobs.StopSchedulers(); err != nil && !errors.Is(err, jobs.ErrSchedulersNotRunning) {
mlog.Warn("Failed to stop job server schedulers", mlog.Err(err))
s.Log.Warn("Failed to stop job server schedulers", mlog.Err(err))
}
}
@@ -1066,7 +1064,7 @@ func (s *Server) Shutdown() {
// on parent services.
for name, product := range s.products {
if err2 := product.Stop(); err2 != nil {
mlog.Warn("Unable to cleanly stop product", mlog.String("name", name), mlog.Err(err2))
s.Log.Warn("Unable to cleanly stop product", mlog.String("name", name), mlog.Err(err2))
}
}
@@ -1076,11 +1074,11 @@ func (s *Server) Shutdown() {
if s.CacheProvider != nil {
if err = s.CacheProvider.Close(); err != nil {
mlog.Warn("Unable to cleanly shutdown cache", mlog.Err(err))
s.Log.Warn("Unable to cleanly shutdown cache", mlog.Err(err))
}
}
mlog.Info("Server stopped")
s.Log.Info("Server stopped")
// shutdown main and notification loggers which will flush any remaining log records.
timeoutCtx, timeoutCancel := context.WithTimeout(context.Background(), time.Second*15)
@@ -1630,104 +1628,8 @@ func doConfigCleanup(s *Server) {
}
}
func (s *Server) StopMetricsServer() {
s.metricsLock.Lock()
defer s.metricsLock.Unlock()
if s.metricsServer != nil {
ctx, cancel := context.WithTimeout(context.Background(), TimeToWaitForConnectionsToCloseOnServerShutdown)
defer cancel()
s.metricsServer.Shutdown(ctx)
s.Log.Info("Metrics and profiling server is stopping")
}
}
func (s *Server) HandleMetrics(route string, h http.Handler) {
if s.metricsRouter != nil {
s.metricsRouter.Handle(route, h)
}
}
func (s *Server) InitMetricsRouter() error {
s.metricsRouter = mux.NewRouter()
runtime.SetBlockProfileRate(*s.Config().MetricsSettings.BlockProfileRate)
metricsPage := `
<html>
<body>{{if .}}
<div><a href="/metrics">Metrics</a></div>{{end}}
<div><a href="/debug/pprof/">Profiling Root</a></div>
<div><a href="/debug/pprof/cmdline">Profiling Command Line</a></div>
<div><a href="/debug/pprof/symbol">Profiling Symbols</a></div>
<div><a href="/debug/pprof/goroutine">Profiling Goroutines</a></div>
<div><a href="/debug/pprof/heap">Profiling Heap</a></div>
<div><a href="/debug/pprof/threadcreate">Profiling Threads</a></div>
<div><a href="/debug/pprof/block">Profiling Blocking</a></div>
<div><a href="/debug/pprof/trace">Profiling Execution Trace</a></div>
<div><a href="/debug/pprof/profile">Profiling CPU</a></div>
</body>
</html>
`
metricsPageTmpl, err := template.New("page").Parse(metricsPage)
if err != nil {
return errors.Wrap(err, "failed to create template")
}
rootHandler := func(w http.ResponseWriter, r *http.Request) {
metricsPageTmpl.Execute(w, s.Metrics != nil)
}
s.metricsRouter.HandleFunc("/", rootHandler)
s.metricsRouter.StrictSlash(true)
s.metricsRouter.Handle("/debug", http.RedirectHandler("/", http.StatusMovedPermanently))
s.metricsRouter.HandleFunc("/debug/pprof/", pprof.Index)
s.metricsRouter.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
s.metricsRouter.HandleFunc("/debug/pprof/profile", pprof.Profile)
s.metricsRouter.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
s.metricsRouter.HandleFunc("/debug/pprof/trace", pprof.Trace)
// Manually add support for paths linked to by index page at /debug/pprof/
s.metricsRouter.Handle("/debug/pprof/goroutine", pprof.Handler("goroutine"))
s.metricsRouter.Handle("/debug/pprof/heap", pprof.Handler("heap"))
s.metricsRouter.Handle("/debug/pprof/threadcreate", pprof.Handler("threadcreate"))
s.metricsRouter.Handle("/debug/pprof/block", pprof.Handler("block"))
return nil
}
func (s *Server) startMetricsServer() {
var notify chan struct{}
s.metricsLock.Lock()
defer func() {
if notify != nil {
<-notify
}
s.metricsLock.Unlock()
}()
l, err := net.Listen("tcp", *s.Config().MetricsSettings.ListenAddress)
if err != nil {
mlog.Error(err.Error())
return
}
notify = make(chan struct{})
s.metricsServer = &http.Server{
Handler: handlers.RecoveryHandler(handlers.PrintRecoveryStack(true))(s.metricsRouter),
ReadTimeout: time.Duration(*s.Config().ServiceSettings.ReadTimeout) * time.Second,
WriteTimeout: time.Duration(*s.Config().ServiceSettings.WriteTimeout) * time.Second,
}
go func() {
close(notify)
if err := s.metricsServer.Serve(l); err != nil && err != http.ErrServerClosed {
mlog.Critical(err.Error())
}
}()
s.Log.Info("Metrics and profiling server is started", mlog.String("address", l.Addr().String()))
s.platform.HandleMetrics(route, h)
}
func (s *Server) sendLicenseUpForRenewalEmail(users map[string]*model.User, license *model.License) *model.AppError {
@@ -1956,7 +1858,7 @@ func (ch *Channels) ClientConfigHash() string {
}
func (s *Server) initJobs() {
s.Jobs = jobs.NewJobServer(s, s.Store, s.Metrics)
s.Jobs = jobs.NewJobServer(s, s.Store, s.GetMetrics())
if jobsDataRetentionJobInterface != nil {
builder := jobsDataRetentionJobInterface(s)
@@ -2039,7 +1941,7 @@ func (s *Server) initJobs() {
s.Jobs.RegisterJobType(
model.JobTypeActiveUsers,
active_users.MakeWorker(s.Jobs, s.Store, func() einterfaces.MetricsInterface { return s.Metrics }),
active_users.MakeWorker(s.Jobs, s.Store, func() einterfaces.MetricsInterface { return s.GetMetrics() }),
active_users.MakeScheduler(s.Jobs),
)
@@ -2106,7 +2008,10 @@ func (s *Server) GetSharedChannelSyncService() SharedChannelServiceIFace {
// GetMetrics returns the server's Metrics interface. Exposing via a method
// allows interfaces to be created with subsets of server APIs.
func (s *Server) GetMetrics() einterfaces.MetricsInterface {
return s.Metrics
if s.platform == nil {
return nil
}
return s.platform.Metrics()
}
// SetRemoteClusterService sets the `RemoteClusterService` to be used by the server.

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

@@ -36,7 +36,7 @@ func NewAutoChannelCreator(a *app.App, team *model.Team, userID string) *AutoCha
}
}
func (cfg *AutoChannelCreator) createRandomChannel(c *request.Context) (*model.Channel, error) {
func (cfg *AutoChannelCreator) createRandomChannel(c request.CTX) (*model.Channel, error) {
var displayName string
if cfg.Fuzzy {
displayName = utils.FuzzName()
@@ -60,7 +60,7 @@ func (cfg *AutoChannelCreator) createRandomChannel(c *request.Context) (*model.C
return channel, nil
}
func (cfg *AutoChannelCreator) CreateTestChannels(c *request.Context, num utils.Range) ([]*model.Channel, error) {
func (cfg *AutoChannelCreator) CreateTestChannels(c request.CTX, num utils.Range) ([]*model.Channel, error) {
numChannels := utils.RandIntFromRange(num)
channels := make([]*model.Channel, numChannels)
@@ -75,7 +75,7 @@ func (cfg *AutoChannelCreator) CreateTestChannels(c *request.Context, num utils.
return channels, nil
}
func (cfg *AutoChannelCreator) CreateTestDMs(c *request.Context, num utils.Range) ([]*model.Channel, error) {
func (cfg *AutoChannelCreator) CreateTestDMs(c request.CTX, num utils.Range) ([]*model.Channel, error) {
numDMs := utils.RandIntFromRange(num)
dms := make([]*model.Channel, numDMs)

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

@@ -18,7 +18,7 @@ type TestEnvironment struct {
Environments []TeamEnvironment
}
func CreateTestEnvironmentWithTeams(a *app.App, c *request.Context, client *model.Client4, rangeTeams utils.Range, rangeChannels utils.Range, rangeUsers utils.Range, rangePosts utils.Range, fuzzy bool) (TestEnvironment, error) {
func CreateTestEnvironmentWithTeams(a *app.App, c request.CTX, client *model.Client4, rangeTeams utils.Range, rangeChannels utils.Range, rangeUsers utils.Range, rangePosts utils.Range, fuzzy bool) (TestEnvironment, error) {
rand.Seed(time.Now().UTC().UnixNano())
teamCreator := NewAutoTeamCreator(client)
@@ -48,7 +48,7 @@ func CreateTestEnvironmentWithTeams(a *app.App, c *request.Context, client *mode
return environment, nil
}
func CreateTestEnvironmentInTeam(a *app.App, c *request.Context, client *model.Client4, team *model.Team, rangeChannels utils.Range, rangeUsers utils.Range, rangePosts utils.Range, fuzzy bool) (TeamEnvironment, error) {
func CreateTestEnvironmentInTeam(a *app.App, c request.CTX, client *model.Client4, team *model.Team, rangeChannels utils.Range, rangeUsers utils.Range, rangePosts utils.Range, fuzzy bool) (TeamEnvironment, error) {
rand.Seed(time.Now().UTC().UnixNano())
// We need to create at least one user

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

@@ -45,7 +45,7 @@ func NewAutoPostCreator(a *app.App, channelid, userid string) *AutoPostCreator {
}
}
func (cfg *AutoPostCreator) UploadTestFile(c *request.Context) ([]string, error) {
func (cfg *AutoPostCreator) UploadTestFile(c request.CTX) ([]string, error) {
filename := cfg.ImageFilenames[utils.RandIntFromRange(utils.Range{Begin: 0, End: len(cfg.ImageFilenames) - 1})]
path, _ := fileutils.FindDir("tests")
@@ -69,11 +69,11 @@ func (cfg *AutoPostCreator) UploadTestFile(c *request.Context) ([]string, error)
return []string{fileResp.Id}, nil
}
func (cfg *AutoPostCreator) CreateRandomPost(c *request.Context) (*model.Post, error) {
func (cfg *AutoPostCreator) CreateRandomPost(c request.CTX) (*model.Post, error) {
return cfg.CreateRandomPostNested(c, "")
}
func (cfg *AutoPostCreator) CreateRandomPostNested(c *request.Context, rootId string) (*model.Post, error) {
func (cfg *AutoPostCreator) CreateRandomPostNested(c request.CTX, rootId string) (*model.Post, error) {
var fileIDs []string
if cfg.HasImage {
var err error

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

@@ -78,7 +78,7 @@ func CreateBasicUser(a *app.App, client *model.Client4) error {
return nil
}
func (cfg *AutoUserCreator) createRandomUser(c *request.Context) (*model.User, error) {
func (cfg *AutoUserCreator) createRandomUser(c request.CTX) (*model.User, error) {
var userEmail string
var userName string
if cfg.Fuzzy {
@@ -113,7 +113,7 @@ func (cfg *AutoUserCreator) createRandomUser(c *request.Context) (*model.User, e
return ruser, nil
}
func (cfg *AutoUserCreator) CreateTestUsers(c *request.Context, num utils.Range) ([]*model.User, error) {
func (cfg *AutoUserCreator) CreateTestUsers(c request.CTX, num utils.Range) ([]*model.User, error) {
numUsers := utils.RandIntFromRange(num)
users := make([]*model.User, numUsers)

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

@@ -34,7 +34,7 @@ func (*AwayProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Command
}
}
func (*AwayProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*AwayProvider) DoCommand(a *app.App, _ request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
a.SetStatusAwayIfNeeded(args.UserId, true)
return &model.CommandResponse{ResponseType: model.CommandResponseTypeEphemeral, Text: args.T("api.command_away.success")}

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

@@ -35,7 +35,7 @@ func (*HeaderProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Comma
}
}
func (*HeaderProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*HeaderProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
channel, err := a.GetChannel(c, args.ChannelId)
if err != nil {
return &model.CommandResponse{

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

@@ -35,7 +35,7 @@ func (*PurposeProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Comm
}
}
func (*PurposeProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*PurposeProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
channel, err := a.GetChannel(c, args.ChannelId)
if err != nil {
return &model.CommandResponse{

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

@@ -38,7 +38,7 @@ func (*RenameProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Comma
}
}
func (*RenameProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*RenameProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
channel, err := a.GetChannel(c, args.ChannelId)
if err != nil {
return &model.CommandResponse{

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

@@ -37,7 +37,7 @@ func (*CodeProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Command
}
}
func (*CodeProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*CodeProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
if message == "" {
return &model.CommandResponse{Text: args.T("api.command_code.message.app_error"), ResponseType: model.CommandResponseTypeEphemeral}
}

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

@@ -41,7 +41,7 @@ func (*CustomStatusProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model
}
}
func (*CustomStatusProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*CustomStatusProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
if !*a.Config().TeamSettings.EnableCustomUserStatuses {
return nil
}

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

@@ -34,7 +34,7 @@ func (*DndProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Command
}
}
func (*DndProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*DndProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
a.SetStatusDoNotDisturb(args.UserId)
return &model.CommandResponse{ResponseType: model.CommandResponseTypeEphemeral, Text: args.T("api.command_dnd.success")}

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

@@ -42,7 +42,7 @@ func (*EchoProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Command
}
}
func (*EchoProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*EchoProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
if message == "" {
return &model.CommandResponse{Text: args.T("api.command_echo.message.app_error"), ResponseType: model.CommandResponseTypeEphemeral}
}

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

@@ -11,7 +11,6 @@ import (
"github.com/mattermost/mattermost-server/v6/app/request"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/shared/i18n"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
)
type ExpandProvider struct {
@@ -56,11 +55,11 @@ func (*CollapseProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Com
}
}
func (*ExpandProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*ExpandProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
return setCollapsePreference(a, args, false)
}
func (*CollapseProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*CollapseProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
return setCollapsePreference(a, args, true)
}
@@ -73,14 +72,14 @@ func setCollapsePreference(a *app.App, args *model.CommandArgs, isCollapse bool)
}
if err := a.Srv().Store.Preference().Save(model.Preferences{pref}); err != nil {
return &model.CommandResponse{Text: args.T("api.command_expand_collapse.fail.app_error"), ResponseType: model.CommandResponseTypeEphemeral}
return &model.CommandResponse{Text: args.T("api.command_expand_collapse.fail.app_error") + err.Error(), ResponseType: model.CommandResponseTypeEphemeral}
}
socketMessage := model.NewWebSocketEvent(model.WebsocketEventPreferenceChanged, "", "", args.UserId, nil)
prefJSON, jsonErr := json.Marshal(pref)
if jsonErr != nil {
mlog.Warn("Failed to encode to JSON", mlog.Err(jsonErr))
return &model.CommandResponse{Text: args.T("api.marshal_error") + jsonErr.Error(), ResponseType: model.CommandResponseTypeEphemeral}
}
socketMessage.Add("preference", string(prefJSON))
a.Publish(socketMessage)

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

@@ -39,7 +39,7 @@ func (*groupmsgProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Com
}
}
func (*groupmsgProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*groupmsgProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
targetUsers := map[string]*model.User{}
targetUsersSlice := []string{args.UserId}
invalidUsernames := []string{}

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

@@ -34,7 +34,7 @@ func (h *HelpProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Comma
}
}
func (h *HelpProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (h *HelpProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
helpLink := *a.Config().SupportSettings.HelpLink
if helpLink == "" {

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

@@ -38,7 +38,7 @@ func (*InviteProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Comma
}
}
func (*InviteProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*InviteProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
if message == "" {
return &model.CommandResponse{
Text: args.T("api.command_invite.missing_message.app_error"),

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

@@ -42,7 +42,7 @@ func (*InvitePeopleProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model
}
}
func (*InvitePeopleProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*InvitePeopleProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
if !a.HasPermissionToTeam(args.UserId, args.TeamId, model.PermissionInviteUser) {
return &model.CommandResponse{Text: args.T("api.command_invite_people.permission.app_error"), ResponseType: model.CommandResponseTypeEphemeral}
}

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

@@ -37,7 +37,7 @@ func (*JoinProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Command
}
}
func (*JoinProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*JoinProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
channelName := strings.ToLower(message)
if strings.HasPrefix(message, "~") {

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

@@ -34,7 +34,7 @@ func (*LeaveProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Comman
}
}
func (*LeaveProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*LeaveProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
var channel *model.Channel
var noChannelErr *model.AppError
if channel, noChannelErr = a.GetChannel(c, args.ChannelId); noChannelErr != nil {

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

@@ -115,16 +115,16 @@ func (*LoadTestProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Com
}
}
func (lt *LoadTestProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (lt *LoadTestProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
commandResponse, err := lt.doCommand(a, c, args, message)
if err != nil {
mlog.Error("failed command /"+CmdTest, mlog.Err(err))
c.Logger().Error("failed command /"+CmdTest, mlog.Err(err))
}
return commandResponse
}
func (lt *LoadTestProvider) doCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
func (lt *LoadTestProvider) doCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
//This command is only available when EnableTesting is true
if !*a.Config().ServiceSettings.EnableTesting {
return &model.CommandResponse{}, nil
@@ -181,7 +181,7 @@ func (*LoadTestProvider) HelpCommand(args *model.CommandArgs, message string) *m
return &model.CommandResponse{Text: usage, ResponseType: model.CommandResponseTypeEphemeral}
}
func (*LoadTestProvider) SetupCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
func (*LoadTestProvider) SetupCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
tokens := strings.Fields(strings.TrimPrefix(message, "setup"))
doTeams := contains(tokens, "teams")
doFuzz := contains(tokens, "fuzz")
@@ -242,10 +242,10 @@ func (*LoadTestProvider) SetupCommand(a *app.App, c *request.Context, args *mode
return &model.CommandResponse{Text: "Failed to create testing environment", ResponseType: model.CommandResponseTypeEphemeral}, err
}
mlog.Info("Testing environment created")
c.Logger().Info("Testing environment created")
for i := 0; i < len(environment.Teams); i++ {
mlog.Info("Team Created: " + environment.Teams[i].Name)
mlog.Info("\t User to login: " + environment.Environments[i].Users[0].Email + ", " + UserPassword)
c.Logger().Info("Team Created: " + environment.Teams[i].Name)
c.Logger().Info("\t User to login: " + environment.Environments[i].Users[0].Email + ", " + UserPassword)
}
} else {
team, err := a.Srv().Store.Team().Get(args.TeamId)
@@ -267,7 +267,7 @@ func (*LoadTestProvider) SetupCommand(a *app.App, c *request.Context, args *mode
return &model.CommandResponse{Text: "Created environment", ResponseType: model.CommandResponseTypeEphemeral}, nil
}
func (*LoadTestProvider) ActivateUserCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
func (*LoadTestProvider) ActivateUserCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
user_id := strings.TrimSpace(strings.TrimPrefix(message, "activate_user"))
if err := a.UpdateUserActive(c, user_id, true); err != nil {
return &model.CommandResponse{Text: "Failed to activate user", ResponseType: model.CommandResponseTypeEphemeral}, err
@@ -276,7 +276,7 @@ func (*LoadTestProvider) ActivateUserCommand(a *app.App, c *request.Context, arg
return &model.CommandResponse{Text: "Activated user", ResponseType: model.CommandResponseTypeEphemeral}, nil
}
func (*LoadTestProvider) DeActivateUserCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
func (*LoadTestProvider) DeActivateUserCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
user_id := strings.TrimSpace(strings.TrimPrefix(message, "deactivate_user"))
if err := a.UpdateUserActive(c, user_id, false); err != nil {
return &model.CommandResponse{Text: "Failed to deactivate user", ResponseType: model.CommandResponseTypeEphemeral}, err
@@ -285,7 +285,7 @@ func (*LoadTestProvider) DeActivateUserCommand(a *app.App, c *request.Context, a
return &model.CommandResponse{Text: "DeActivated user", ResponseType: model.CommandResponseTypeEphemeral}, nil
}
func (*LoadTestProvider) UsersCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
func (*LoadTestProvider) UsersCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
cmd := strings.TrimSpace(strings.TrimPrefix(message, "users"))
doFuzz := false
@@ -314,7 +314,7 @@ func (*LoadTestProvider) UsersCommand(a *app.App, c *request.Context, args *mode
return &model.CommandResponse{Text: "Added users", ResponseType: model.CommandResponseTypeEphemeral}, nil
}
func (*LoadTestProvider) ChannelsCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
func (*LoadTestProvider) ChannelsCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
cmd := strings.TrimSpace(strings.TrimPrefix(message, "channels"))
doFuzz := false
@@ -342,7 +342,7 @@ func (*LoadTestProvider) ChannelsCommand(a *app.App, c *request.Context, args *m
return &model.CommandResponse{Text: "Added channels", ResponseType: model.CommandResponseTypeEphemeral}, nil
}
func (*LoadTestProvider) DMsCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
func (*LoadTestProvider) DMsCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
cmd := strings.TrimSpace(strings.TrimPrefix(message, "dms"))
channelsr, ok := parseRange(cmd, "")
@@ -358,7 +358,7 @@ func (*LoadTestProvider) DMsCommand(a *app.App, c *request.Context, args *model.
return &model.CommandResponse{Text: "Added DMs", ResponseType: model.CommandResponseTypeEphemeral}, nil
}
func (*LoadTestProvider) ThreadedPostCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
func (*LoadTestProvider) ThreadedPostCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
var usernames []string
options := &model.UserGetOptions{InTeamId: args.TeamId, Page: 0, PerPage: 1000}
if profileUsers, err := a.Srv().Store.User().GetProfiles(options); err == nil {
@@ -384,7 +384,7 @@ func (*LoadTestProvider) ThreadedPostCommand(a *app.App, c *request.Context, arg
return &model.CommandResponse{Text: "Added threaded post", ResponseType: model.CommandResponseTypeEphemeral}, nil
}
func (*LoadTestProvider) PostsCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
func (*LoadTestProvider) PostsCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
cmd := strings.TrimSpace(strings.TrimPrefix(message, "posts"))
doFuzz := false
@@ -486,7 +486,7 @@ func (*LoadTestProvider) PostCommand(a *app.App, c request.CTX, args *model.Comm
return &model.CommandResponse{Text: "Added a post to " + channel.DisplayName, ResponseType: model.CommandResponseTypeEphemeral}, nil
}
func (*LoadTestProvider) URLCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
func (*LoadTestProvider) URLCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
url := strings.TrimSpace(strings.TrimPrefix(message, "url"))
if url == "" {
return &model.CommandResponse{Text: "Command must contain a url", ResponseType: model.CommandResponseTypeEphemeral}, nil
@@ -540,7 +540,7 @@ func (*LoadTestProvider) URLCommand(a *app.App, c *request.Context, args *model.
return &model.CommandResponse{Text: "Loaded data", ResponseType: model.CommandResponseTypeEphemeral}, nil
}
func (*LoadTestProvider) JsonCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
func (*LoadTestProvider) JsonCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) (*model.CommandResponse, error) {
url := strings.TrimSpace(strings.TrimPrefix(message, "json"))
if url == "" {
return &model.CommandResponse{Text: "Command must contain a url", ResponseType: model.CommandResponseTypeEphemeral}, nil

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

@@ -35,7 +35,7 @@ func (*LogoutProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Comma
}
}
func (*LogoutProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*LogoutProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
// Actual logout is handled client side.
return &model.CommandResponse{GotoLocation: "/login"}
}

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

@@ -35,7 +35,7 @@ func (*MeProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Command {
}
}
func (*MeProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*MeProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
return &model.CommandResponse{
ResponseType: model.CommandResponseTypeInChannel,
Type: model.PostTypeMe,

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

@@ -40,7 +40,7 @@ func (*msgProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Command
}
}
func (*msgProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*msgProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
splitMessage := strings.SplitN(message, " ", 2)
parsedMessage := ""

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

@@ -37,7 +37,7 @@ func (*MuteProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Command
}
}
func (*MuteProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*MuteProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
var channel *model.Channel
var noChannelErr *model.AppError

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

@@ -34,7 +34,7 @@ func (*OfflineProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Comm
}
}
func (*OfflineProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*OfflineProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
a.SetStatusOffline(args.UserId, true)
return &model.CommandResponse{ResponseType: model.CommandResponseTypeEphemeral, Text: args.T("api.command_offline.success")}

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

@@ -34,7 +34,7 @@ func (*OnlineProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Comma
}
}
func (*OnlineProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*OnlineProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
a.SetStatusOnline(args.UserId, true)
return &model.CommandResponse{ResponseType: model.CommandResponseTypeEphemeral, Text: args.T("api.command_online.success")}

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

@@ -69,7 +69,7 @@ func (rp *RemoteProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Co
}
}
func (rp *RemoteProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (rp *RemoteProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
if !a.HasPermissionTo(args.UserId, model.PermissionManageSecureConnections) {
return responsef(args.T("api.command_remote.permission_required", map[string]any{"Permission": "manage_secure_connections"}))
}

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

@@ -57,15 +57,15 @@ func (*KickProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Command
}
}
func (*RemoveProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*RemoveProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
return doCommand(a, c, args, message)
}
func (*KickProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*KickProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
return doCommand(a, c, args, message)
}
func doCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func doCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
channel, err := a.GetChannel(c, args.ChannelId)
if err != nil {
return &model.CommandResponse{

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

@@ -35,7 +35,7 @@ func (search *SearchProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *mode
}
}
func (search *SearchProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (search *SearchProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
// This command is handled client-side and shouldn't hit the server.
return &model.CommandResponse{
Text: args.T("api.command_search.unsupported.app_error"),

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

@@ -35,7 +35,7 @@ func (settings *SettingsProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *
}
}
func (settings *SettingsProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (settings *SettingsProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
// This command is handled client-side and shouldn't hit the server.
return &model.CommandResponse{
Text: args.T("api.command_settings.unsupported.app_error"),

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

@@ -120,7 +120,7 @@ func (sp *ShareProvider) getAutoCompleteUnInviteRemote(a *app.App, _ *model.Comm
}
}
func (sp *ShareProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (sp *ShareProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
if !a.HasPermissionTo(args.UserId, model.PermissionManageSharedChannels) {
return responsef(args.T("api.command_share.permission_required", map[string]any{"Permission": "manage_shared_channels"}))
}

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

@@ -35,7 +35,7 @@ func (*ShortcutsProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Co
}
}
func (*ShortcutsProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*ShortcutsProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
// This command is handled client-side and shouldn't hit the server.
return &model.CommandResponse{
Text: args.T("api.command_shortcuts.unsupported.app_error"),

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

@@ -35,7 +35,7 @@ func (*ShrugProvider) GetCommand(a *app.App, T i18n.TranslateFunc) *model.Comman
}
}
func (*ShrugProvider) DoCommand(a *app.App, c *request.Context, args *model.CommandArgs, message string) *model.CommandResponse {
func (*ShrugProvider) DoCommand(a *app.App, c request.CTX, args *model.CommandArgs, message string) *model.CommandResponse {
rmsg := `¯\\\_(ツ)\_/¯`
if message != "" {
rmsg = message + " " + rmsg

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

@@ -525,7 +525,7 @@ func TestMentionsToTeamMembers(t *testing.T) {
}
for _, data := range fixture {
actualMap := th.App.MentionsToTeamMembers(data.message, data.inTeam)
actualMap := th.App.MentionsToTeamMembers(th.Context, data.message, data.inTeam)
require.Equal(t, actualMap, data.expectedMap)
}
}

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

@@ -65,7 +65,7 @@ func setupTestHelper(dbStore store.Store, enterprise bool, includeCacheLayer boo
options = append(options, app.ConfigStore(memoryStore))
if includeCacheLayer {
options = append(options, app.StoreOverride(func(s *app.Server) store.Store {
lcl, err2 := localcachelayer.NewLocalCacheLayer(dbStore, s.Metrics, s.Cluster, s.CacheProvider)
lcl, err2 := localcachelayer.NewLocalCacheLayer(dbStore, s.GetMetrics(), s.Cluster, s.CacheProvider)
if err2 != nil {
panic(err2)
}

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

@@ -18,7 +18,7 @@ import (
// only that channel's members are created. If channelID is nil all channel memberships are created.
// If includeRemovedMembers is true, then channel members who left or were removed from the channel will
// be re-added; otherwise, they will not be re-added.
func (a *App) createDefaultChannelMemberships(c *request.Context, since int64, channelID *string, includeRemovedMembers bool) error {
func (a *App) createDefaultChannelMemberships(c request.CTX, since int64, channelID *string, includeRemovedMembers bool) error {
channelMembers, appErr := a.ChannelMembersToAdd(since, channelID, includeRemovedMembers)
if appErr != nil {
return appErr
@@ -40,7 +40,7 @@ func (a *App) createDefaultChannelMemberships(c *request.Context, since int64, c
_, err = a.AddTeamMember(c, channel.TeamId, userChannel.UserID)
if err != nil {
if err.Id == "api.team.join_user_to_team.allowed_domains.app_error" {
a.Log().Info("User not added to channel - the domain associated with the user is not in the list of allowed team domains",
c.Logger().Info("User not added to channel - the domain associated with the user is not in the list of allowed team domains",
mlog.String("user_id", userChannel.UserID),
mlog.String("channel_id", userChannel.ChannelID),
mlog.String("team_id", channel.TeamId),
@@ -49,7 +49,7 @@ func (a *App) createDefaultChannelMemberships(c *request.Context, since int64, c
}
return err
}
a.Log().Info("added teammember",
c.Logger().Info("added teammember",
mlog.String("user_id", userChannel.UserID),
mlog.String("team_id", channel.TeamId),
)
@@ -60,7 +60,7 @@ func (a *App) createDefaultChannelMemberships(c *request.Context, since int64, c
})
if err != nil {
if err.Id == "api.channel.add_user.to.channel.failed.deleted.app_error" {
a.Log().Info("Not adding user to channel because they have already left the team",
c.Logger().Info("Not adding user to channel because they have already left the team",
mlog.String("user_id", userChannel.UserID),
mlog.String("channel_id", userChannel.ChannelID),
)
@@ -69,7 +69,7 @@ func (a *App) createDefaultChannelMemberships(c *request.Context, since int64, c
}
}
a.Log().Info("added channelmember",
c.Logger().Info("added channelmember",
mlog.String("user_id", userChannel.UserID),
mlog.String("channel_id", userChannel.ChannelID),
)
@@ -83,7 +83,7 @@ func (a *App) createDefaultChannelMemberships(c *request.Context, since int64, c
// only that team's members are created. If teamID is nil all team memberships are created.
// If includeRemovedMembers is true, then team members who left or were removed from the team will
// be re-added; otherwise, they will not be re-added.
func (a *App) createDefaultTeamMemberships(c *request.Context, since int64, teamID *string, includeRemovedMembers bool) error {
func (a *App) createDefaultTeamMemberships(c request.CTX, since int64, teamID *string, includeRemovedMembers bool) error {
teamMembers, appErr := a.TeamMembersToAdd(since, teamID, includeRemovedMembers)
if appErr != nil {
return appErr
@@ -93,7 +93,7 @@ func (a *App) createDefaultTeamMemberships(c *request.Context, since int64, team
_, err := a.AddTeamMember(c, userTeam.TeamID, userTeam.UserID)
if err != nil {
if err.Id == "api.team.join_user_to_team.allowed_domains.app_error" {
a.Log().Info("User not added to team - the domain associated with the user is not in the list of allowed team domains",
c.Logger().Info("User not added to team - the domain associated with the user is not in the list of allowed team domains",
mlog.String("user_id", userTeam.UserID),
mlog.String("team_id", userTeam.TeamID),
)
@@ -102,7 +102,7 @@ func (a *App) createDefaultTeamMemberships(c *request.Context, since int64, team
return err
}
a.Log().Info("added teammember",
c.Logger().Info("added teammember",
mlog.String("user_id", userTeam.UserID),
mlog.String("team_id", userTeam.TeamID),
)
@@ -148,7 +148,7 @@ func (a *App) DeleteGroupConstrainedMemberships(c *request.Context) error {
// deleteGroupConstrainedTeamMemberships deletes team memberships of users who aren't members of the allowed
// groups of the given group-constrained team. If a teamID is given then the procedure is scoped to the given team,
// if teamID is nil then the procedure affects all teams.
func (a *App) deleteGroupConstrainedTeamMemberships(c *request.Context, teamID *string) error {
func (a *App) deleteGroupConstrainedTeamMemberships(c request.CTX, teamID *string) error {
teamMembers, appErr := a.TeamMembersToRemove(teamID)
if appErr != nil {
return appErr
@@ -160,7 +160,7 @@ func (a *App) deleteGroupConstrainedTeamMemberships(c *request.Context, teamID *
return err
}
a.Log().Info("removed teammember",
c.Logger().Info("removed teammember",
mlog.String("user_id", userTeam.UserId),
mlog.String("team_id", userTeam.TeamId),
)
@@ -172,7 +172,7 @@ func (a *App) deleteGroupConstrainedTeamMemberships(c *request.Context, teamID *
// deleteGroupConstrainedChannelMemberships deletes channel memberships of users who aren't members of the allowed
// groups of the given group-constrained channel. If a channelID is given then the procedure is scoped to the given team,
// if channelID is nil then the procedure affects all teams.
func (a *App) deleteGroupConstrainedChannelMemberships(c *request.Context, channelID *string) error {
func (a *App) deleteGroupConstrainedChannelMemberships(c request.CTX, channelID *string) error {
channelMembers, appErr := a.ChannelMembersToRemove(channelID)
if appErr != nil {
return appErr
@@ -233,7 +233,7 @@ func (a *App) SyncSyncableRoles(syncableID string, syncableType model.GroupSynca
// SyncRolesAndMembership updates the SchemeAdmin status and membership of all of the members of the given
// syncable.
func (a *App) SyncRolesAndMembership(c *request.Context, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) {
func (a *App) SyncRolesAndMembership(c request.CTX, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) {
a.SyncSyncableRoles(syncableID, syncableType)
lastJob, _ := a.Srv().Store.Job().GetNewestJobByStatusAndType(model.JobStatusSuccess, model.JobTypeLdapSync)
@@ -246,10 +246,14 @@ func (a *App) SyncRolesAndMembership(c *request.Context, syncableID string, sync
case model.GroupSyncableTypeTeam:
a.createDefaultTeamMemberships(c, since, &syncableID, includeRemovedMembers)
a.deleteGroupConstrainedTeamMemberships(c, &syncableID)
a.ClearTeamMembersCache(syncableID)
if err := a.ClearTeamMembersCache(syncableID); err != nil {
c.Logger().Warn("Error clearing team members cache", mlog.Err(err))
}
case model.GroupSyncableTypeChannel:
a.createDefaultChannelMemberships(c, since, &syncableID, includeRemovedMembers)
a.deleteGroupConstrainedChannelMemberships(c, &syncableID)
a.ClearChannelMembersCache(c, syncableID)
if err := a.ClearChannelMembersCache(c, syncableID); err != nil {
c.Logger().Warn("Error clearing channel members cache", mlog.Err(err))
}
}
}

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

@@ -231,7 +231,9 @@ func (a *App) UpdateTeam(team *model.Team) (*model.Team, *model.AppError) {
}
}
a.sendTeamEvent(oldTeam, model.WebsocketEventUpdateTeam)
if appErr := a.sendTeamEvent(oldTeam, model.WebsocketEventUpdateTeam); appErr != nil {
return nil, appErr
}
return oldTeam, nil
}
@@ -301,9 +303,14 @@ func (a *App) UpdateTeamScheme(team *model.Team) (*model.Team, *model.AppError)
}
}
a.ClearTeamMembersCache(team.Id)
nErr = a.ClearTeamMembersCache(team.Id)
if nErr != nil {
return nil, model.NewAppError("UpdateTeamScheme", "app.team.clear_cache.app_error", nil, "", http.StatusInternalServerError).Wrap(nErr)
}
a.sendTeamEvent(oldTeam, model.WebsocketEventUpdateTeamScheme)
if appErr := a.sendTeamEvent(oldTeam, model.WebsocketEventUpdateTeamScheme); appErr != nil {
return nil, appErr
}
return oldTeam, nil
}
@@ -336,7 +343,9 @@ func (a *App) UpdateTeamPrivacy(teamID string, teamType string, allowOpenInvite
}
}
a.sendTeamEvent(oldTeam, model.WebsocketEventUpdateTeam)
if appErr := a.sendTeamEvent(oldTeam, model.WebsocketEventUpdateTeam); appErr != nil {
return appErr
}
return nil
}
@@ -362,7 +371,9 @@ func (a *App) PatchTeam(teamID string, patch *model.TeamPatch) (*model.Team, *mo
}
}
a.sendTeamEvent(team, model.WebsocketEventUpdateTeam)
if appErr := a.sendTeamEvent(team, model.WebsocketEventUpdateTeam); appErr != nil {
return nil, appErr
}
return team, nil
}
@@ -389,12 +400,14 @@ func (a *App) RegenerateTeamInviteId(teamID string) (*model.Team, *model.AppErro
}
}
a.sendTeamEvent(updatedTeam, model.WebsocketEventUpdateTeam)
if appErr := a.sendTeamEvent(updatedTeam, model.WebsocketEventUpdateTeam); appErr != nil {
return nil, appErr
}
return updatedTeam, nil
}
func (a *App) sendTeamEvent(team *model.Team, event string) {
func (a *App) sendTeamEvent(team *model.Team, event string) *model.AppError {
sanitizedTeam := &model.Team{}
*sanitizedTeam = *team
sanitizedTeam.Sanitize()
@@ -407,10 +420,11 @@ func (a *App) sendTeamEvent(team *model.Team, event string) {
message := model.NewWebSocketEvent(event, teamID, "", "", nil)
teamJSON, jsonErr := json.Marshal(team)
if jsonErr != nil {
mlog.Warn("Failed to encode team to JSON", mlog.Err(jsonErr))
return model.NewAppError("sendTeamEvent", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
message.Add("team", string(teamJSON))
a.Publish(message)
return nil
}
func (a *App) GetSchemeRolesForTeam(teamID string) (string, string, string, *model.AppError) {
@@ -507,7 +521,9 @@ func (a *App) UpdateTeamMemberRoles(teamID string, userID string, newRoles strin
a.ClearSessionCacheForUser(userID)
a.sendUpdatedMemberRoleEvent(userID, member)
if appErr := a.sendUpdatedMemberRoleEvent(userID, member); appErr != nil {
return nil, appErr
}
return member, nil
}
@@ -544,22 +560,25 @@ func (a *App) UpdateTeamMemberSchemeRoles(teamID string, userID string, isScheme
a.ClearSessionCacheForUser(userID)
a.sendUpdatedMemberRoleEvent(userID, member)
if appErr := a.sendUpdatedMemberRoleEvent(userID, member); appErr != nil {
return nil, appErr
}
return member, nil
}
func (a *App) sendUpdatedMemberRoleEvent(userID string, member *model.TeamMember) {
func (a *App) sendUpdatedMemberRoleEvent(userID string, member *model.TeamMember) *model.AppError {
message := model.NewWebSocketEvent(model.WebsocketEventMemberroleUpdated, "", "", userID, nil)
tmJSON, jsonErr := json.Marshal(member)
if jsonErr != nil {
mlog.Warn("Failed to encode team member to JSON", mlog.Err(jsonErr))
return model.NewAppError("sendUpdatedMemberRoleEvent", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
message.Add("member", string(tmJSON))
a.Publish(message)
return nil
}
func (a *App) AddUserToTeam(c *request.Context, teamID string, userID string, userRequestorId string) (*model.Team, *model.TeamMember, *model.AppError) {
func (a *App) AddUserToTeam(c request.CTX, teamID string, userID string, userRequestorId string) (*model.Team, *model.TeamMember, *model.AppError) {
tchan := make(chan store.StoreResult, 1)
go func() {
team, err := a.Srv().Store.Team().Get(teamID)
@@ -1059,7 +1078,7 @@ func (a *App) GetCommonTeamIDsForTwoUsers(userID, otherUserID string) ([]string,
return teamIDs, nil
}
func (a *App) AddTeamMember(c *request.Context, teamID, userID string) (*model.TeamMember, *model.AppError) {
func (a *App) AddTeamMember(c request.CTX, teamID, userID string) (*model.TeamMember, *model.AppError) {
_, teamMember, err := a.AddUserToTeam(c, teamID, userID, "")
if err != nil {
return nil, err
@@ -1152,7 +1171,7 @@ func (a *App) GetTeamUnread(teamID, userID string) (*model.TeamUnread, *model.Ap
return teamUnread, nil
}
func (a *App) RemoveUserFromTeam(c *request.Context, teamID string, userID string, requestorId string) *model.AppError {
func (a *App) RemoveUserFromTeam(c request.CTX, teamID string, userID string, requestorId string) *model.AppError {
tchan := make(chan store.StoreResult, 1)
go func() {
team, err := a.Srv().Store.Team().Get(teamID)
@@ -1245,7 +1264,7 @@ func (a *App) postProcessTeamMemberLeave(c request.CTX, teamMember *model.TeamMe
return nil
}
func (a *App) LeaveTeam(c *request.Context, team *model.Team, user *model.User, requestorId string) *model.AppError {
func (a *App) LeaveTeam(c request.CTX, team *model.Team, user *model.User, requestorId string) *model.AppError {
teamMember, err := a.GetTeamMember(team.Id, user.Id)
if err != nil {
return model.NewAppError("LeaveTeam", "api.team.remove_user_from_team.missing.app_error", nil, err.Error(), http.StatusBadRequest)
@@ -1288,11 +1307,11 @@ func (a *App) LeaveTeam(c *request.Context, team *model.Team, user *model.User,
if requestorId == user.Id {
if err = a.postLeaveTeamMessage(c, user, channel); err != nil {
mlog.Warn("Failed to post join/leave message", mlog.Err(err))
c.Logger().Warn("Failed to post join/leave message", mlog.Err(err))
}
} else {
if err = a.postRemoveFromTeamMessage(c, user, channel); err != nil {
mlog.Warn("Failed to post join/leave message", mlog.Err(err))
c.Logger().Warn("Failed to post join/leave message", mlog.Err(err))
}
}
}
@@ -1308,7 +1327,7 @@ func (a *App) LeaveTeam(c *request.Context, team *model.Team, user *model.User,
return nil
}
func (a *App) postLeaveTeamMessage(c *request.Context, user *model.User, channel *model.Channel) *model.AppError {
func (a *App) postLeaveTeamMessage(c request.CTX, user *model.User, channel *model.Channel) *model.AppError {
post := &model.Post{
ChannelId: channel.Id,
Message: fmt.Sprintf(i18n.T("api.team.leave.left"), user.Username),
@@ -1326,7 +1345,7 @@ func (a *App) postLeaveTeamMessage(c *request.Context, user *model.User, channel
return nil
}
func (a *App) postRemoveFromTeamMessage(c *request.Context, user *model.User, channel *model.Channel) *model.AppError {
func (a *App) postRemoveFromTeamMessage(c request.CTX, user *model.User, channel *model.Channel) *model.AppError {
post := &model.Post{
ChannelId: channel.Id,
Message: fmt.Sprintf(i18n.T("api.team.remove_user_from_team.removed"), user.Username),
@@ -1797,7 +1816,9 @@ func (a *App) PermanentDeleteTeam(c request.CTX, team *model.Team) *model.AppErr
return model.NewAppError("PermanentDeleteTeam", "app.team.permanent_delete.app_error", nil, err.Error(), http.StatusInternalServerError)
}
a.sendTeamEvent(team, model.WebsocketEventDeleteTeam)
if appErr := a.sendTeamEvent(team, model.WebsocketEventDeleteTeam); appErr != nil {
return appErr
}
return nil
}
@@ -1823,7 +1844,9 @@ func (a *App) SoftDeleteTeam(teamID string) *model.AppError {
}
}
a.sendTeamEvent(team, model.WebsocketEventDeleteTeam)
if appErr := a.sendTeamEvent(team, model.WebsocketEventDeleteTeam); appErr != nil {
return appErr
}
return nil
}
@@ -1849,7 +1872,10 @@ func (a *App) RestoreTeam(teamID string) *model.AppError {
}
}
a.sendTeamEvent(team, model.WebsocketEventRestoreTeam)
if appErr := a.sendTeamEvent(team, model.WebsocketEventRestoreTeam); appErr != nil {
return appErr
}
return nil
}
@@ -2022,7 +2048,9 @@ func (a *App) SetTeamIconFromFile(team *model.Team, file io.Reader) *model.AppEr
// manually set time to avoid possible cluster inconsistencies
team.LastTeamIconUpdate = curTime
a.sendTeamEvent(team, model.WebsocketEventUpdateTeam)
if appErr := a.sendTeamEvent(team, model.WebsocketEventUpdateTeam); appErr != nil {
return appErr
}
return nil
}
@@ -2039,7 +2067,9 @@ func (a *App) RemoveTeamIcon(teamID string) *model.AppError {
team.LastTeamIconUpdate = 0
a.sendTeamEvent(team, model.WebsocketEventUpdateTeam)
if appErr := a.sendTeamEvent(team, model.WebsocketEventUpdateTeam); appErr != nil {
return appErr
}
return nil
}
@@ -2072,15 +2102,14 @@ func (a *App) InvalidateAllResendInviteEmailJobs() *model.AppError {
return nil
}
func (a *App) ClearTeamMembersCache(teamID string) {
func (a *App) ClearTeamMembersCache(teamID string) error {
perPage := 100
page := 0
for {
teamMembers, err := a.Srv().Store.Team().GetMembers(teamID, page*perPage, perPage, nil)
if err != nil {
a.Log().Warn("error clearing cache for team members", mlog.String("team_id", teamID), mlog.String("err", err.Error()))
break
return fmt.Errorf("failed to get team members: %v", err)
}
for _, teamMember := range teamMembers {
@@ -2089,7 +2118,7 @@ func (a *App) ClearTeamMembersCache(teamID string) {
message := model.NewWebSocketEvent(model.WebsocketEventMemberroleUpdated, "", "", teamMember.UserId, nil)
tmJSON, jsonErr := json.Marshal(teamMember)
if jsonErr != nil {
mlog.Warn("Failed to encode team member to JSON", mlog.Err(jsonErr))
return jsonErr
}
message.Add("member", string(tmJSON))
a.Publish(message)
@@ -2102,4 +2131,5 @@ func (a *App) ClearTeamMembersCache(teamID string) {
page++
}
return nil
}

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

@@ -1433,7 +1433,7 @@ func TestClearTeamMembersCache(t *testing.T) {
mockStore.On("Team").Return(&mockTeamStore)
mockStore.On("GetDBSchemaVersion").Return(1, nil)
th.App.ClearTeamMembersCache("teamID")
require.NoError(t, th.App.ClearTeamMembersCache("teamID"))
}
func TestInviteNewUsersToTeamGracefully(t *testing.T) {

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

@@ -883,7 +883,7 @@ func (a *App) UpdatePasswordAsUser(c request.CTX, userID, currentPassword, newPa
return a.UpdatePasswordSendEmail(c, user, newPassword, T("api.user.update_password.menu"))
}
func (a *App) userDeactivated(c *request.Context, userID string) *model.AppError {
func (a *App) userDeactivated(c request.CTX, userID string) *model.AppError {
a.SetStatusOffline(userID, false)
user, err := a.GetUser(userID)
@@ -928,7 +928,7 @@ func (a *App) invalidateUserChannelMembersCaches(c request.CTX, userID string) *
return nil
}
func (a *App) UpdateActive(c *request.Context, user *model.User, active bool) (*model.User, *model.AppError) {
func (a *App) UpdateActive(c request.CTX, user *model.User, active bool) (*model.User, *model.AppError) {
user.UpdateAt = model.GetMillis()
if active {
user.DeleteAt = 0
@@ -1220,7 +1220,7 @@ func (a *App) UpdateUser(c request.CTX, user *model.User, sendNotifications bool
return userUpdate.New, nil
}
func (a *App) UpdateUserActive(c *request.Context, userID string, active bool) *model.AppError {
func (a *App) UpdateUserActive(c request.CTX, userID string, active bool) *model.AppError {
user, err := a.GetUser(userID)
if err != nil {
@@ -1416,7 +1416,6 @@ func (a *App) CreatePasswordRecoveryToken(userID, email string) (*model.Token, *
email,
}
jsonData, err := json.Marshal(tokenExtra)
if err != nil {
return nil, model.NewAppError("CreatePasswordRecoveryToken", "api.user.create_password_token.error", nil, "", http.StatusInternalServerError)
}
@@ -2196,7 +2195,7 @@ func (a *App) PromoteGuestToUser(c *request.Context, user *model.User, requestor
evt := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", user.Id, nil)
memberJSON, jsonErr := json.Marshal(member)
if jsonErr != nil {
c.Logger().Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr))
return model.NewAppError("PromoteGuestToUser", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
evt.Add("channelMember", string(memberJSON))
a.Publish(evt)
@@ -2241,7 +2240,7 @@ func (a *App) DemoteUserToGuest(c request.CTX, user *model.User) *model.AppError
evt := model.NewWebSocketEvent(model.WebsocketEventChannelMemberUpdated, "", "", user.Id, nil)
memberJSON, jsonErr := json.Marshal(member)
if jsonErr != nil {
c.Logger().Warn("Failed to encode channel member to JSON", mlog.Err(jsonErr))
return model.NewAppError("DemoteUserToGuest", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
evt.Add("channelMember", string(memberJSON))
a.Publish(evt)
@@ -2518,7 +2517,7 @@ func (a *App) UpdateThreadFollowForUserFromChannelAdd(c request.CTX, userID, tea
payload, jsonErr := json.Marshal(userThread)
if jsonErr != nil {
c.Logger().Warn("Failed to encode thread to JSON")
return model.NewAppError("UpdateThreadFollowForUserFromChannelAdd", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(jsonErr)
}
message.Add("thread", string(payload))
message.Add("previous_unread_replies", int64(0))

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

@@ -157,8 +157,8 @@ func (a *App) HubUnregister(webConn *WebConn) {
}
func (s *Server) Publish(message *model.WebSocketEvent) {
if s.Metrics != nil {
s.Metrics.IncrementWebsocketEvent(message.EventType())
if s.GetMetrics() != nil {
s.GetMetrics().IncrementWebsocketEvent(message.EventType())
}
s.PublishSkipClusterSend(message)
@@ -357,7 +357,7 @@ func (h *Hub) Broadcast(message *model.WebSocketEvent) {
// And possibly, we can look into doing the hub initialization inside
// NewServer itself.
if h != nil && message != nil {
if metrics := h.srv.Metrics; metrics != nil {
if metrics := h.srv.GetMetrics(); metrics != nil {
metrics.IncrementWebSocketBroadcastBufferSize(strconv.Itoa(h.connectionIndex), 1)
}
select {
@@ -525,7 +525,7 @@ func (h *Hub) Start() {
connIndex.Remove(directMsg.conn)
}
case msg := <-h.broadcast:
if metrics := h.srv.Metrics; metrics != nil {
if metrics := h.srv.GetMetrics(); metrics != nil {
metrics.DecrementWebSocketBroadcastBufferSize(strconv.Itoa(h.connectionIndex), 1)
}
msg = msg.PrecomputeJSON()

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

@@ -10,6 +10,7 @@ import (
"path/filepath"
"time"
"github.com/mattermost/mattermost-server/v6/app/request"
"github.com/mattermost/mattermost-server/v6/audit"
"github.com/mattermost/mattermost-server/v6/model"
@@ -229,7 +230,7 @@ func bulkExportCmdF(command *cobra.Command, args []string) error {
var opts model.BulkExportOpts
opts.IncludeAttachments = attachments
opts.CreateArchive = archive
if err := a.BulkExport(fileWriter, filepath.Dir(outPath), opts); err != nil {
if err := a.BulkExport(request.EmptyContext(a.Log()), fileWriter, filepath.Dir(outPath), opts); err != nil {
CommandPrintErrorln(err.Error())
return err
}

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

@@ -2045,10 +2045,6 @@
"id": "api.license.request_trial_license.fail_get_user_count.app_error",
"translation": "Unable to get a trial license, please try again or contact with support@mattermost.com. Cannot obtain the number of registered users."
},
{
"id": "api.license.request_trial_license.no-site-url.app_error",
"translation": "Unable to request a trial license. Please configure a Site URL in the web server section of the Mattermost System Console."
},
{
"id": "api.license.upgrade_needed.app_error",
"translation": "Feature requires an upgrade to Enterprise Edition."
@@ -6155,6 +6151,10 @@
"id": "app.team.clear_all_custom_role_assignments.select.app_error",
"translation": "Failed to retrieve the team members."
},
{
"id": "app.team.clear_cache.app_error",
"translation": "Error clearing team member cache"
},
{
"id": "app.team.get.find.app_error",
"translation": "Unable to find the existing team."

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

@@ -7,6 +7,7 @@ import (
"io"
"path/filepath"
"github.com/mattermost/mattermost-server/v6/app/request"
"github.com/mattermost/mattermost-server/v6/jobs"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/services/configservice"
@@ -18,7 +19,8 @@ const jobName = "ExportProcess"
type AppIface interface {
configservice.ConfigService
WriteFile(fr io.Reader, path string) (int64, *model.AppError)
BulkExport(writer io.Writer, outPath string, opts model.BulkExportOpts) *model.AppError
BulkExport(ctx request.CTX, writer io.Writer, outPath string, opts model.BulkExportOpts) *model.AppError
Log() *mlog.Logger
}
func MakeWorker(jobServer *jobs.JobServer, app AppIface) model.Worker {
@@ -45,7 +47,7 @@ func MakeWorker(jobServer *jobs.JobServer, app AppIface) model.Worker {
errCh <- appErr
}()
appErr := app.BulkExport(wr, outPath, opts)
appErr := app.BulkExport(request.EmptyContext(app.Log()), wr, outPath, opts)
if err := wr.Close(); err != nil {
mlog.Warn("Worker: error closing writer")
}

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

@@ -98,11 +98,11 @@ func (f *FeatureFlags) SetDefaults() {
f.GraphQL = false
f.InsightsEnabled = true
f.CommandPalette = false
f.PostForwarding = false
f.PostForwarding = true
f.AdvancedTextEditor = true
f.CallsEnabled = true
f.BoardsProduct = false
f.PlanUpgradeButtonText = "Upgrade"
f.PlanUpgradeButtonText = "upgrade"
}
func (f *FeatureFlags) Plugins() map[string]string {

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

@@ -269,13 +269,13 @@ func (_m *MockAppIface) InvalidateCacheForUser(userID string) {
_m.Called(userID)
}
// MentionsToTeamMembers provides a mock function with given fields: message, teamID
func (_m *MockAppIface) MentionsToTeamMembers(message string, teamID string) model.UserMentionMap {
ret := _m.Called(message, teamID)
// MentionsToTeamMembers provides a mock function with given fields: c, message, teamID
func (_m *MockAppIface) MentionsToTeamMembers(c request.CTX, message string, teamID string) model.UserMentionMap {
ret := _m.Called(c, message, teamID)
var r0 model.UserMentionMap
if rf, ok := ret.Get(0).(func(string, string) model.UserMentionMap); ok {
r0 = rf(message, teamID)
if rf, ok := ret.Get(0).(func(request.CTX, string, string) model.UserMentionMap); ok {
r0 = rf(c, message, teamID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(model.UserMentionMap)

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

@@ -59,7 +59,7 @@ type AppIface interface {
PatchChannelModerationsForChannel(c request.CTX, channel *model.Channel, channelModerationsPatch []*model.ChannelModerationPatch) ([]*model.ChannelModeration, *model.AppError)
CreateUploadSession(c request.CTX, us *model.UploadSession) (*model.UploadSession, *model.AppError)
FileReader(path string) (filestore.ReadCloseSeeker, *model.AppError)
MentionsToTeamMembers(message, teamID string) model.UserMentionMap
MentionsToTeamMembers(c request.CTX, message, teamID string) model.UserMentionMap
GetProfileImage(user *model.User) ([]byte, bool, *model.AppError)
InvalidateCacheForUser(userID string)
NotifySharedChannelUserUpdate(user *model.User)

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

@@ -11,6 +11,7 @@ import (
"github.com/wiggin77/merror"
"github.com/mattermost/mattermost-server/v6/app/request"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/services/remotecluster"
"github.com/mattermost/mattermost-server/v6/shared/mlog"
@@ -271,7 +272,7 @@ func (scs *Service) fetchPostUsersForSync(sd *syncData) error {
userIDs[post.UserId] = p2mm{}
// get mentions and users for each mention
mentionMap := scs.app.MentionsToTeamMembers(post.Message, sc.TeamId)
mentionMap := scs.app.MentionsToTeamMembers(request.EmptyContext(scs.server.GetLogger()), post.Message, sc.TeamId)
for _, userID := range mentionMap {
userIDs[userID] = p2mm{
post: post,

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

@@ -368,7 +368,10 @@ func (b *S3FileBackend) WriteFile(fr io.Reader, path string) (int64, error) {
options := s3PutOptions(b.encrypt, contentType)
objSize := -1
if buf, ok := fr.(*bytes.Buffer); ok {
isCloud := os.Getenv("MM_CLOUD_FILESTORE_BIFROST") != ""
// We pass an object size only in situations where bifrost is not
// used. Bifrost needs to run in HTTPS, which is not yet deployed.
if buf, ok := fr.(*bytes.Buffer); ok && !isCloud {
objSize = buf.Len()
}
@@ -401,7 +404,10 @@ func (b *S3FileBackend) AppendFile(fr io.Reader, path string) (int64, error) {
ctx2, cancel2 := context.WithTimeout(context.Background(), b.timeout)
defer cancel2()
objSize := -1
if buf, ok := fr.(*bytes.Buffer); ok {
isCloud := os.Getenv("MM_CLOUD_FILESTORE_BIFROST") != ""
// We pass an object size only in situations where bifrost is not
// used. Bifrost needs to run in HTTPS, which is not yet deployed.
if buf, ok := fr.(*bytes.Buffer); ok && !isCloud {
objSize = buf.Len()
}
info, err := b.client.PutObject(ctx2, b.bucket, partName, fr, int64(objSize), options)

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

@@ -784,6 +784,13 @@ func (s *SqlPostStore) Get(ctx context.Context, id string, opts model.GetPostsOp
}
for _, p := range posts {
if p.Id == id {
// Based on the conditions above such as sq.Or{ sq.Eq{"p.Id": rootId}, sq.Eq{"p.RootId": rootId}, }
// posts may contain the "id" post which has already been fetched and added in the "pl"
// So, skip the "id" to avoid duplicate entry of the post
continue
}
pl.AddPost(p)
pl.AddOrder(p.Id)
}
@@ -2188,7 +2195,7 @@ func (s *SqlPostStore) AnalyticsPostCountsByDay(options *model.AnalyticsPostCoun
func (s *SqlPostStore) AnalyticsPostCount(options *model.PostCountOptions) (int64, error) {
query := s.getQueryBuilder().
Select("COUNT(p.Id) AS Value").
Select("COUNT(*) AS Value").
From("Posts p")
if options.TeamId != "" {
@@ -2840,8 +2847,23 @@ func (s *SqlPostStore) updateThreadAfterReplyDeletion(transaction *sqlxTxWrapper
}
}
lastReplyAtSubquery := sq.Select("COALESCE(MAX(CreateAt), 0)").
From("Posts").
Where(sq.Eq{
"RootId": rootId,
"DeleteAt": 0,
})
lastReplyCountSubquery := sq.Select("Count(*)").
From("Posts").
Where(sq.Eq{
"RootId": rootId,
"DeleteAt": 0,
})
updateQueryString, updateArgs, err := updateQuery.
Set("ReplyCount", sq.Expr("ReplyCount - 1")).
Set("LastReplyAt", lastReplyAtSubquery).
Set("ReplyCount", lastReplyCountSubquery).
Where(sq.And{
sq.Eq{"PostId": rootId},
sq.Gt{"ReplyCount": 0},

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

@@ -1500,17 +1500,20 @@ func generateSearchQuery(query sq.SelectBuilder, terms []string, fields []string
for _, term := range terms {
searchFields := []string{}
termArgs := []any{}
var dbSpecificTerm string
for _, field := range fields {
if isPostgreSQL {
searchFields = append(searchFields, fmt.Sprintf("lower(%s) LIKE lower(?) escape '*' ", field))
searchFields = append(searchFields, fmt.Sprintf("to_tsvector(lower(%[1]s)) @@ to_tsquery(concat(lower(?),':*'))", field))
dbSpecificTerm = strings.TrimLeft(term, "@")
} else {
searchFields = append(searchFields, fmt.Sprintf("%s LIKE ? escape '*' ", field))
dbSpecificTerm = fmt.Sprintf("%s%%", strings.TrimLeft(term, "@"))
}
termArgs = append(termArgs, fmt.Sprintf("%s%%", strings.TrimLeft(term, "@")))
termArgs = append(termArgs, dbSpecificTerm)
}
query = query.Where(fmt.Sprintf("(%s)", strings.Join(searchFields, " OR ")), termArgs...)
}
return query
}

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

@@ -569,6 +569,7 @@ func testPostStoreGetForThread(t *testing.T, ss store.Store) {
})
t.Run("Pagination", func(t *testing.T) {
t.Skip("MM-46134")
o1, err := ss.Post().Save(&model.Post{ChannelId: model.NewId(), UserId: model.NewId(), Message: NewTestId()})
require.NoError(t, err)
_, err = ss.Post().Save(&model.Post{ChannelId: o1.ChannelId, UserId: model.NewId(), Message: NewTestId(), RootId: o1.Id})
@@ -644,7 +645,7 @@ func testPostStoreGetForThread(t *testing.T, ss store.Store) {
}
r1, err = ss.Post().Get(context.Background(), o1.Id, opts, o1.UserId, map[string]bool{})
require.NoError(t, err)
assert.Len(t, r1.Order, 3) // including the root post
assert.Len(t, r1.Order, 2) // including the root post
assert.True(t, r1.HasNext)
lastPostID = r1.Order[len(r1.Order)-1]
@@ -676,7 +677,7 @@ func testPostStoreGetForThread(t *testing.T, ss store.Store) {
}
r1, err = ss.Post().Get(context.Background(), o1.Id, opts, o1.UserId, map[string]bool{})
require.NoError(t, err)
assert.Len(t, r1.Order, 3) // including the root post
assert.Len(t, r1.Order, 2) // including the root post
assert.LessOrEqual(t, r1.Posts[r1.Order[1]].CreateAt, firstPostCreateAt)
assert.False(t, r1.HasNext)
@@ -980,6 +981,74 @@ func testPostStoreDelete(t *testing.T, ss store.Store) {
_, err = ss.Post().Get(context.Background(), rootPost2.Id, model.GetPostsOptions{}, "", map[string]bool{})
require.NoError(t, err)
})
t.Run("thread with multiple replies, update thread last reply at", func(t *testing.T) {
// Create a root post
rootPost1, err := ss.Post().Save(&model.Post{
ChannelId: model.NewId(),
UserId: model.NewId(),
Message: NewTestId(),
})
require.NoError(t, err)
// Reply to that root post
replyPost1, err := ss.Post().Save(&model.Post{
ChannelId: rootPost1.ChannelId,
UserId: model.NewId(),
Message: NewTestId(),
RootId: rootPost1.Id,
})
require.NoError(t, err)
// Reply to that root post a second time
replyPost2, err := ss.Post().Save(&model.Post{
ChannelId: rootPost1.ChannelId,
UserId: model.NewId(),
Message: NewTestId(),
RootId: rootPost1.Id,
})
require.NoError(t, err)
// Reply to that root post a third time
replyPost3, err := ss.Post().Save(&model.Post{
ChannelId: rootPost1.ChannelId,
UserId: model.NewId(),
Message: NewTestId(),
RootId: rootPost1.Id,
})
require.NoError(t, err)
thread, err := ss.Thread().Get(rootPost1.Id)
require.NoError(t, err)
require.Equal(t, replyPost3.CreateAt, thread.LastReplyAt)
// Delete the reply previous to last
err = ss.Post().Delete(replyPost2.Id, model.GetMillis(), "")
require.NoError(t, err)
thread, err = ss.Thread().Get(rootPost1.Id)
require.NoError(t, err)
// last reply at should be unchanged
require.Equal(t, replyPost3.CreateAt, thread.LastReplyAt)
// Delete the last reply
err = ss.Post().Delete(replyPost3.Id, model.GetMillis(), "")
require.NoError(t, err)
thread, err = ss.Thread().Get(rootPost1.Id)
require.NoError(t, err)
// last reply at should have changed
require.Equal(t, replyPost1.CreateAt, thread.LastReplyAt)
// Delete the last reply
err = ss.Post().Delete(replyPost1.Id, model.GetMillis(), "")
require.NoError(t, err)
thread, err = ss.Thread().Get(rootPost1.Id)
require.NoError(t, err)
// last reply at should be 0
require.Equal(t, int64(0), thread.LastReplyAt)
})
}
func testPostStorePermDelete1Level(t *testing.T, ss store.Store) {

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

@@ -94,6 +94,7 @@ func TestUserStore(t *testing.T, ss store.Store, s SqlStore) {
t.Run("ResetLastPictureUpdate", func(t *testing.T) { testUserStoreResetLastPictureUpdate(t, ss) })
t.Run("GetKnownUsers", func(t *testing.T) { testGetKnownUsers(t, ss) })
t.Run("GetUsersWithInvalidEmails", func(t *testing.T) { testGetUsersWithInvalidEmails(t, ss) })
t.Run("SearchMultilingual", func(t *testing.T) { testUserStoreSearchUsersMultilingual(t, ss, s) })
}
func testUserStoreSave(t *testing.T, ss store.Store) {
@@ -6010,3 +6011,174 @@ func testGetUsersWithInvalidEmails(t *testing.T, ss store.Store) {
require.NoError(t, err)
assert.Len(t, users, 1)
}
func testUserStoreSearchUsersMultilingual(t *testing.T, ss store.Store, s SqlStore) {
u1 := &model.User{
Username: "test1" + model.NewId(),
FirstName: "Inígo",
LastName: "Martínez",
Nickname: "Berridi",
Email: MakeEmail(),
}
_, err := ss.User().Save(u1)
require.NoError(t, err)
defer func() { require.NoError(t, ss.User().PermanentDelete(u1.Id)) }()
u2 := &model.User{
Username: "test2" + model.NewId(),
FirstName: "Zinëdìne",
LastName: "Zidanë",
Email: MakeEmail(),
}
_, err = ss.User().Save(u2)
require.NoError(t, err)
defer func() { require.NoError(t, ss.User().PermanentDelete(u2.Id)) }()
u3 := &model.User{
Username: "test3" + model.NewId(),
FirstName: "Thomas ",
LastName: "Müller",
Nickname: "Fußballspieler",
Email: MakeEmail(),
}
_, err = ss.User().Save(u3)
require.NoError(t, err)
defer func() { require.NoError(t, ss.User().PermanentDelete(u3.Id)) }()
u4 := &model.User{
Username: "test4" + model.NewId(),
FirstName: "Jérémie ",
LastName: "Jéry",
Email: MakeEmail(),
}
_, err = ss.User().Save(u4)
require.NoError(t, err)
defer func() { require.NoError(t, ss.User().PermanentDelete(u4.Id)) }()
// The users returned from the database will have AuthData as an empty string.
nilAuthData := new(string)
*nilAuthData = ""
u1.AuthData = nilAuthData
u2.AuthData = nilAuthData
u3.AuthData = nilAuthData
u4.AuthData = nilAuthData
testCases := []struct {
Description string
Term string
Options *model.UserSearchOptions
ExpectedPostgres []*model.User
ExpectedMysql []*model.User
Language string
}{
{
"search test1 player",
"inig",
&model.UserSearchOptions{
AllowFullNames: true,
Limit: model.UserSearchDefaultLimit,
},
[]*model.User{u1},
[]*model.User{u1},
"spanish",
},
{
"search test2 player",
"zine",
&model.UserSearchOptions{
AllowFullNames: true,
Limit: model.UserSearchDefaultLimit,
},
[]*model.User{u2},
[]*model.User{u2},
"french",
},
{
"search test2 player",
"zidane",
&model.UserSearchOptions{
AllowFullNames: true,
Limit: model.UserSearchDefaultLimit,
},
[]*model.User{u2},
[]*model.User{u2},
"french",
},
{
"search test3 player",
"muller",
&model.UserSearchOptions{
AllowFullNames: true,
Limit: model.UserSearchDefaultLimit,
},
[]*model.User{u3},
[]*model.User{u3},
"german",
},
{
"search test3 player",
"muller",
&model.UserSearchOptions{
AllowFullNames: true,
Limit: model.UserSearchDefaultLimit,
},
[]*model.User{},
[]*model.User{u3},
"english",
},
{
"search test4 player",
"jere",
&model.UserSearchOptions{
AllowFullNames: true,
Limit: model.UserSearchDefaultLimit,
},
[]*model.User{u4},
[]*model.User{u4},
"spanish",
},
{
"search test4 player",
"jere",
&model.UserSearchOptions{
AllowFullNames: true,
Limit: model.UserSearchDefaultLimit,
},
[]*model.User{},
[]*model.User{u4},
"english",
},
}
var initialDefaultTextSearchConfig string
if s.DriverName() == model.DatabaseDriverPostgres {
error := s.GetMasterX().Get(&initialDefaultTextSearchConfig, `SHOW default_text_search_config`)
require.NoError(t, error)
}
for _, testCase := range testCases {
if s.DriverName() == model.DatabaseDriverPostgres {
_, error := s.GetMasterX().Exec("SET default_text_search_config TO '" + testCase.Language + "'")
require.NoError(t, error)
}
t.Run(testCase.Description, func(t *testing.T) {
users, err := ss.User().SearchWithoutTeam(
testCase.Term,
testCase.Options,
)
if s.DriverName() != model.DatabaseDriverPostgres {
require.NoError(t, err)
assertUsers(t, testCase.ExpectedMysql, users)
} else {
require.NoError(t, err)
assertUsers(t, testCase.ExpectedPostgres, users)
}
})
}
if s.DriverName() == model.DatabaseDriverPostgres {
_, error := s.GetMasterX().Exec("SET default_text_search_config TO '" + initialDefaultTextSearchConfig + "'")
require.NoError(t, error)
}
}

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

@@ -96,7 +96,7 @@ func setupTestHelper(tb testing.TB, includeCacheLayer bool) *TestHelper {
}
if includeCacheLayer {
// Adds the cache layer to the test store
s.Store, err = localcachelayer.NewLocalCacheLayer(s.Store, s.Metrics, s.Cluster, s.CacheProvider)
s.Store, err = localcachelayer.NewLocalCacheLayer(s.Store, s.GetMetrics(), s.Cluster, s.CacheProvider)
if err != nil {
panic(err)
}