From 4ebf9746905c845ee3874f87478d7450391680d8 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 2 Mar 2018 10:49:18 -0600 Subject: remove `go Publish(...)` idiom (#8373) --- app/channel.go | 17 ++++------------- app/command_expand_collapse.go | 4 +--- app/emoji.go | 1 - app/post.go | 18 ++++-------------- app/preference.go | 8 ++------ app/status.go | 16 ++++------------ app/team.go | 9 ++------- app/user.go | 9 ++------- 8 files changed, 19 insertions(+), 63 deletions(-) (limited to 'app') diff --git a/app/channel.go b/app/channel.go index 8ac1f421c..131e242fb 100644 --- a/app/channel.go +++ b/app/channel.go @@ -545,7 +545,6 @@ func (a *App) DeleteChannel(channel *model.Channel, userId string) *model.AppErr message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_DELETED, channel.TeamId, "", "", nil) message.Add("channel_id", channel.Id) - a.Publish(message) } @@ -1166,17 +1165,13 @@ func (a *App) removeUserFromChannel(userIdToRemove string, removerUserId string, message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_REMOVED, "", channel.Id, "", nil) message.Add("user_id", userIdToRemove) message.Add("remover_id", removerUserId) - a.Go(func() { - a.Publish(message) - }) + a.Publish(message) // because the removed user no longer belongs to the channel we need to send a separate websocket event userMsg := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_REMOVED, "", "", userIdToRemove, nil) userMsg.Add("channel_id", channel.Id) userMsg.Add("remover_id", removerUserId) - a.Go(func() { - a.Publish(userMsg) - }) + a.Publish(userMsg) return nil } @@ -1246,9 +1241,7 @@ func (a *App) UpdateChannelLastViewedAt(channelIds []string, userId string) *mod for _, channelId := range channelIds { message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, "", "", userId, nil) message.Add("channel_id", channelId) - a.Go(func() { - a.Publish(message) - }) + a.Publish(message) } } @@ -1325,9 +1318,7 @@ func (a *App) ViewChannel(view *model.ChannelView, userId string, clearPushNotif if *a.Config().ServiceSettings.EnableChannelViewedMessages && model.IsValidId(view.ChannelId) { message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, "", "", userId, nil) message.Add("channel_id", view.ChannelId) - a.Go(func() { - a.Publish(message) - }) + a.Publish(message) } return times, nil diff --git a/app/command_expand_collapse.go b/app/command_expand_collapse.go index a8eb3bc1f..638490c6c 100644 --- a/app/command_expand_collapse.go +++ b/app/command_expand_collapse.go @@ -74,9 +74,7 @@ func (a *App) setCollapsePreference(args *model.CommandArgs, isCollapse bool) *m socketMessage := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCE_CHANGED, "", "", args.UserId, nil) socketMessage.Add("preference", pref.ToJson()) - a.Go(func() { - a.Publish(socketMessage) - }) + a.Publish(socketMessage) var rmsg string diff --git a/app/emoji.go b/app/emoji.go index 20d4bb44d..eebe59ccf 100644 --- a/app/emoji.go +++ b/app/emoji.go @@ -60,7 +60,6 @@ func (a *App) CreateEmoji(sessionUserId string, emoji *model.Emoji, multiPartIma } else { message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_EMOJI_ADDED, "", "", "", nil) message.Add("emoji", emoji.ToJson()) - a.Publish(message) return result.Data.(*model.Emoji), nil } diff --git a/app/post.go b/app/post.go index a541797fa..5067777ab 100644 --- a/app/post.go +++ b/app/post.go @@ -84,9 +84,7 @@ func (a *App) CreatePostAsUser(post *model.Post) (*model.Post, *model.AppError) if *a.Config().ServiceSettings.EnableChannelViewedMessages { message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_VIEWED, "", "", post.UserId, nil) message.Add("channel_id", post.ChannelId) - a.Go(func() { - a.Publish(message) - }) + a.Publish(message) } } @@ -314,10 +312,7 @@ func (a *App) SendEphemeralPost(userId string, post *model.Post) *model.Post { message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_EPHEMERAL_MESSAGE, "", post.ChannelId, userId, nil) message.Add("post", a.PostWithProxyAddedToImageURLs(post).ToJson()) - - a.Go(func() { - a.Publish(message) - }) + a.Publish(message) return post } @@ -424,10 +419,7 @@ func (a *App) PatchPost(postId string, patch *model.PostPatch) (*model.Post, *mo func (a *App) sendUpdatedPostEvent(post *model.Post) { message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POST_EDITED, "", post.ChannelId, "", nil) message.Add("post", a.PostWithProxyAddedToImageURLs(post).ToJson()) - - a.Go(func() { - a.Publish(message) - }) + a.Publish(message) } func (a *App) GetPostsPage(channelId string, page int, perPage int) (*model.PostList, *model.AppError) { @@ -567,10 +559,8 @@ func (a *App) DeletePost(postId string) (*model.Post, *model.AppError) { message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_POST_DELETED, "", post.ChannelId, "", nil) message.Add("post", a.PostWithProxyAddedToImageURLs(post).ToJson()) + a.Publish(message) - a.Go(func() { - a.Publish(message) - }) a.Go(func() { a.DeletePostFiles(post) }) diff --git a/app/preference.go b/app/preference.go index 9ca1f474c..eb41992da 100644 --- a/app/preference.go +++ b/app/preference.go @@ -55,9 +55,7 @@ func (a *App) UpdatePreferences(userId string, preferences model.Preferences) *m message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCES_CHANGED, "", "", userId, nil) message.Add("preferences", preferences.ToJson()) - a.Go(func() { - a.Publish(message) - }) + a.Publish(message) return nil } @@ -80,9 +78,7 @@ func (a *App) DeletePreferences(userId string, preferences model.Preferences) *m message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_PREFERENCES_DELETED, "", "", userId, nil) message.Add("preferences", preferences.ToJson()) - a.Go(func() { - a.Publish(message) - }) + a.Publish(message) return nil } diff --git a/app/status.go b/app/status.go index 1ef7aef0f..d677f9a23 100644 --- a/app/status.go +++ b/app/status.go @@ -221,9 +221,7 @@ func (a *App) BroadcastStatus(status *model.Status) { event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil) event.Add("status", status.Status) event.Add("user_id", status.UserId) - a.Go(func() { - a.Publish(event) - }) + a.Publish(event) } func (a *App) SetStatusOffline(userId string, manual bool) { @@ -247,9 +245,7 @@ func (a *App) SetStatusOffline(userId string, manual bool) { event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil) event.Add("status", model.STATUS_OFFLINE) event.Add("user_id", status.UserId) - a.Go(func() { - a.Publish(event) - }) + a.Publish(event) } func (a *App) SetStatusAwayIfNeeded(userId string, manual bool) { @@ -290,9 +286,7 @@ func (a *App) SetStatusAwayIfNeeded(userId string, manual bool) { event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil) event.Add("status", model.STATUS_AWAY) event.Add("user_id", status.UserId) - a.Go(func() { - a.Publish(event) - }) + a.Publish(event) } func (a *App) SetStatusDoNotDisturb(userId string) { @@ -318,9 +312,7 @@ func (a *App) SetStatusDoNotDisturb(userId string) { event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil) event.Add("status", model.STATUS_DND) event.Add("user_id", status.UserId) - a.Go(func() { - a.Publish(event) - }) + a.Publish(event) } func GetStatusFromCache(userId string) *model.Status { diff --git a/app/team.go b/app/team.go index 65b1934f9..239ce4369 100644 --- a/app/team.go +++ b/app/team.go @@ -139,9 +139,7 @@ func (a *App) sendTeamEvent(team *model.Team, event string) { message := model.NewWebSocketEvent(event, "", "", "", nil) message.Add("team", sanitizedTeam.ToJson()) - a.Go(func() { - a.Publish(message) - }) + a.Publish(message) } func (a *App) UpdateTeamMemberRoles(teamId string, userId string, newRoles string) (*model.TeamMember, *model.AppError) { @@ -178,10 +176,7 @@ func (a *App) UpdateTeamMemberRoles(teamId string, userId string, newRoles strin func (a *App) sendUpdatedMemberRoleEvent(userId string, member *model.TeamMember) { message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_MEMBERROLE_UPDATED, "", "", userId, nil) message.Add("member", member.ToJson()) - - a.Go(func() { - a.Publish(message) - }) + a.Publish(message) } func (a *App) AddUserToTeam(teamId string, userId string, userRequestorId string) (*model.Team, *model.AppError) { diff --git a/app/user.go b/app/user.go index f915f35cb..5790be21e 100644 --- a/app/user.go +++ b/app/user.go @@ -202,9 +202,7 @@ func (a *App) CreateUser(user *model.User) (*model.User, *model.AppError) { // This message goes to everyone, so the teamId, channelId and userId are irrelevant message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_NEW_USER, "", "", "", nil) message.Add("user_id", ruser.Id) - a.Go(func() { - a.Publish(message) - }) + a.Publish(message) return ruser, nil } @@ -832,7 +830,6 @@ func (a *App) SetProfileImageFromFile(userId string, file multipart.File) *model message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_UPDATED, "", "", "", nil) message.Add("user", user) - a.Publish(message) } @@ -1002,9 +999,7 @@ func (a *App) sendUpdatedUserEvent(user model.User, asAdmin bool) { message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_USER_UPDATED, "", "", "", nil) message.Add("user", user) - a.Go(func() { - a.Publish(message) - }) + a.Publish(message) } func (a *App) UpdateUser(user *model.User, sendNotifications bool) (*model.User, *model.AppError) { -- cgit v1.2.3-1-g7c22 From fbff94f3be1bf596f2b94f593687d3b162413de9 Mon Sep 17 00:00:00 2001 From: Jesse Hallam Date: Mon, 5 Mar 2018 07:18:22 -0500 Subject: MM-8604: emit config/license websocket events (#8371) --- app/app.go | 18 +++++++++++++++++- app/config.go | 15 +++++++++++++++ app/config_test.go | 10 ++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/app.go b/app/app.go index 26aed4c73..f5e5dd21e 100644 --- a/app/app.go +++ b/app/app.go @@ -131,8 +131,24 @@ func New(options ...Option) (outApp *App, outErr error) { app.configListenerId = app.AddConfigListener(func(_, _ *model.Config) { app.configOrLicenseListener() + + message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CONFIG_CHANGED, "", "", "", nil) + + message.Add("config", app.ClientConfigWithNoAccounts()) + app.Go(func() { + app.Publish(message) + }) + }) + app.licenseListenerId = app.AddLicenseListener(func() { + app.configOrLicenseListener() + + message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_LICENSE_CHANGED, "", "", "", nil) + message.Add("license", app.GetSanitizedClientLicense()) + app.Go(func() { + app.Publish(message) + }) + }) - app.licenseListenerId = app.AddLicenseListener(app.configOrLicenseListener) app.regenerateClientConfig() app.setDefaultRolesBasedOnConfig() diff --git a/app/config.go b/app/config.go index 35a0c9a3f..460d580d8 100644 --- a/app/config.go +++ b/app/config.go @@ -14,6 +14,7 @@ import ( "fmt" "net/url" "runtime/debug" + "strconv" "strings" l4g "github.com/alecthomas/log4go" @@ -34,6 +35,7 @@ func (a *App) UpdateConfig(f func(*model.Config)) { updated := old.Clone() f(updated) a.config.Store(updated) + a.InvokeConfigListeners(old, updated) } @@ -269,3 +271,16 @@ func (a *App) GetCookieDomain() string { func (a *App) GetSiteURL() string { return a.siteURL } + +// ClientConfigWithNoAccounts gets the configuration in a format suitable for sending to the client. +func (a *App) ClientConfigWithNoAccounts() map[string]string { + respCfg := map[string]string{} + for k, v := range a.ClientConfig() { + respCfg[k] = v + } + + // NoAccounts is not actually part of the configuration, but is expected by the client. + respCfg["NoAccounts"] = strconv.FormatBool(a.IsFirstUserAccount()) + + return respCfg +} diff --git a/app/config_test.go b/app/config_test.go index 5ee999f0f..051fa8fd8 100644 --- a/app/config_test.go +++ b/app/config_test.go @@ -63,3 +63,13 @@ func TestAsymmetricSigningKey(t *testing.T) { assert.NotNil(t, th.App.AsymmetricSigningKey()) assert.NotEmpty(t, th.App.ClientConfig()["AsymmetricSigningPublicKey"]) } + +func TestClientConfigWithNoAccounts(t *testing.T) { + th := Setup().InitBasic() + defer th.TearDown() + + config := th.App.ClientConfigWithNoAccounts() + if _, ok := config["NoAccounts"]; !ok { + t.Fatal("expected NoAccounts in returned config") + } +} -- cgit v1.2.3-1-g7c22 From 4a1802c039a0db2d97e8351c462963a99da857bf Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Mon, 5 Mar 2018 10:35:26 -0500 Subject: MM-9664 Add invalidation metrics for store caches (#8340) * Add invalidation metrics for store caches * Increment session invalidation metric * Fix tests --- app/admin.go | 10 +++++----- app/session.go | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/admin.go b/app/admin.go index 154fa8899..22928390e 100644 --- a/app/admin.go +++ b/app/admin.go @@ -15,7 +15,6 @@ import ( l4g "github.com/alecthomas/log4go" "github.com/mattermost/mattermost-server/model" - "github.com/mattermost/mattermost-server/store/sqlstore" "github.com/mattermost/mattermost-server/utils" ) @@ -141,10 +140,11 @@ func (a *App) InvalidateAllCachesSkipSend() { l4g.Info(utils.T("api.context.invalidate_all_caches")) a.sessionCache.Purge() ClearStatusCache() - sqlstore.ClearChannelCaches() - sqlstore.ClearUserCaches() - sqlstore.ClearPostCaches() - sqlstore.ClearWebhookCaches() + a.Srv.Store.Channel().ClearCaches() + a.Srv.Store.User().ClearCaches() + a.Srv.Store.Post().ClearCaches() + a.Srv.Store.FileInfo().ClearCaches() + a.Srv.Store.Webhook().ClearCaches() a.LoadLicense() } diff --git a/app/session.go b/app/session.go index 459618439..88f52477f 100644 --- a/app/session.go +++ b/app/session.go @@ -138,6 +138,9 @@ func (a *App) ClearSessionCacheForUserSkipClusterSend(userId string) { session := ts.(*model.Session) if session.UserId == userId { a.sessionCache.Remove(key) + if a.Metrics != nil { + a.Metrics.IncrementMemCacheInvalidationCounterSession() + } } } } -- cgit v1.2.3-1-g7c22 From 09713ff4eadd3d706df45cb69f096b66c5b283fd Mon Sep 17 00:00:00 2001 From: Philippe GRANET Date: Wed, 7 Mar 2018 14:00:35 +0100 Subject: Add addedUser IDs to render correctly in client based on teammate name display setting (#8400) See PLT-7776 on mattermost-webapp: https://github.com/mattermost/mattermost-webapp/pull/353 --- app/channel.go | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'app') diff --git a/app/channel.go b/app/channel.go index 131e242fb..edece8c98 100644 --- a/app/channel.go +++ b/app/channel.go @@ -1092,7 +1092,9 @@ func (a *App) PostAddToChannelMessage(user *model.User, addedUser *model.User, c UserId: user.Id, RootId: postRootId, Props: model.StringInterface{ + "userId": user.Id, "username": user.Username, + "addedUserId": addedUser.Id, "addedUsername": addedUser.Username, }, } @@ -1112,7 +1114,9 @@ func (a *App) postAddToTeamMessage(user *model.User, addedUser *model.User, chan UserId: user.Id, RootId: postRootId, Props: model.StringInterface{ + "userId": user.Id, "username": user.Username, + "addedUserId": addedUser.Id, "addedUsername": addedUser.Username, }, } @@ -1131,6 +1135,7 @@ func (a *App) postRemoveFromChannelMessage(removerUserId string, removedUser *mo Type: model.POST_REMOVE_FROM_CHANNEL, UserId: removerUserId, Props: model.StringInterface{ + "removedUserId": removedUser.Id, "removedUsername": removedUser.Username, }, } -- cgit v1.2.3-1-g7c22 From d448a6bef30339a63b7c118b8b2deb44cdb79d8e Mon Sep 17 00:00:00 2001 From: Jonathan Date: Wed, 7 Mar 2018 10:54:51 -0500 Subject: XYZ-87: GlobalRelay DM Exports do not Include Channel Name (#8275) * Adding ChannelMemberHistory table records when DM channels are created. This ensures that both participants in a DM are shown in compliance export, even if only one of them typed anything * Direct/Group Message channels now get pretty display names for the purpose of compliance exports * Fixed string formatting in t.Fatal calls * Changed uses of ChannelMemberHistory over to ChannelMemberHistoryResult in tests. This should have been done as a part of the work in XYZ-110, but seems to have been missed in this branch for some reason --- app/channel.go | 19 ++++++++++++++- app/channel_test.go | 69 +++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 80 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/channel.go b/app/channel.go index edece8c98..76147a508 100644 --- a/app/channel.go +++ b/app/channel.go @@ -225,6 +225,14 @@ func (a *App) createDirectChannel(userId string, otherUserId string) (*model.Cha } } else { channel := result.Data.(*model.Channel) + + if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(userId, channel.Id, model.GetMillis()); result.Err != nil { + l4g.Warn("Failed to update ChannelMemberHistory table %v", result.Err) + } + if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(otherUserId, channel.Id, model.GetMillis()); result.Err != nil { + l4g.Warn("Failed to update ChannelMemberHistory table %v", result.Err) + } + return channel, nil } } @@ -1426,7 +1434,16 @@ func (a *App) GetDirectChannel(userId1, userId2 string) (*model.Channel, *model. } a.InvalidateCacheForUser(userId1) a.InvalidateCacheForUser(userId2) - return result.Data.(*model.Channel), nil + + channel := result.Data.(*model.Channel) + if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(userId1, channel.Id, model.GetMillis()); result.Err != nil { + l4g.Warn("Failed to update ChannelMemberHistory table %v", result.Err) + } + if result := <-a.Srv.Store.ChannelMemberHistory().LogJoinEvent(userId2, channel.Id, model.GetMillis()); result.Err != nil { + l4g.Warn("Failed to update ChannelMemberHistory table %v", result.Err) + } + + return channel, nil } else if result.Err != nil { return nil, model.NewAppError("GetOrCreateDMChannel", "web.incoming_webhook.channel.app_error", nil, "err="+result.Err.Message, result.Err.StatusCode) } diff --git a/app/channel_test.go b/app/channel_test.go index e4a0e4320..69efaeca7 100644 --- a/app/channel_test.go +++ b/app/channel_test.go @@ -110,7 +110,7 @@ func TestMoveChannel(t *testing.T) { } } -func TestJoinDefaultChannelsTownSquare(t *testing.T) { +func TestJoinDefaultChannelsCreatesChannelMemberHistoryRecordTownSquare(t *testing.T) { th := Setup().InitBasic() defer th.TearDown() @@ -136,7 +136,7 @@ func TestJoinDefaultChannelsTownSquare(t *testing.T) { assert.True(t, found) } -func TestJoinDefaultChannelsOffTopic(t *testing.T) { +func TestJoinDefaultChannelsCreatesChannelMemberHistoryRecordOffTopic(t *testing.T) { th := Setup().InitBasic() defer th.TearDown() @@ -162,7 +162,7 @@ func TestJoinDefaultChannelsOffTopic(t *testing.T) { assert.True(t, found) } -func TestCreateChannelPublic(t *testing.T) { +func TestCreateChannelPublicCreatesChannelMemberHistoryRecord(t *testing.T) { th := Setup().InitBasic() defer th.TearDown() @@ -176,7 +176,7 @@ func TestCreateChannelPublic(t *testing.T) { assert.Equal(t, publicChannel.Id, histories[0].ChannelId) } -func TestCreateChannelPrivate(t *testing.T) { +func TestCreateChannelPrivateCreatesChannelMemberHistoryRecord(t *testing.T) { th := Setup().InitBasic() defer th.TearDown() @@ -205,7 +205,7 @@ func TestUpdateChannelPrivacy(t *testing.T) { } } -func TestCreateGroupChannel(t *testing.T) { +func TestCreateGroupChannelCreatesChannelMemberHistoryRecord(t *testing.T) { th := Setup().InitBasic() defer th.TearDown() @@ -233,7 +233,62 @@ func TestCreateGroupChannel(t *testing.T) { } } -func TestAddUserToChannel(t *testing.T) { +func TestCreateDirectChannelCreatesChannelMemberHistoryRecord(t *testing.T) { + th := Setup().InitBasic() + defer th.TearDown() + + user1 := th.CreateUser() + user2 := th.CreateUser() + + if channel, err := th.App.CreateDirectChannel(user1.Id, user2.Id); err != nil { + t.Fatal("Failed to create direct channel. Error: " + err.Message) + } else { + // there should be a ChannelMemberHistory record for both users + histories := store.Must(th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, channel.Id)).([]*model.ChannelMemberHistoryResult) + assert.Len(t, histories, 2) + + historyId0 := histories[0].UserId + historyId1 := histories[1].UserId + switch historyId0 { + case user1.Id: + assert.Equal(t, user2.Id, historyId1) + case user2.Id: + assert.Equal(t, user1.Id, historyId1) + default: + t.Fatal("Unexpected user id " + historyId0 + " in ChannelMemberHistory table") + } + } +} + +func TestGetDirectChannelCreatesChannelMemberHistoryRecord(t *testing.T) { + th := Setup().InitBasic() + defer th.TearDown() + + user1 := th.CreateUser() + user2 := th.CreateUser() + + // this function call implicitly creates a direct channel between the two users if one doesn't already exist + if channel, err := th.App.GetDirectChannel(user1.Id, user2.Id); err != nil { + t.Fatal("Failed to create direct channel. Error: " + err.Message) + } else { + // there should be a ChannelMemberHistory record for both users + histories := store.Must(th.App.Srv.Store.ChannelMemberHistory().GetUsersInChannelDuring(model.GetMillis()-100, model.GetMillis()+100, channel.Id)).([]*model.ChannelMemberHistoryResult) + assert.Len(t, histories, 2) + + historyId0 := histories[0].UserId + historyId1 := histories[1].UserId + switch historyId0 { + case user1.Id: + assert.Equal(t, user2.Id, historyId1) + case user2.Id: + assert.Equal(t, user1.Id, historyId1) + default: + t.Fatal("Unexpected user id " + historyId0 + " in ChannelMemberHistory table") + } + } +} + +func TestAddUserToChannelCreatesChannelMemberHistoryRecord(t *testing.T) { th := Setup().InitBasic() defer th.TearDown() @@ -263,7 +318,7 @@ func TestAddUserToChannel(t *testing.T) { assert.Equal(t, groupUserIds, channelMemberHistoryUserIds) } -func TestRemoveUserFromChannel(t *testing.T) { +func TestRemoveUserFromChannelUpdatesChannelMemberHistoryRecord(t *testing.T) { th := Setup().InitBasic() defer th.TearDown() -- cgit v1.2.3-1-g7c22 From e8943936c51450540a4f2e8e7a2f3a2af90d14db Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 7 Mar 2018 12:36:40 -0600 Subject: general cleanup (#8387) --- app/apptestlib.go | 8 -------- app/authorization.go | 12 ------------ app/auto_constants.go | 22 +++++++++------------- app/auto_posts.go | 15 --------------- app/channel.go | 4 ++-- app/server.go | 47 ----------------------------------------------- app/slackimport.go | 12 +++++------- app/user.go | 1 - 8 files changed, 16 insertions(+), 105 deletions(-) (limited to 'app') diff --git a/app/apptestlib.go b/app/apptestlib.go index c7846c9b5..9e5bfc637 100644 --- a/app/apptestlib.go +++ b/app/apptestlib.go @@ -135,10 +135,6 @@ func (me *TestHelper) InitBasic() *TestHelper { return me } -func (me *TestHelper) MakeUsername() string { - return "un_" + model.NewId() -} - func (me *TestHelper) MakeEmail() string { return "success_" + model.NewId() + "@simulator.amazonses.com" } @@ -191,10 +187,6 @@ func (me *TestHelper) CreateChannel(team *model.Team) *model.Channel { return me.createChannel(team, model.CHANNEL_OPEN) } -func (me *TestHelper) CreatePrivateChannel(team *model.Team) *model.Channel { - return me.createChannel(team, model.CHANNEL_PRIVATE) -} - func (me *TestHelper) createChannel(team *model.Team, channelType string) *model.Channel { id := model.NewId() diff --git a/app/authorization.go b/app/authorization.go index 3a64bb717..4231cac77 100644 --- a/app/authorization.go +++ b/app/authorization.go @@ -181,18 +181,6 @@ func (a *App) HasPermissionToChannelByPost(askingUserId string, postId string, p return a.HasPermissionTo(askingUserId, permission) } -func (a *App) HasPermissionToUser(askingUserId string, userId string) bool { - if askingUserId == userId { - return true - } - - if a.HasPermissionTo(askingUserId, model.PERMISSION_EDIT_OTHER_USERS) { - return true - } - - return false -} - func (a *App) CheckIfRolesGrantPermission(roles []string, permissionId string) bool { for _, roleId := range roles { if role := a.Role(roleId); role == nil { diff --git a/app/auto_constants.go b/app/auto_constants.go index c52eb6243..520d4e363 100644 --- a/app/auto_constants.go +++ b/app/auto_constants.go @@ -9,16 +9,15 @@ import ( ) const ( - USER_PASSWORD = "passwd" - CHANNEL_TYPE = model.CHANNEL_OPEN - FUZZ_USER_EMAIL_PREFIX_LEN = 10 - BTEST_TEAM_DISPLAY_NAME = "TestTeam" - BTEST_TEAM_NAME = "z-z-testdomaina" - BTEST_TEAM_EMAIL = "test@nowhere.com" - BTEST_TEAM_TYPE = model.TEAM_OPEN - BTEST_USER_NAME = "Mr. Testing Tester" - BTEST_USER_EMAIL = "success+ttester@simulator.amazonses.com" - BTEST_USER_PASSWORD = "passwd" + USER_PASSWORD = "passwd" + CHANNEL_TYPE = model.CHANNEL_OPEN + BTEST_TEAM_DISPLAY_NAME = "TestTeam" + BTEST_TEAM_NAME = "z-z-testdomaina" + BTEST_TEAM_EMAIL = "test@nowhere.com" + BTEST_TEAM_TYPE = model.TEAM_OPEN + BTEST_USER_NAME = "Mr. Testing Tester" + BTEST_USER_EMAIL = "success+ttester@simulator.amazonses.com" + BTEST_USER_PASSWORD = "passwd" ) var ( @@ -29,8 +28,5 @@ var ( USER_EMAIL_LEN = utils.Range{Begin: 15, End: 30} CHANNEL_DISPLAY_NAME_LEN = utils.Range{Begin: 10, End: 20} CHANNEL_NAME_LEN = utils.Range{Begin: 5, End: 20} - POST_MESSAGE_LEN = utils.Range{Begin: 100, End: 400} - POST_HASHTAGS_NUM = utils.Range{Begin: 5, End: 10} - POST_MENTIONS_NUM = utils.Range{Begin: 0, End: 3} TEST_IMAGE_FILENAMES = []string{"test.png", "testjpg.jpg", "testgif.gif"} ) diff --git a/app/auto_posts.go b/app/auto_posts.go index 6d1e352e5..379c74ab7 100644 --- a/app/auto_posts.go +++ b/app/auto_posts.go @@ -90,18 +90,3 @@ func (cfg *AutoPostCreator) CreateRandomPost() (*model.Post, bool) { } return result.Data.(*model.Post), true } - -func (cfg *AutoPostCreator) CreateTestPosts(rangePosts utils.Range) ([]*model.Post, bool) { - numPosts := utils.RandIntFromRange(rangePosts) - posts := make([]*model.Post, numPosts) - - for i := 0; i < numPosts; i++ { - var err bool - posts[i], err = cfg.CreateRandomPost() - if !err { - return posts, false - } - } - - return posts, true -} diff --git a/app/channel.go b/app/channel.go index 76147a508..4e294abbb 100644 --- a/app/channel.go +++ b/app/channel.go @@ -377,7 +377,7 @@ func (a *App) postChannelPrivacyMessage(user *model.User, channel *model.Channel })[channel.Type] post := &model.Post{ ChannelId: channel.Id, - Message: fmt.Sprintf(utils.T("api.channel.change_channel_privacy." + privacy)), + Message: utils.T("api.channel.change_channel_privacy." + privacy), Type: model.POST_CHANGE_CHANNEL_PRIVACY, UserId: user.Id, Props: model.StringInterface{ @@ -1062,7 +1062,7 @@ func (a *App) LeaveChannel(channelId string, userId string) *model.AppError { return err } - if channel.Name == model.DEFAULT_CHANNEL && *a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages == false { + if channel.Name == model.DEFAULT_CHANNEL && !*a.Config().ServiceSettings.ExperimentalEnableDefaultChannelLeaveJoinMessages { return nil } diff --git a/app/server.go b/app/server.go index 93804a372..0c6c25ba5 100644 --- a/app/server.go +++ b/app/server.go @@ -84,28 +84,6 @@ func (cw *CorsWrapper) ServeHTTP(w http.ResponseWriter, r *http.Request) { const TIME_TO_WAIT_FOR_CONNECTIONS_TO_CLOSE_ON_SERVER_SHUTDOWN = time.Second -type VaryBy struct { - useIP bool - useAuth bool -} - -func (m *VaryBy) Key(r *http.Request) string { - key := "" - - if m.useAuth { - token, tokenLocation := ParseAuthTokenFromRequest(r) - if tokenLocation != TokenLocationNotFound { - key += token - } else if m.useIP { // If we don't find an authentication token and IP based is enabled, fall back to IP - key += utils.GetIpAddress(r) - } - } else if m.useIP { // Only if Auth based is not enabed do we use a plain IP based - key = utils.GetIpAddress(r) - } - - return key -} - func redirectHTTPToHTTPS(w http.ResponseWriter, r *http.Request) { if r.Host == "" { http.Error(w, "Not Found", http.StatusNotFound) @@ -223,31 +201,6 @@ func (a *App) StartServer() error { return nil } -type tcpKeepAliveListener struct { - *net.TCPListener -} - -func (ln tcpKeepAliveListener) Accept() (c net.Conn, err error) { - tc, err := ln.AcceptTCP() - if err != nil { - return - } - tc.SetKeepAlive(true) - tc.SetKeepAlivePeriod(3 * time.Minute) - return tc, nil -} - -func (a *App) Listen(addr string) (net.Listener, error) { - if addr == "" { - addr = ":http" - } - ln, err := net.Listen("tcp", addr) - if err != nil { - return nil, err - } - return tcpKeepAliveListener{ln.(*net.TCPListener)}, nil -} - func (a *App) StopServer() { if a.Srv.Server != nil { ctx, cancel := context.WithTimeout(context.Background(), TIME_TO_WAIT_FOR_CONNECTIONS_TO_CLOSE_ON_SERVER_SHUTDOWN) diff --git a/app/slackimport.go b/app/slackimport.go index 9d1b4cf9c..ed522671a 100644 --- a/app/slackimport.go +++ b/app/slackimport.go @@ -109,13 +109,11 @@ func SlackParseUsers(data io.Reader) ([]SlackUser, error) { decoder := json.NewDecoder(data) var users []SlackUser - if err := decoder.Decode(&users); err != nil { - // This actually returns errors that are ignored. - // In this case it is erroring because of a null that Slack - // introduced. So we just return the users here. - return users, err - } - return users, nil + err := decoder.Decode(&users) + // This actually returns errors that are ignored. + // In this case it is erroring because of a null that Slack + // introduced. So we just return the users here. + return users, err } func SlackParsePosts(data io.Reader) ([]SlackPost, error) { diff --git a/app/user.go b/app/user.go index 5790be21e..c303cbc68 100644 --- a/app/user.go +++ b/app/user.go @@ -34,7 +34,6 @@ const ( TOKEN_TYPE_PASSWORD_RECOVERY = "password_recovery" TOKEN_TYPE_VERIFY_EMAIL = "verify_email" PASSWORD_RECOVER_EXPIRY_TIME = 1000 * 60 * 60 // 1 hour - VERIFY_EMAIL_EXPIRY_TIME = 1000 * 60 * 60 // 1 hour IMAGE_PROFILE_PIXEL_DIMENSION = 128 ) -- cgit v1.2.3-1-g7c22 From 302dae5bb982aad14324a4df61a018557f3dd24e Mon Sep 17 00:00:00 2001 From: Stephen Kiers Date: Fri, 9 Mar 2018 05:48:30 -0700 Subject: MM-9274- Sort Users in Channel by status (#8181) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * sort by lastActivity * added status ordering to Users * sort offline before dnd * remove data not needed * added seperate call for when order=‘status’ is on GetUser request * remove PrintLn * styling fix * remove mistake * mistake 2 * better comment * explicit if statemnt * writing tests * removed manually added mocks * generated mock * ICU-668 Added unit tests * style fix * sort by lastActivity * added status ordering to Users * sort offline before dnd * remove data not needed * added seperate call for when order=‘status’ is on GetUser request * remove PrintLn * styling fix * remove mistake * mistake 2 * better comment * explicit if statemnt * writing tests * removed manually added mocks * generated mock * ICU-668 Added unit tests * style fix * reverse dnd and offline * Fixed app.SaveStatusAndBroadcast * Fixed incorrect merge * Fixing incorrect merge again --- app/apptestlib.go | 16 +++++++ app/server_test.go | 2 +- app/status.go | 32 +++++-------- app/status_test.go | 40 +++++++++++++++++ app/user.go | 17 +++++++ app/user_test.go | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 213 insertions(+), 23 deletions(-) create mode 100644 app/status_test.go (limited to 'app') diff --git a/app/apptestlib.go b/app/apptestlib.go index 9e5bfc637..01f5b0102 100644 --- a/app/apptestlib.go +++ b/app/apptestlib.go @@ -245,6 +245,22 @@ func (me *TestHelper) LinkUserToTeam(user *model.User, team *model.Team) { utils.EnableDebugLogForTest() } +func (me *TestHelper) AddUserToChannel(user *model.User, channel *model.Channel) *model.ChannelMember { + utils.DisableDebugLogForTest() + + member, err := me.App.AddUserToChannel(user, channel) + if err != nil { + l4g.Error(err.Error()) + l4g.Close() + time.Sleep(time.Second) + panic(err) + } + + utils.EnableDebugLogForTest() + + return member +} + func (me *TestHelper) TearDown() { me.App.Shutdown() os.Remove(me.tempConfigPath) diff --git a/app/server_test.go b/app/server_test.go index de358b976..94771a44e 100644 --- a/app/server_test.go +++ b/app/server_test.go @@ -26,7 +26,7 @@ func TestStartServerRateLimiterCriticalError(t *testing.T) { // Attempt to use Rate Limiter with an invalid config a.UpdateConfig(func(cfg *model.Config) { - *cfg.RateLimitSettings.Enable = true + *cfg.RateLimitSettings.Enable = true *cfg.RateLimitSettings.MaxBurst = -100 }) diff --git a/app/status.go b/app/status.go index d677f9a23..c8bff0d1a 100644 --- a/app/status.go +++ b/app/status.go @@ -236,16 +236,7 @@ func (a *App) SetStatusOffline(userId string, manual bool) { status = &model.Status{UserId: userId, Status: model.STATUS_OFFLINE, Manual: manual, LastActivityAt: model.GetMillis(), ActiveChannel: ""} - a.AddStatusCache(status) - - if result := <-a.Srv.Store.Status().SaveOrUpdate(status); result.Err != nil { - l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err) - } - - event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil) - event.Add("status", model.STATUS_OFFLINE) - event.Add("user_id", status.UserId) - a.Publish(event) + a.SaveAndBroadcastStatus(status) } func (a *App) SetStatusAwayIfNeeded(userId string, manual bool) { @@ -277,16 +268,7 @@ func (a *App) SetStatusAwayIfNeeded(userId string, manual bool) { status.Manual = manual status.ActiveChannel = "" - a.AddStatusCache(status) - - if result := <-a.Srv.Store.Status().SaveOrUpdate(status); result.Err != nil { - l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err) - } - - event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil) - event.Add("status", model.STATUS_AWAY) - event.Add("user_id", status.UserId) - a.Publish(event) + a.SaveAndBroadcastStatus(status) } func (a *App) SetStatusDoNotDisturb(userId string) { @@ -303,16 +285,22 @@ func (a *App) SetStatusDoNotDisturb(userId string) { status.Status = model.STATUS_DND status.Manual = true + a.SaveAndBroadcastStatus(status) +} + +func (a *App) SaveAndBroadcastStatus(status *model.Status) *model.AppError { a.AddStatusCache(status) if result := <-a.Srv.Store.Status().SaveOrUpdate(status); result.Err != nil { - l4g.Error(utils.T("api.status.save_status.error"), userId, result.Err) + l4g.Error(utils.T("api.status.save_status.error"), status.UserId, result.Err) } event := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_STATUS_CHANGE, "", "", status.UserId, nil) - event.Add("status", model.STATUS_DND) + event.Add("status", status.Status) event.Add("user_id", status.UserId) a.Publish(event) + + return nil } func GetStatusFromCache(userId string) *model.Status { diff --git a/app/status_test.go b/app/status_test.go new file mode 100644 index 000000000..bf5736a48 --- /dev/null +++ b/app/status_test.go @@ -0,0 +1,40 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package app + +import ( + "testing" + + "github.com/mattermost/mattermost-server/model" +) + +func TestSaveStatus(t *testing.T) { + th := Setup().InitBasic() + defer th.TearDown() + + user := th.BasicUser + + for _, statusString := range []string{ + model.STATUS_ONLINE, + model.STATUS_AWAY, + model.STATUS_DND, + model.STATUS_OFFLINE, + } { + t.Run(statusString, func(t *testing.T) { + status := &model.Status{ + UserId: user.Id, + Status: statusString, + } + + th.App.SaveAndBroadcastStatus(status) + + after, err := th.App.GetStatus(user.Id) + if err != nil { + t.Fatalf("failed to get status after save: %v", err) + } else if after.Status != statusString { + t.Fatalf("failed to save status, got %v, expected %v", after.Status, statusString) + } + }) + } +} diff --git a/app/user.go b/app/user.go index c303cbc68..dbce296d2 100644 --- a/app/user.go +++ b/app/user.go @@ -505,6 +505,14 @@ func (a *App) GetUsersInChannel(channelId string, offset int, limit int) ([]*mod } } +func (a *App) GetUsersInChannelByStatus(channelId string, offset int, limit int) ([]*model.User, *model.AppError) { + if result := <-a.Srv.Store.User().GetProfilesInChannelByStatus(channelId, offset, limit); result.Err != nil { + return nil, result.Err + } else { + return result.Data.([]*model.User), nil + } +} + func (a *App) GetUsersInChannelMap(channelId string, offset int, limit int, asAdmin bool) (map[string]*model.User, *model.AppError) { users, err := a.GetUsersInChannel(channelId, offset, limit) if err != nil { @@ -530,6 +538,15 @@ func (a *App) GetUsersInChannelPage(channelId string, page int, perPage int, asA return a.sanitizeProfiles(users, asAdmin), nil } +func (a *App) GetUsersInChannelPageByStatus(channelId string, page int, perPage int, asAdmin bool) ([]*model.User, *model.AppError) { + users, err := a.GetUsersInChannelByStatus(channelId, page*perPage, perPage) + if err != nil { + return nil, err + } + + return a.sanitizeProfiles(users, asAdmin), nil +} + func (a *App) GetUsersNotInChannel(teamId string, channelId string, offset int, limit int) ([]*model.User, *model.AppError) { if result := <-a.Srv.Store.User().GetProfilesNotInChannel(teamId, channelId, offset, limit); result.Err != nil { return nil, result.Err diff --git a/app/user_test.go b/app/user_test.go index 38ff286b3..94052da61 100644 --- a/app/user_test.go +++ b/app/user_test.go @@ -299,3 +299,132 @@ func createGitlabUser(t *testing.T, a *App, email string, username string) (*mod return user, gitlabUserObj } + +func TestGetUsersByStatus(t *testing.T) { + th := Setup() + defer th.TearDown() + + team := th.CreateTeam() + channel, err := th.App.CreateChannel(&model.Channel{ + DisplayName: "dn_" + model.NewId(), + Name: "name_" + model.NewId(), + Type: model.CHANNEL_OPEN, + TeamId: team.Id, + CreatorId: model.NewId(), + }, false) + if err != nil { + t.Fatalf("failed to create channel: %v", err) + } + + createUserWithStatus := func(username string, status string) *model.User { + id := model.NewId() + + user, err := th.App.CreateUser(&model.User{ + Email: "success+" + id + "@simulator.amazonses.com", + Username: "un_" + username + "_" + id, + Nickname: "nn_" + id, + Password: "Password1", + }) + if err != nil { + t.Fatalf("failed to create user: %v", err) + } + + th.LinkUserToTeam(user, team) + th.AddUserToChannel(user, channel) + + th.App.SaveAndBroadcastStatus(&model.Status{ + UserId: user.Id, + Status: status, + Manual: true, + }) + + return user + } + + // Creating these out of order in case that affects results + awayUser1 := createUserWithStatus("away1", model.STATUS_AWAY) + awayUser2 := createUserWithStatus("away2", model.STATUS_AWAY) + dndUser1 := createUserWithStatus("dnd1", model.STATUS_DND) + dndUser2 := createUserWithStatus("dnd2", model.STATUS_DND) + offlineUser1 := createUserWithStatus("offline1", model.STATUS_OFFLINE) + offlineUser2 := createUserWithStatus("offline2", model.STATUS_OFFLINE) + onlineUser1 := createUserWithStatus("online1", model.STATUS_ONLINE) + onlineUser2 := createUserWithStatus("online2", model.STATUS_ONLINE) + + t.Run("sorting by status then alphabetical", func(t *testing.T) { + usersByStatus, err := th.App.GetUsersInChannelPageByStatus(channel.Id, 0, 8, true) + if err != nil { + t.Fatal(err) + } + + expectedUsersByStatus := []*model.User{ + onlineUser1, + onlineUser2, + awayUser1, + awayUser2, + dndUser1, + dndUser2, + offlineUser1, + offlineUser2, + } + + if len(usersByStatus) != len(expectedUsersByStatus) { + t.Fatalf("received only %v users, expected %v", len(usersByStatus), len(expectedUsersByStatus)) + } + + for i := range usersByStatus { + if usersByStatus[i].Id != expectedUsersByStatus[i].Id { + t.Fatalf("received user %v at index %v, expected %v", usersByStatus[i].Username, i, expectedUsersByStatus[i].Username) + } + } + }) + + t.Run("paging", func(t *testing.T) { + usersByStatus, err := th.App.GetUsersInChannelPageByStatus(channel.Id, 0, 3, true) + if err != nil { + t.Fatal(err) + } + + if len(usersByStatus) != 3 { + t.Fatal("received too many users") + } + + if usersByStatus[0].Id != onlineUser1.Id && usersByStatus[1].Id != onlineUser2.Id { + t.Fatal("expected to receive online users first") + } + + if usersByStatus[2].Id != awayUser1.Id { + t.Fatal("expected to receive away users second") + } + + usersByStatus, err = th.App.GetUsersInChannelPageByStatus(channel.Id, 1, 3, true) + if err != nil { + t.Fatal(err) + } + + if usersByStatus[0].Id != awayUser2.Id { + t.Fatal("expected to receive away users second") + } + + if usersByStatus[1].Id != dndUser1.Id && usersByStatus[2].Id != dndUser2.Id { + t.Fatal("expected to receive dnd users third") + } + + usersByStatus, err = th.App.GetUsersInChannelPageByStatus(channel.Id, 1, 4, true) + if err != nil { + t.Fatal(err) + } + + if len(usersByStatus) != 4 { + t.Fatal("received too many users") + } + + if usersByStatus[0].Id != dndUser1.Id && usersByStatus[1].Id != dndUser2.Id { + t.Fatal("expected to receive dnd users third") + } + + if usersByStatus[2].Id != offlineUser1.Id && usersByStatus[3].Id != offlineUser2.Id { + t.Fatal("expected to receive offline users last") + } + }) +} -- cgit v1.2.3-1-g7c22 From 8ad99b4b1fbc901a69886d9a12ac016d8396b32f Mon Sep 17 00:00:00 2001 From: Joram Wilander Date: Fri, 9 Mar 2018 08:06:31 -0500 Subject: Remove query to update channel extra_update_at field on user activation/deactivation (#8415) --- app/user.go | 4 ---- 1 file changed, 4 deletions(-) (limited to 'app') diff --git a/app/user.go b/app/user.go index dbce296d2..7a6dc0b49 100644 --- a/app/user.go +++ b/app/user.go @@ -914,10 +914,6 @@ func (a *App) UpdateActive(user *model.User, active bool) (*model.User, *model.A } } - if extra := <-a.Srv.Store.Channel().ExtraUpdateByUser(user.Id, model.GetMillis()); extra.Err != nil { - return nil, extra.Err - } - ruser := result.Data.([2]*model.User)[0] options := a.Config().GetSanitizeOptions() options["passwordupdate"] = false -- cgit v1.2.3-1-g7c22 From cb1b8fc3337f2e7611b342d077573312a62d5619 Mon Sep 17 00:00:00 2001 From: Carlos Tadeu Panato Junior Date: Mon, 12 Mar 2018 12:40:11 +0100 Subject: [MM-9725] Slack compatibility code in webhooks captures incorrect text (#8428) --- app/webhook.go | 2 +- app/webhook_test.go | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/webhook.go b/app/webhook.go index f3777ab48..abfc388b5 100644 --- a/app/webhook.go +++ b/app/webhook.go @@ -225,7 +225,7 @@ func SplitWebhookPost(post *model.Post) ([]*model.Post, *model.AppError) { func (a *App) CreateWebhookPost(userId string, channel *model.Channel, text, overrideUsername, overrideIconUrl string, props model.StringInterface, postType string, postRootId string) (*model.Post, *model.AppError) { // parse links into Markdown format - linkWithTextRegex := regexp.MustCompile(`<([^<\|]+)\|([^>]+)>`) + linkWithTextRegex := regexp.MustCompile(`<([^\n<\|>]+)\|([^\n>]+)>`) text = linkWithTextRegex.ReplaceAllString(text, "[${2}](${1})") post := &model.Post{UserId: userId, ChannelId: channel.Id, Message: text, Type: postType, RootId: postRootId} diff --git a/app/webhook_test.go b/app/webhook_test.go index 850e74efc..4d2bc58fa 100644 --- a/app/webhook_test.go +++ b/app/webhook_test.go @@ -317,6 +317,64 @@ func TestCreateWebhookPost(t *testing.T) { if err == nil { t.Fatal("should have failed - bad post type") } + + expectedText := "`<>|<>|`" + post, err = th.App.CreateWebhookPost(hook.UserId, th.BasicChannel, expectedText, "user", "http://iconurl", model.StringInterface{ + "attachments": []*model.SlackAttachment{ + { + Text: "text", + }, + }, + "webhook_display_name": hook.DisplayName, + }, model.POST_SLACK_ATTACHMENT, "") + if err != nil { + t.Fatal(err.Error()) + } + assert.Equal(t, expectedText, post.Message) + + expectedText = "< | \n|\n>" + post, err = th.App.CreateWebhookPost(hook.UserId, th.BasicChannel, expectedText, "user", "http://iconurl", model.StringInterface{ + "attachments": []*model.SlackAttachment{ + { + Text: "text", + }, + }, + "webhook_display_name": hook.DisplayName, + }, model.POST_SLACK_ATTACHMENT, "") + if err != nil { + t.Fatal(err.Error()) + } + assert.Equal(t, expectedText, post.Message) + + expectedText = `commit bc95839e4a430ace453e8b209a3723c000c1729a +Author: foo +Date: Thu Mar 1 19:46:54 2018 +0300 + + commit message 2 + + test | 1 + + 1 file changed, 1 insertion(+) + +commit 5df78b7139b543997838071cd912e375d8bd69b2 +Author: foo +Date: Thu Mar 1 19:46:48 2018 +0300 + + commit message 1 + + test | 3 +++ + 1 file changed, 3 insertions(+)` + post, err = th.App.CreateWebhookPost(hook.UserId, th.BasicChannel, expectedText, "user", "http://iconurl", model.StringInterface{ + "attachments": []*model.SlackAttachment{ + { + Text: "text", + }, + }, + "webhook_display_name": hook.DisplayName, + }, model.POST_SLACK_ATTACHMENT, "") + if err != nil { + t.Fatal(err.Error()) + } + assert.Equal(t, expectedText, post.Message) } func TestSplitWebhookPost(t *testing.T) { -- cgit v1.2.3-1-g7c22 From 4e26594fcb03c378222d2316a004c291d48dd6c7 Mon Sep 17 00:00:00 2001 From: Harrison Healey Date: Mon, 12 Mar 2018 10:21:20 -0400 Subject: Removed mssola/user_agent library (#8417) * Removed mssola/user_agent library * Changed user agent tests to use t.Run --- app/login.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/login.go b/app/login.go index e01566bcd..43b022749 100644 --- a/app/login.go +++ b/app/login.go @@ -9,8 +9,8 @@ import ( "strings" "time" + "github.com/avct/uasurfer" "github.com/mattermost/mattermost-server/model" - "github.com/mssola/user_agent" ) func (a *App) AuthenticateUserForLogin(id, loginId, password, mfaToken, deviceId string, ldapOnly bool) (*model.User, *model.AppError) { @@ -71,19 +71,19 @@ func (a *App) DoLogin(w http.ResponseWriter, r *http.Request, user *model.User, session.SetExpireInDays(*a.Config().ServiceSettings.SessionLengthWebInDays) } - ua := user_agent.New(r.UserAgent()) + ua := uasurfer.Parse(r.UserAgent()) - plat := ua.Platform() + plat := ua.OS.Platform.String() if plat == "" { plat = "unknown" } - os := ua.OS() + os := ua.OS.Name.String() if os == "" { os = "unknown" } - bname, bversion := ua.Browser() + bname := ua.Browser.Name.String() if bname == "" { bname = "unknown" } @@ -92,9 +92,7 @@ func (a *App) DoLogin(w http.ResponseWriter, r *http.Request, user *model.User, bname = "Desktop App" } - if bversion == "" { - bversion = "0.0" - } + bversion := ua.Browser.Version session.AddProp(model.SESSION_PROP_PLATFORM, plat) session.AddProp(model.SESSION_PROP_OS, os) -- cgit v1.2.3-1-g7c22 From f2d26801b9647715fb43af873354d8def753868b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Espino?= Date: Mon, 12 Mar 2018 17:52:17 +0000 Subject: Adding new global relay settings to diagnostics and default.json (#8441) --- app/diagnostics.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/diagnostics.go b/app/diagnostics.go index 12553afc8..4cff5f02a 100644 --- a/app/diagnostics.go +++ b/app/diagnostics.go @@ -502,11 +502,15 @@ func (a *App) trackConfig() { }) a.SendDiagnostic(TRACK_CONFIG_MESSAGE_EXPORT, map[string]interface{}{ - "enable_message_export": *cfg.MessageExportSettings.EnableExport, - "export_format": *cfg.MessageExportSettings.ExportFormat, - "daily_run_time": *cfg.MessageExportSettings.DailyRunTime, - "default_export_from_timestamp": *cfg.MessageExportSettings.ExportFromTimestamp, - "batch_size": *cfg.MessageExportSettings.BatchSize, + "enable_message_export": *cfg.MessageExportSettings.EnableExport, + "export_format": *cfg.MessageExportSettings.ExportFormat, + "daily_run_time": *cfg.MessageExportSettings.DailyRunTime, + "default_export_from_timestamp": *cfg.MessageExportSettings.ExportFromTimestamp, + "batch_size": *cfg.MessageExportSettings.BatchSize, + "global_relay_customer_type": *cfg.MessageExportSettings.GlobalRelaySettings.CustomerType, + "is_default_global_relay_smtp_username": isDefault(*cfg.MessageExportSettings.GlobalRelaySettings.SmtpUsername, ""), + "is_default_global_relay_smtp_password": isDefault(*cfg.MessageExportSettings.GlobalRelaySettings.SmtpPassword, ""), + "is_default_global_relay_email_address": isDefault(*cfg.MessageExportSettings.GlobalRelaySettings.EmailAddress, ""), }) } -- cgit v1.2.3-1-g7c22