From 3e9cd464de333c2c3c7aae9ad069a93c05bb22af Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Thu, 21 Nov 2019 19:35:19 -0300 Subject: [PATCH] MM-20347 Move ID Loaded Push Notifications to E20 (#13185) * Move ID Loaded Push Notifications to E20 * Fix model tests --- api4/system.go | 15 +++- app/app.go | 1 + app/enterprise.go | 9 ++ app/notification.go | 32 +++---- app/notification_email.go | 4 +- app/notification_push.go | 152 +++++++++------------------------- app/notification_push_test.go | 67 +-------------- app/notification_test.go | 12 +-- app/options.go | 1 + app/server.go | 1 + einterfaces/notification.go | 13 +++ i18n/en.json | 8 ++ model/license.go | 6 ++ model/license_test.go | 5 ++ model/push_notification.go | 3 +- utils/license.go | 1 + 16 files changed, 125 insertions(+), 205 deletions(-) create mode 100644 einterfaces/notification.go diff --git a/api4/system.go b/api4/system.go index 385ab28c63..7b9462c111 100644 --- a/api4/system.go +++ b/api4/system.go @@ -410,7 +410,7 @@ func pushNotificationAck(c *Context, w http.ResponseWriter, r *http.Request) { } err := c.App.SendAckToPushProxy(ack) - if ack.NotificationType == model.PUSH_TYPE_ID_LOADED { + if ack.IsIdLoaded { if err != nil { // Log the error only, then continue to fetch notification message c.App.NotificationsLog.Error("Notification ack not sent to push proxy", @@ -421,9 +421,16 @@ func pushNotificationAck(c *Context, w http.ResponseWriter, r *http.Request) { ) } - msg, appErr := c.App.BuildFetchedPushNotificationMessage(ack.PostId, c.App.Session.UserId) - if appErr != nil { - c.Err = model.NewAppError("pushNotificationAck", "api.push_notification.id_loaded.fetch.app_error", nil, appErr.Error(), http.StatusInternalServerError) + notificationInterface := c.App.Notification + + if notificationInterface == nil { + c.Err = model.NewAppError("pushNotificationAck", "api.system.id_loaded.not_available.app_error", nil, "", http.StatusFound) + return + } + + msg, appError := notificationInterface.GetNotificationMessage(ack, c.App.Session.UserId) + if appError != nil { + c.Err = model.NewAppError("pushNotificationAck", "api.push_notification.id_loaded.fetch.app_error", nil, appError.Error(), http.StatusInternalServerError) return } diff --git a/app/app.go b/app/app.go index dd106ce4ba..8862da17e0 100644 --- a/app/app.go +++ b/app/app.go @@ -41,6 +41,7 @@ type App struct { Ldap einterfaces.LdapInterface MessageExport einterfaces.MessageExportInterface Metrics einterfaces.MetricsInterface + Notification einterfaces.NotificationInterface Saml einterfaces.SamlInterface HTTPService httpservice.HTTPService diff --git a/app/enterprise.go b/app/enterprise.go index 22da49fe23..957174f075 100644 --- a/app/enterprise.go +++ b/app/enterprise.go @@ -107,6 +107,12 @@ func RegisterSamlInterface(f func(*App) einterfaces.SamlInterface) { samlInterface = f } +var notificationInterface func(*App) einterfaces.NotificationInterface + +func RegisterNotificationInterface(f func(*App) einterfaces.NotificationInterface) { + notificationInterface = f +} + func (s *Server) initEnterprise() { if accountMigrationInterface != nil { s.AccountMigration = accountMigrationInterface(s) @@ -126,6 +132,9 @@ func (s *Server) initEnterprise() { if metricsInterface != nil { s.Metrics = metricsInterface(s.FakeApp()) } + if notificationInterface != nil { + s.Notification = notificationInterface(s.FakeApp()) + } if samlInterface != nil { s.Saml = samlInterface(s.FakeApp()) s.AddConfigListener(func(_, cfg *model.Config) { diff --git a/app/notification.go b/app/notification.go index 5bd906bebb..dce6dd6253 100644 --- a/app/notification.go +++ b/app/notification.go @@ -140,10 +140,10 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod } notification := &PostNotification{ - post: post, - channel: channel, - profileMap: profileMap, - sender: sender, + Post: post, + Channel: channel, + ProfileMap: profileMap, + Sender: sender, } if *a.Config().EmailSettings.SendEmailNotifications { @@ -692,22 +692,22 @@ func addMentionKeywordsForUser(keywords map[string][]string, profile *model.User // Represents either an email or push notification and contains the fields required to send it to any user. type PostNotification struct { - channel *model.Channel - post *model.Post - profileMap map[string]*model.User - sender *model.User + Channel *model.Channel + Post *model.Post + ProfileMap map[string]*model.User + Sender *model.User } // Returns the name of the channel for this notification. For direct messages, this is the sender's name // preceeded by an at sign. For group messages, this is a comma-separated list of the members of the // channel, with an option to exclude the recipient of the message from that list. func (n *PostNotification) GetChannelName(userNameFormat, excludeId string) string { - switch n.channel.Type { + switch n.Channel.Type { case model.CHANNEL_DIRECT: - return n.sender.GetDisplayNameWithPrefix(userNameFormat, "@") + return n.Sender.GetDisplayNameWithPrefix(userNameFormat, "@") case model.CHANNEL_GROUP: names := []string{} - for _, user := range n.profileMap { + for _, user := range n.ProfileMap { if user.Id != excludeId { names = append(names, user.GetDisplayName(userNameFormat)) } @@ -717,24 +717,24 @@ func (n *PostNotification) GetChannelName(userNameFormat, excludeId string) stri return strings.Join(names, ", ") default: - return n.channel.DisplayName + return n.Channel.DisplayName } } // Returns the name of the sender of this notification, accounting for things like system messages // and whether or not the username has been overridden by an integration. func (n *PostNotification) GetSenderName(userNameFormat string, overridesAllowed bool) string { - if n.post.IsSystemMessage() { + if n.Post.IsSystemMessage() { return utils.T("system.message.name") } - if overridesAllowed && n.channel.Type != model.CHANNEL_DIRECT { - if value, ok := n.post.Props["override_username"]; ok && n.post.Props["from_webhook"] == "true" { + if overridesAllowed && n.Channel.Type != model.CHANNEL_DIRECT { + if value, ok := n.Post.Props["override_username"]; ok && n.Post.Props["from_webhook"] == "true" { return value.(string) } } - return n.sender.GetDisplayNameWithPrefix(userNameFormat, "@") + return n.Sender.GetDisplayNameWithPrefix(userNameFormat, "@") } // checkForMention checks if there is a mention to a specific user or to the keywords here / channel / all diff --git a/app/notification_email.go b/app/notification_email.go index 65c5ff0f8d..5344cc917a 100644 --- a/app/notification_email.go +++ b/app/notification_email.go @@ -19,8 +19,8 @@ import ( ) func (a *App) sendNotificationEmail(notification *PostNotification, user *model.User, team *model.Team) *model.AppError { - channel := notification.channel - post := notification.post + channel := notification.Channel + post := notification.Post if channel.IsGroupOrDirect() { teams, err := a.Srv.Store.Team().GetTeamsByUserId(user.Id) diff --git a/app/notification_push.go b/app/notification_push.go index e14d195acb..4038e81c86 100644 --- a/app/notification_push.go +++ b/app/notification_push.go @@ -53,7 +53,18 @@ func (hub *PushNotificationsHub) GetGoChannelFromUserId(userId string) chan Push func (a *App) sendPushNotificationSync(post *model.Post, user *model.User, channel *model.Channel, channelName string, senderName string, explicitMention bool, channelWideMention bool, replyToThreadType string) *model.AppError { - msg, err := a.BuildPushNotificationMessage(post, user, channel, channelName, senderName, explicitMention, channelWideMention, replyToThreadType) + cfg := a.Config() + msg, err := a.BuildPushNotificationMessage( + *cfg.EmailSettings.PushNotificationContents, + post, + user, + channel, + channelName, + senderName, + explicitMention, + channelWideMention, + replyToThreadType, + ) if err != nil { return err } @@ -112,8 +123,8 @@ func (a *App) sendPushNotificationToAllSessions(msg *model.PushNotification, use func (a *App) sendPushNotification(notification *PostNotification, user *model.User, explicitMention, channelWideMention bool, replyToThreadType string) { cfg := a.Config() - channel := notification.channel - post := notification.post + channel := notification.Channel + post := notification.Post nameFormat := a.GetNotificationNameFormat(user) @@ -134,23 +145,7 @@ func (a *App) sendPushNotification(notification *PostNotification, user *model.U } } -func (a *App) getFetchedPushNotificationMessage(postMessage, senderName, channelType string, hasFiles bool, userLocale i18n.TranslateFunc) string { - // If the post only has images then push an appropriate message - if len(postMessage) == 0 && hasFiles { - if channelType == model.CHANNEL_DIRECT { - return strings.Trim(userLocale("api.post.send_notifications_and_forget.push_image_only"), " ") - } - return senderName + userLocale("api.post.send_notifications_and_forget.push_image_only") - } - - if channelType == model.CHANNEL_DIRECT { - return model.ClearMentionTags(postMessage) - } - - return senderName + ": " + model.ClearMentionTags(postMessage) -} - -func (a *App) getPushNotificationMessage(postMessage string, explicitMention, channelWideMention, hasFiles bool, +func (a *App) getPushNotificationMessage(contentsConfig, postMessage string, explicitMention, channelWideMention, hasFiles bool, senderName, channelName, channelType, replyToThreadType string, userLocale i18n.TranslateFunc) string { // If the post only has images then push an appropriate message @@ -161,8 +156,6 @@ func (a *App) getPushNotificationMessage(postMessage string, explicitMention, ch return senderName + userLocale("api.post.send_notifications_and_forget.push_image_only") } - contentsConfig := *a.Config().EmailSettings.PushNotificationContents - if contentsConfig == model.FULL_NOTIFICATION { if channelType == model.CHANNEL_DIRECT { return model.ClearMentionTags(postMessage) @@ -444,85 +437,20 @@ func DoesStatusAllowPushNotification(userNotifyProps model.StringMap, status *mo return false } -func (a *App) BuildFetchedPushNotificationMessage(postId string, userId string) (model.PushNotification, *model.AppError) { - msg := model.PushNotification{ - Type: model.PUSH_TYPE_ID_LOADED, - Category: model.CATEGORY_CAN_REPLY, - Version: model.PUSH_MESSAGE_V2, - } - - post, err := a.GetSinglePost(postId) - if err != nil { - return msg, err - } - - channel, err := a.GetChannel(post.ChannelId) - if err != nil { - return msg, err - } - - user, err := a.GetUser(userId) - if err != nil { - return msg, err - } - - sender, err := a.GetUser(post.UserId) - if err != nil { - return msg, err - } - - msg.PostId = post.Id - msg.RootId = post.RootId - msg.SenderId = post.UserId - msg.ChannelId = channel.Id - msg.TeamId = channel.TeamId - - notification := &PostNotification{ - post: post, - channel: channel, - sender: sender, - } - - cfg := a.Config() - nameFormat := a.GetNotificationNameFormat(user) - channelName := notification.GetChannelName(nameFormat, user.Id) - senderName := notification.GetSenderName(nameFormat, *cfg.ServiceSettings.EnablePostUsernameOverride) - - msg.ChannelName = channelName - - msg.SenderName = senderName - if ou, ok := post.Props["override_username"].(string); ok && *cfg.ServiceSettings.EnablePostUsernameOverride { - msg.OverrideUsername = ou - msg.SenderName = ou - } - - if oi, ok := post.Props["override_icon_url"].(string); ok && *cfg.ServiceSettings.EnablePostIconOverride { - msg.OverrideIconUrl = oi - } - - if fw, ok := post.Props["from_webhook"].(string); ok { - msg.FromWebhook = fw - } - - userLocale := utils.GetUserTranslations(user.Locale) - hasFiles := post.FileIds != nil && len(post.FileIds) > 0 - - msg.Message = a.getFetchedPushNotificationMessage(post.Message, msg.SenderName, channel.Type, hasFiles, userLocale) - - return msg, nil -} - -func (a *App) BuildPushNotificationMessage(post *model.Post, user *model.User, channel *model.Channel, channelName string, senderName string, +func (a *App) BuildPushNotificationMessage(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) { var msg *model.PushNotification - cfg := a.Config() - contentsConfig := *cfg.EmailSettings.PushNotificationContents + notificationInterface := a.Srv.Notification + if (notificationInterface == nil || notificationInterface.CheckLicense() != nil) && contentsConfig == model.ID_LOADED_NOTIFICATION { + contentsConfig = model.GENERIC_NOTIFICATION + } + if contentsConfig == model.ID_LOADED_NOTIFICATION { msg = a.buildIdLoadedPushNotificationMessage(post, user) } else { - msg = a.buildFullPushNotificationMessage(post, user, channel, channelName, senderName, explicitMention, channelWideMention, replyToThreadType) + msg = a.buildFullPushNotificationMessage(contentsConfig, post, user, channel, channelName, senderName, explicitMention, channelWideMention, replyToThreadType) } badge, err := a.getPushNotificationBadge(user, channel) @@ -537,33 +465,35 @@ func (a *App) BuildPushNotificationMessage(post *model.Post, user *model.User, c func (a *App) buildIdLoadedPushNotificationMessage(post *model.Post, user *model.User) *model.PushNotification { userLocale := utils.GetUserTranslations(user.Locale) msg := &model.PushNotification{ - PostId: post.Id, - ChannelId: post.ChannelId, - Category: model.CATEGORY_CAN_REPLY, - Version: model.PUSH_MESSAGE_V2, - Type: model.PUSH_TYPE_ID_LOADED, - Message: userLocale("api.push_notification.id_loaded.default_message"), + PostId: post.Id, + ChannelId: post.ChannelId, + Category: model.CATEGORY_CAN_REPLY, + Version: model.PUSH_MESSAGE_V2, + Type: model.PUSH_TYPE_MESSAGE, + IsIdLoaded: true, + SenderId: user.Id, + Message: userLocale("api.push_notification.id_loaded.default_message"), } return msg } -func (a *App) buildFullPushNotificationMessage(post *model.Post, user *model.User, channel *model.Channel, channelName string, senderName string, +func (a *App) buildFullPushNotificationMessage(contentsConfig string, post *model.Post, user *model.User, channel *model.Channel, channelName string, senderName string, explicitMention bool, channelWideMention bool, replyToThreadType string) *model.PushNotification { msg := &model.PushNotification{ - Category: model.CATEGORY_CAN_REPLY, - Version: model.PUSH_MESSAGE_V2, - Type: model.PUSH_TYPE_MESSAGE, - TeamId: channel.TeamId, - ChannelId: channel.Id, - PostId: post.Id, - RootId: post.RootId, - SenderId: post.UserId, + Category: model.CATEGORY_CAN_REPLY, + Version: model.PUSH_MESSAGE_V2, + Type: model.PUSH_TYPE_MESSAGE, + TeamId: channel.TeamId, + ChannelId: channel.Id, + PostId: post.Id, + RootId: post.RootId, + SenderId: post.UserId, + IsIdLoaded: false, } cfg := a.Config() - contentsConfig := *cfg.EmailSettings.PushNotificationContents if contentsConfig != model.GENERIC_NO_CHANNEL_NOTIFICATION || channel.Type == model.CHANNEL_DIRECT { msg.ChannelName = channelName } @@ -585,7 +515,7 @@ func (a *App) buildFullPushNotificationMessage(post *model.Post, user *model.Use userLocale := utils.GetUserTranslations(user.Locale) hasFiles := post.FileIds != nil && len(post.FileIds) > 0 - msg.Message = a.getPushNotificationMessage(post.Message, explicitMention, channelWideMention, hasFiles, msg.SenderName, channelName, channel.Type, replyToThreadType, userLocale) + msg.Message = a.getPushNotificationMessage(contentsConfig, post.Message, explicitMention, channelWideMention, hasFiles, msg.SenderName, channelName, channel.Type, replyToThreadType, userLocale) return msg } diff --git a/app/notification_push_test.go b/app/notification_push_test.go index bb1bf1f72f..ee68b036ac 100644 --- a/app/notification_push_test.go +++ b/app/notification_push_test.go @@ -883,6 +883,7 @@ func TestGetPushNotificationMessage(t *testing.T) { }) actualMessage := th.App.getPushNotificationMessage( + pushNotificationContents, tc.Message, tc.explicitMention, tc.channelWideMention, @@ -943,73 +944,9 @@ func TestBuildPushNotificationMessageMentions(t *testing.T) { } { t.Run(name, func(t *testing.T) { receiver.NotifyProps["push"] = tc.pushNotifyProps - msg, err := th.App.BuildPushNotificationMessage(post, receiver, channel, channel.Name, sender.Username, tc.explicitMention, tc.channelWideMention, tc.replyToThreadType) + msg, err := th.App.BuildPushNotificationMessage(model.FULL_NOTIFICATION, post, receiver, channel, channel.Name, sender.Username, tc.explicitMention, tc.channelWideMention, tc.replyToThreadType) require.Nil(t, err) assert.Equal(t, tc.expectedBadge, msg.Badge) }) } } - -func TestBuildPushNotificationMessageContents(t *testing.T) { - th := Setup(t).InitBasic() - defer th.TearDown() - - team := th.CreateTeam() - sender := th.CreateUser() - receiver := th.CreateUser() - th.LinkUserToTeam(sender, team) - th.LinkUserToTeam(receiver, team) - channel := th.CreateChannel(team) - th.AddUserToChannel(sender, channel) - th.AddUserToChannel(receiver, channel) - - post := th.CreatePost(channel) - - explicitMention := false - channelWideMention := false - replyToThreadType := "" - - receiverLocale := utils.GetUserTranslations(receiver.Locale) - - for name, tc := range map[string]struct { - contentsConfig string - expectedMsg *model.PushNotification - }{ - "only post ID, channel ID, and message included in push notification": { - contentsConfig: model.ID_LOADED_NOTIFICATION, - expectedMsg: &model.PushNotification{ - PostId: post.Id, - ChannelId: post.ChannelId, - Category: model.CATEGORY_CAN_REPLY, - Version: model.PUSH_MESSAGE_V2, - Type: model.PUSH_TYPE_ID_LOADED, - Message: receiverLocale("api.push_notification.id_loaded.default_message"), - }, - }, - "full contents included in push notification": { - contentsConfig: model.GENERIC_NOTIFICATION, - expectedMsg: &model.PushNotification{ - Category: model.CATEGORY_CAN_REPLY, - Version: model.PUSH_MESSAGE_V2, - Type: model.PUSH_TYPE_MESSAGE, - PostId: post.Id, - TeamId: channel.TeamId, - ChannelId: channel.Id, - ChannelName: channel.Name, - RootId: post.RootId, - SenderId: post.UserId, - SenderName: sender.Username, - Message: fmt.Sprintf("%s posted a message.", sender.Username), - }, - }, - } { - t.Run(name, func(t *testing.T) { - th.App.UpdateConfig(func(cfg *model.Config) { *cfg.EmailSettings.PushNotificationContents = tc.contentsConfig }) - - msg, err := th.App.BuildPushNotificationMessage(post, receiver, channel, channel.Name, sender.Username, explicitMention, channelWideMention, replyToThreadType) - - require.Nil(t, err) - assert.Equal(t, tc.expectedMsg, msg) - }) - } -} diff --git a/app/notification_test.go b/app/notification_test.go index a9d453ee23..b04d79523a 100644 --- a/app/notification_test.go +++ b/app/notification_test.go @@ -1541,9 +1541,9 @@ func TestPostNotificationGetChannelName(t *testing.T) { } { t.Run(name, func(t *testing.T) { notification := &PostNotification{ - channel: testCase.channel, - sender: sender, - profileMap: profileMap, + Channel: testCase.channel, + Sender: sender, + ProfileMap: profileMap, } recipientId := recipient.Id @@ -1626,9 +1626,9 @@ func TestPostNotificationGetSenderName(t *testing.T) { } notification := &PostNotification{ - channel: channel, - post: post, - sender: sender, + Channel: channel, + Post: post, + Sender: sender, } assert.Equal(t, testCase.expected, notification.GetSenderName(testCase.nameFormat, testCase.allowOverrides)) diff --git a/app/options.go b/app/options.go index 4409b5aedf..55f420ce57 100644 --- a/app/options.go +++ b/app/options.go @@ -109,6 +109,7 @@ func ServerConnector(s *Server) AppOption { a.Ldap = s.Ldap a.MessageExport = s.MessageExport a.Metrics = s.Metrics + a.Notification = s.Notification a.Saml = s.Saml a.HTTPService = s.HTTPService diff --git a/app/server.go b/app/server.go index 319e8cecdc..2b0fcdef69 100644 --- a/app/server.go +++ b/app/server.go @@ -126,6 +126,7 @@ type Server struct { Ldap einterfaces.LdapInterface MessageExport einterfaces.MessageExportInterface Metrics einterfaces.MetricsInterface + Notification einterfaces.NotificationInterface Saml einterfaces.SamlInterface } diff --git a/einterfaces/notification.go b/einterfaces/notification.go new file mode 100644 index 0000000000..ed4ecd4b6c --- /dev/null +++ b/einterfaces/notification.go @@ -0,0 +1,13 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +package einterfaces + +import ( + "github.com/mattermost/mattermost-server/model" +) + +type NotificationInterface interface { + GetNotificationMessage(ack *model.PushNotificationAck, userId string) (*model.PushNotification, *model.AppError) + CheckLicense() *model.AppError +} diff --git a/i18n/en.json b/i18n/en.json index 3edbf60ced..a978bbd6d9 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -1878,6 +1878,10 @@ "id": "api.status.user_not_found.app_error", "translation": "User not found" }, + { + "id": "api.system.id_loaded.not_available.app_error", + "translation": "ID Loaded Push Notifications are not configured or supported on this server." + }, { "id": "api.team.add_members.error", "translation": "Error adding team member(s)." @@ -3954,6 +3958,10 @@ "id": "ent.elasticsearch.test_config.reenter_password", "translation": "The Elasticsearch Server URL or Username has changed. Please re-enter the Elasticsearch password to test connection." }, + { + "id": "ent.id_loaded.license_disable.app_error", + "translation": "Your license does not support ID Loaded Push Notifications." + }, { "id": "ent.ldap.app_error", "translation": "ldap interface was nil" diff --git a/model/license.go b/model/license.go index e9eec517fd..41630a0a19 100644 --- a/model/license.go +++ b/model/license.go @@ -60,6 +60,7 @@ type Features struct { CustomPermissionsSchemes *bool `json:"custom_permissions_schemes"` CustomTermsOfService *bool `json:"custom_terms_of_service"` GuestAccountsPermissions *bool `json:"guest_accounts_permissions"` + IDLoadedPushNotifications *bool `json:"id_loaded"` // after we enabled more features we'll need to control them with this FutureFeatures *bool `json:"future_features"` @@ -83,6 +84,7 @@ func (f *Features) ToMap() map[string]interface{} { "message_export": *f.MessageExport, "custom_permissions_schemes": *f.CustomPermissionsSchemes, "guest_accounts_permissions": *f.GuestAccountsPermissions, + "id_loaded": *f.IDLoadedPushNotifications, "future": *f.FutureFeatures, } } @@ -171,6 +173,10 @@ func (f *Features) SetDefaults() { if f.CustomTermsOfService == nil { f.CustomTermsOfService = NewBool(*f.FutureFeatures) } + + if f.IDLoadedPushNotifications == nil { + f.IDLoadedPushNotifications = NewBool(*f.FutureFeatures) + } } func (l *License) IsExpired() bool { diff --git a/model/license_test.go b/model/license_test.go index 9ddf710e7a..5baab8cec3 100644 --- a/model/license_test.go +++ b/model/license_test.go @@ -31,6 +31,7 @@ func TestLicenseFeaturesToMap(t *testing.T) { CheckTrue(t, m["data_retention"].(bool)) CheckTrue(t, m["message_export"].(bool)) CheckTrue(t, m["custom_permissions_schemes"].(bool)) + CheckTrue(t, m["id_loaded"].(bool)) CheckTrue(t, m["future"].(bool)) } @@ -55,6 +56,7 @@ func TestLicenseFeaturesSetDefaults(t *testing.T) { CheckTrue(t, *f.MessageExport) CheckTrue(t, *f.CustomPermissionsSchemes) CheckTrue(t, *f.GuestAccountsPermissions) + CheckTrue(t, *f.IDLoadedPushNotifications) CheckTrue(t, *f.FutureFeatures) f = Features{} @@ -78,6 +80,7 @@ func TestLicenseFeaturesSetDefaults(t *testing.T) { *f.CustomPermissionsSchemes = true *f.GuestAccountsPermissions = true *f.EmailNotificationContents = true + *f.IDLoadedPushNotifications = true f.SetDefaults() @@ -98,6 +101,7 @@ func TestLicenseFeaturesSetDefaults(t *testing.T) { CheckTrue(t, *f.MessageExport) CheckTrue(t, *f.CustomPermissionsSchemes) CheckTrue(t, *f.GuestAccountsPermissions) + CheckTrue(t, *f.IDLoadedPushNotifications) CheckFalse(t, *f.FutureFeatures) } @@ -173,6 +177,7 @@ func TestLicenseToFromJson(t *testing.T) { CheckBool(t, *f1.MessageExport, *f.MessageExport) CheckBool(t, *f1.CustomPermissionsSchemes, *f.CustomPermissionsSchemes) CheckBool(t, *f1.GuestAccountsPermissions, *f.GuestAccountsPermissions) + CheckBool(t, *f1.IDLoadedPushNotifications, *f.IDLoadedPushNotifications) CheckBool(t, *f1.FutureFeatures, *f.FutureFeatures) invalid := `{"asdf` diff --git a/model/push_notification.go b/model/push_notification.go index 00eb3955f8..3c640817eb 100644 --- a/model/push_notification.go +++ b/model/push_notification.go @@ -15,7 +15,6 @@ const ( PUSH_NOTIFY_APPLE_REACT_NATIVE = "apple_rn" PUSH_NOTIFY_ANDROID_REACT_NATIVE = "android_rn" - PUSH_TYPE_ID_LOADED = "id_loaded" PUSH_TYPE_MESSAGE = "message" PUSH_TYPE_CLEAR = "clear" PUSH_TYPE_UPDATE_BADGE = "update_badge" @@ -41,6 +40,7 @@ type PushNotificationAck struct { ClientPlatform string `json:"platform"` NotificationType string `json:"type"` PostId string `json:"post_id,omitempty"` + IsIdLoaded bool `json:"is_id_loaded"` } type PushNotification struct { @@ -65,6 +65,7 @@ type PushNotification struct { OverrideIconUrl string `json:"override_icon_url,omitempty"` FromWebhook string `json:"from_webhook,omitempty"` Version string `json:"version,omitempty"` + IsIdLoaded bool `json:"is_id_loaded"` } func (me *PushNotification) ToJson() string { diff --git a/utils/license.go b/utils/license.go index 9758ca1e0e..3426525a02 100644 --- a/utils/license.go +++ b/utils/license.go @@ -144,6 +144,7 @@ func GetClientLicense(l *model.License) map[string]string { props["Announcement"] = strconv.FormatBool(*l.Features.Announcement) props["Elasticsearch"] = strconv.FormatBool(*l.Features.Elasticsearch) props["DataRetention"] = strconv.FormatBool(*l.Features.DataRetention) + props["IDLoadedPushNotifications"] = strconv.FormatBool(*l.Features.IDLoadedPushNotifications) props["IssuedAt"] = strconv.FormatInt(l.IssuedAt, 10) props["StartsAt"] = strconv.FormatInt(l.StartsAt, 10) props["ExpiresAt"] = strconv.FormatInt(l.ExpiresAt, 10)