MM-20347 Move ID Loaded Push Notifications to E20 (#13185)
* Move ID Loaded Push Notifications to E20 * Fix model tests
Этот коммит содержится в:
@@ -410,7 +410,7 @@ func pushNotificationAck(c *Context, w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
err := c.App.SendAckToPushProxy(ack)
|
err := c.App.SendAckToPushProxy(ack)
|
||||||
if ack.NotificationType == model.PUSH_TYPE_ID_LOADED {
|
if ack.IsIdLoaded {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Log the error only, then continue to fetch notification message
|
// Log the error only, then continue to fetch notification message
|
||||||
c.App.NotificationsLog.Error("Notification ack not sent to push proxy",
|
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)
|
notificationInterface := c.App.Notification
|
||||||
if appErr != nil {
|
|
||||||
c.Err = model.NewAppError("pushNotificationAck", "api.push_notification.id_loaded.fetch.app_error", nil, appErr.Error(), http.StatusInternalServerError)
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ type App struct {
|
|||||||
Ldap einterfaces.LdapInterface
|
Ldap einterfaces.LdapInterface
|
||||||
MessageExport einterfaces.MessageExportInterface
|
MessageExport einterfaces.MessageExportInterface
|
||||||
Metrics einterfaces.MetricsInterface
|
Metrics einterfaces.MetricsInterface
|
||||||
|
Notification einterfaces.NotificationInterface
|
||||||
Saml einterfaces.SamlInterface
|
Saml einterfaces.SamlInterface
|
||||||
|
|
||||||
HTTPService httpservice.HTTPService
|
HTTPService httpservice.HTTPService
|
||||||
|
|||||||
@@ -107,6 +107,12 @@ func RegisterSamlInterface(f func(*App) einterfaces.SamlInterface) {
|
|||||||
samlInterface = f
|
samlInterface = f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var notificationInterface func(*App) einterfaces.NotificationInterface
|
||||||
|
|
||||||
|
func RegisterNotificationInterface(f func(*App) einterfaces.NotificationInterface) {
|
||||||
|
notificationInterface = f
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Server) initEnterprise() {
|
func (s *Server) initEnterprise() {
|
||||||
if accountMigrationInterface != nil {
|
if accountMigrationInterface != nil {
|
||||||
s.AccountMigration = accountMigrationInterface(s)
|
s.AccountMigration = accountMigrationInterface(s)
|
||||||
@@ -126,6 +132,9 @@ func (s *Server) initEnterprise() {
|
|||||||
if metricsInterface != nil {
|
if metricsInterface != nil {
|
||||||
s.Metrics = metricsInterface(s.FakeApp())
|
s.Metrics = metricsInterface(s.FakeApp())
|
||||||
}
|
}
|
||||||
|
if notificationInterface != nil {
|
||||||
|
s.Notification = notificationInterface(s.FakeApp())
|
||||||
|
}
|
||||||
if samlInterface != nil {
|
if samlInterface != nil {
|
||||||
s.Saml = samlInterface(s.FakeApp())
|
s.Saml = samlInterface(s.FakeApp())
|
||||||
s.AddConfigListener(func(_, cfg *model.Config) {
|
s.AddConfigListener(func(_, cfg *model.Config) {
|
||||||
|
|||||||
@@ -140,10 +140,10 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod
|
|||||||
}
|
}
|
||||||
|
|
||||||
notification := &PostNotification{
|
notification := &PostNotification{
|
||||||
post: post,
|
Post: post,
|
||||||
channel: channel,
|
Channel: channel,
|
||||||
profileMap: profileMap,
|
ProfileMap: profileMap,
|
||||||
sender: sender,
|
Sender: sender,
|
||||||
}
|
}
|
||||||
|
|
||||||
if *a.Config().EmailSettings.SendEmailNotifications {
|
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.
|
// Represents either an email or push notification and contains the fields required to send it to any user.
|
||||||
type PostNotification struct {
|
type PostNotification struct {
|
||||||
channel *model.Channel
|
Channel *model.Channel
|
||||||
post *model.Post
|
Post *model.Post
|
||||||
profileMap map[string]*model.User
|
ProfileMap map[string]*model.User
|
||||||
sender *model.User
|
Sender *model.User
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the name of the channel for this notification. For direct messages, this is the sender's name
|
// 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
|
// 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.
|
// channel, with an option to exclude the recipient of the message from that list.
|
||||||
func (n *PostNotification) GetChannelName(userNameFormat, excludeId string) string {
|
func (n *PostNotification) GetChannelName(userNameFormat, excludeId string) string {
|
||||||
switch n.channel.Type {
|
switch n.Channel.Type {
|
||||||
case model.CHANNEL_DIRECT:
|
case model.CHANNEL_DIRECT:
|
||||||
return n.sender.GetDisplayNameWithPrefix(userNameFormat, "@")
|
return n.Sender.GetDisplayNameWithPrefix(userNameFormat, "@")
|
||||||
case model.CHANNEL_GROUP:
|
case model.CHANNEL_GROUP:
|
||||||
names := []string{}
|
names := []string{}
|
||||||
for _, user := range n.profileMap {
|
for _, user := range n.ProfileMap {
|
||||||
if user.Id != excludeId {
|
if user.Id != excludeId {
|
||||||
names = append(names, user.GetDisplayName(userNameFormat))
|
names = append(names, user.GetDisplayName(userNameFormat))
|
||||||
}
|
}
|
||||||
@@ -717,24 +717,24 @@ func (n *PostNotification) GetChannelName(userNameFormat, excludeId string) stri
|
|||||||
|
|
||||||
return strings.Join(names, ", ")
|
return strings.Join(names, ", ")
|
||||||
default:
|
default:
|
||||||
return n.channel.DisplayName
|
return n.Channel.DisplayName
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the name of the sender of this notification, accounting for things like system messages
|
// 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.
|
// and whether or not the username has been overridden by an integration.
|
||||||
func (n *PostNotification) GetSenderName(userNameFormat string, overridesAllowed bool) string {
|
func (n *PostNotification) GetSenderName(userNameFormat string, overridesAllowed bool) string {
|
||||||
if n.post.IsSystemMessage() {
|
if n.Post.IsSystemMessage() {
|
||||||
return utils.T("system.message.name")
|
return utils.T("system.message.name")
|
||||||
}
|
}
|
||||||
|
|
||||||
if overridesAllowed && n.channel.Type != model.CHANNEL_DIRECT {
|
if overridesAllowed && n.Channel.Type != model.CHANNEL_DIRECT {
|
||||||
if value, ok := n.post.Props["override_username"]; ok && n.post.Props["from_webhook"] == "true" {
|
if value, ok := n.Post.Props["override_username"]; ok && n.Post.Props["from_webhook"] == "true" {
|
||||||
return value.(string)
|
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
|
// checkForMention checks if there is a mention to a specific user or to the keywords here / channel / all
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (a *App) sendNotificationEmail(notification *PostNotification, user *model.User, team *model.Team) *model.AppError {
|
func (a *App) sendNotificationEmail(notification *PostNotification, user *model.User, team *model.Team) *model.AppError {
|
||||||
channel := notification.channel
|
channel := notification.Channel
|
||||||
post := notification.post
|
post := notification.Post
|
||||||
|
|
||||||
if channel.IsGroupOrDirect() {
|
if channel.IsGroupOrDirect() {
|
||||||
teams, err := a.Srv.Store.Team().GetTeamsByUserId(user.Id)
|
teams, err := a.Srv.Store.Team().GetTeamsByUserId(user.Id)
|
||||||
|
|||||||
@@ -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,
|
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 {
|
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 {
|
if err != nil {
|
||||||
return err
|
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) {
|
func (a *App) sendPushNotification(notification *PostNotification, user *model.User, explicitMention, channelWideMention bool, replyToThreadType string) {
|
||||||
cfg := a.Config()
|
cfg := a.Config()
|
||||||
channel := notification.channel
|
channel := notification.Channel
|
||||||
post := notification.post
|
post := notification.Post
|
||||||
|
|
||||||
nameFormat := a.GetNotificationNameFormat(user)
|
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 {
|
func (a *App) getPushNotificationMessage(contentsConfig, postMessage string, explicitMention, channelWideMention, hasFiles bool,
|
||||||
// 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,
|
|
||||||
senderName, channelName, channelType, replyToThreadType string, userLocale i18n.TranslateFunc) string {
|
senderName, channelName, channelType, replyToThreadType string, userLocale i18n.TranslateFunc) string {
|
||||||
|
|
||||||
// If the post only has images then push an appropriate message
|
// 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")
|
return senderName + userLocale("api.post.send_notifications_and_forget.push_image_only")
|
||||||
}
|
}
|
||||||
|
|
||||||
contentsConfig := *a.Config().EmailSettings.PushNotificationContents
|
|
||||||
|
|
||||||
if contentsConfig == model.FULL_NOTIFICATION {
|
if contentsConfig == model.FULL_NOTIFICATION {
|
||||||
if channelType == model.CHANNEL_DIRECT {
|
if channelType == model.CHANNEL_DIRECT {
|
||||||
return model.ClearMentionTags(postMessage)
|
return model.ClearMentionTags(postMessage)
|
||||||
@@ -444,85 +437,20 @@ func DoesStatusAllowPushNotification(userNotifyProps model.StringMap, status *mo
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *App) BuildFetchedPushNotificationMessage(postId string, userId string) (model.PushNotification, *model.AppError) {
|
func (a *App) BuildPushNotificationMessage(contentsConfig string, post *model.Post, user *model.User, channel *model.Channel, channelName string, senderName string,
|
||||||
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,
|
|
||||||
explicitMention bool, channelWideMention bool, replyToThreadType string) (*model.PushNotification, *model.AppError) {
|
explicitMention bool, channelWideMention bool, replyToThreadType string) (*model.PushNotification, *model.AppError) {
|
||||||
|
|
||||||
var msg *model.PushNotification
|
var msg *model.PushNotification
|
||||||
|
|
||||||
cfg := a.Config()
|
notificationInterface := a.Srv.Notification
|
||||||
contentsConfig := *cfg.EmailSettings.PushNotificationContents
|
if (notificationInterface == nil || notificationInterface.CheckLicense() != nil) && contentsConfig == model.ID_LOADED_NOTIFICATION {
|
||||||
|
contentsConfig = model.GENERIC_NOTIFICATION
|
||||||
|
}
|
||||||
|
|
||||||
if contentsConfig == model.ID_LOADED_NOTIFICATION {
|
if contentsConfig == model.ID_LOADED_NOTIFICATION {
|
||||||
msg = a.buildIdLoadedPushNotificationMessage(post, user)
|
msg = a.buildIdLoadedPushNotificationMessage(post, user)
|
||||||
} else {
|
} 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)
|
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 {
|
func (a *App) buildIdLoadedPushNotificationMessage(post *model.Post, user *model.User) *model.PushNotification {
|
||||||
userLocale := utils.GetUserTranslations(user.Locale)
|
userLocale := utils.GetUserTranslations(user.Locale)
|
||||||
msg := &model.PushNotification{
|
msg := &model.PushNotification{
|
||||||
PostId: post.Id,
|
PostId: post.Id,
|
||||||
ChannelId: post.ChannelId,
|
ChannelId: post.ChannelId,
|
||||||
Category: model.CATEGORY_CAN_REPLY,
|
Category: model.CATEGORY_CAN_REPLY,
|
||||||
Version: model.PUSH_MESSAGE_V2,
|
Version: model.PUSH_MESSAGE_V2,
|
||||||
Type: model.PUSH_TYPE_ID_LOADED,
|
Type: model.PUSH_TYPE_MESSAGE,
|
||||||
Message: userLocale("api.push_notification.id_loaded.default_message"),
|
IsIdLoaded: true,
|
||||||
|
SenderId: user.Id,
|
||||||
|
Message: userLocale("api.push_notification.id_loaded.default_message"),
|
||||||
}
|
}
|
||||||
|
|
||||||
return msg
|
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 {
|
explicitMention bool, channelWideMention bool, replyToThreadType string) *model.PushNotification {
|
||||||
|
|
||||||
msg := &model.PushNotification{
|
msg := &model.PushNotification{
|
||||||
Category: model.CATEGORY_CAN_REPLY,
|
Category: model.CATEGORY_CAN_REPLY,
|
||||||
Version: model.PUSH_MESSAGE_V2,
|
Version: model.PUSH_MESSAGE_V2,
|
||||||
Type: model.PUSH_TYPE_MESSAGE,
|
Type: model.PUSH_TYPE_MESSAGE,
|
||||||
TeamId: channel.TeamId,
|
TeamId: channel.TeamId,
|
||||||
ChannelId: channel.Id,
|
ChannelId: channel.Id,
|
||||||
PostId: post.Id,
|
PostId: post.Id,
|
||||||
RootId: post.RootId,
|
RootId: post.RootId,
|
||||||
SenderId: post.UserId,
|
SenderId: post.UserId,
|
||||||
|
IsIdLoaded: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg := a.Config()
|
cfg := a.Config()
|
||||||
contentsConfig := *cfg.EmailSettings.PushNotificationContents
|
|
||||||
if contentsConfig != model.GENERIC_NO_CHANNEL_NOTIFICATION || channel.Type == model.CHANNEL_DIRECT {
|
if contentsConfig != model.GENERIC_NO_CHANNEL_NOTIFICATION || channel.Type == model.CHANNEL_DIRECT {
|
||||||
msg.ChannelName = channelName
|
msg.ChannelName = channelName
|
||||||
}
|
}
|
||||||
@@ -585,7 +515,7 @@ func (a *App) buildFullPushNotificationMessage(post *model.Post, user *model.Use
|
|||||||
userLocale := utils.GetUserTranslations(user.Locale)
|
userLocale := utils.GetUserTranslations(user.Locale)
|
||||||
hasFiles := post.FileIds != nil && len(post.FileIds) > 0
|
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
|
return msg
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -883,6 +883,7 @@ func TestGetPushNotificationMessage(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
actualMessage := th.App.getPushNotificationMessage(
|
actualMessage := th.App.getPushNotificationMessage(
|
||||||
|
pushNotificationContents,
|
||||||
tc.Message,
|
tc.Message,
|
||||||
tc.explicitMention,
|
tc.explicitMention,
|
||||||
tc.channelWideMention,
|
tc.channelWideMention,
|
||||||
@@ -943,73 +944,9 @@ func TestBuildPushNotificationMessageMentions(t *testing.T) {
|
|||||||
} {
|
} {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
receiver.NotifyProps["push"] = tc.pushNotifyProps
|
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)
|
require.Nil(t, err)
|
||||||
assert.Equal(t, tc.expectedBadge, msg.Badge)
|
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)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1541,9 +1541,9 @@ func TestPostNotificationGetChannelName(t *testing.T) {
|
|||||||
} {
|
} {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
notification := &PostNotification{
|
notification := &PostNotification{
|
||||||
channel: testCase.channel,
|
Channel: testCase.channel,
|
||||||
sender: sender,
|
Sender: sender,
|
||||||
profileMap: profileMap,
|
ProfileMap: profileMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
recipientId := recipient.Id
|
recipientId := recipient.Id
|
||||||
@@ -1626,9 +1626,9 @@ func TestPostNotificationGetSenderName(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
notification := &PostNotification{
|
notification := &PostNotification{
|
||||||
channel: channel,
|
Channel: channel,
|
||||||
post: post,
|
Post: post,
|
||||||
sender: sender,
|
Sender: sender,
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, testCase.expected, notification.GetSenderName(testCase.nameFormat, testCase.allowOverrides))
|
assert.Equal(t, testCase.expected, notification.GetSenderName(testCase.nameFormat, testCase.allowOverrides))
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ func ServerConnector(s *Server) AppOption {
|
|||||||
a.Ldap = s.Ldap
|
a.Ldap = s.Ldap
|
||||||
a.MessageExport = s.MessageExport
|
a.MessageExport = s.MessageExport
|
||||||
a.Metrics = s.Metrics
|
a.Metrics = s.Metrics
|
||||||
|
a.Notification = s.Notification
|
||||||
a.Saml = s.Saml
|
a.Saml = s.Saml
|
||||||
|
|
||||||
a.HTTPService = s.HTTPService
|
a.HTTPService = s.HTTPService
|
||||||
|
|||||||
@@ -126,6 +126,7 @@ type Server struct {
|
|||||||
Ldap einterfaces.LdapInterface
|
Ldap einterfaces.LdapInterface
|
||||||
MessageExport einterfaces.MessageExportInterface
|
MessageExport einterfaces.MessageExportInterface
|
||||||
Metrics einterfaces.MetricsInterface
|
Metrics einterfaces.MetricsInterface
|
||||||
|
Notification einterfaces.NotificationInterface
|
||||||
Saml einterfaces.SamlInterface
|
Saml einterfaces.SamlInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
einterfaces/notification.go
Обычный файл
13
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
|
||||||
|
}
|
||||||
@@ -1878,6 +1878,10 @@
|
|||||||
"id": "api.status.user_not_found.app_error",
|
"id": "api.status.user_not_found.app_error",
|
||||||
"translation": "User not found"
|
"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",
|
"id": "api.team.add_members.error",
|
||||||
"translation": "Error adding team member(s)."
|
"translation": "Error adding team member(s)."
|
||||||
@@ -3954,6 +3958,10 @@
|
|||||||
"id": "ent.elasticsearch.test_config.reenter_password",
|
"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."
|
"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",
|
"id": "ent.ldap.app_error",
|
||||||
"translation": "ldap interface was nil"
|
"translation": "ldap interface was nil"
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ type Features struct {
|
|||||||
CustomPermissionsSchemes *bool `json:"custom_permissions_schemes"`
|
CustomPermissionsSchemes *bool `json:"custom_permissions_schemes"`
|
||||||
CustomTermsOfService *bool `json:"custom_terms_of_service"`
|
CustomTermsOfService *bool `json:"custom_terms_of_service"`
|
||||||
GuestAccountsPermissions *bool `json:"guest_accounts_permissions"`
|
GuestAccountsPermissions *bool `json:"guest_accounts_permissions"`
|
||||||
|
IDLoadedPushNotifications *bool `json:"id_loaded"`
|
||||||
|
|
||||||
// after we enabled more features we'll need to control them with this
|
// after we enabled more features we'll need to control them with this
|
||||||
FutureFeatures *bool `json:"future_features"`
|
FutureFeatures *bool `json:"future_features"`
|
||||||
@@ -83,6 +84,7 @@ func (f *Features) ToMap() map[string]interface{} {
|
|||||||
"message_export": *f.MessageExport,
|
"message_export": *f.MessageExport,
|
||||||
"custom_permissions_schemes": *f.CustomPermissionsSchemes,
|
"custom_permissions_schemes": *f.CustomPermissionsSchemes,
|
||||||
"guest_accounts_permissions": *f.GuestAccountsPermissions,
|
"guest_accounts_permissions": *f.GuestAccountsPermissions,
|
||||||
|
"id_loaded": *f.IDLoadedPushNotifications,
|
||||||
"future": *f.FutureFeatures,
|
"future": *f.FutureFeatures,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -171,6 +173,10 @@ func (f *Features) SetDefaults() {
|
|||||||
if f.CustomTermsOfService == nil {
|
if f.CustomTermsOfService == nil {
|
||||||
f.CustomTermsOfService = NewBool(*f.FutureFeatures)
|
f.CustomTermsOfService = NewBool(*f.FutureFeatures)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if f.IDLoadedPushNotifications == nil {
|
||||||
|
f.IDLoadedPushNotifications = NewBool(*f.FutureFeatures)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *License) IsExpired() bool {
|
func (l *License) IsExpired() bool {
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ func TestLicenseFeaturesToMap(t *testing.T) {
|
|||||||
CheckTrue(t, m["data_retention"].(bool))
|
CheckTrue(t, m["data_retention"].(bool))
|
||||||
CheckTrue(t, m["message_export"].(bool))
|
CheckTrue(t, m["message_export"].(bool))
|
||||||
CheckTrue(t, m["custom_permissions_schemes"].(bool))
|
CheckTrue(t, m["custom_permissions_schemes"].(bool))
|
||||||
|
CheckTrue(t, m["id_loaded"].(bool))
|
||||||
CheckTrue(t, m["future"].(bool))
|
CheckTrue(t, m["future"].(bool))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,6 +56,7 @@ func TestLicenseFeaturesSetDefaults(t *testing.T) {
|
|||||||
CheckTrue(t, *f.MessageExport)
|
CheckTrue(t, *f.MessageExport)
|
||||||
CheckTrue(t, *f.CustomPermissionsSchemes)
|
CheckTrue(t, *f.CustomPermissionsSchemes)
|
||||||
CheckTrue(t, *f.GuestAccountsPermissions)
|
CheckTrue(t, *f.GuestAccountsPermissions)
|
||||||
|
CheckTrue(t, *f.IDLoadedPushNotifications)
|
||||||
CheckTrue(t, *f.FutureFeatures)
|
CheckTrue(t, *f.FutureFeatures)
|
||||||
|
|
||||||
f = Features{}
|
f = Features{}
|
||||||
@@ -78,6 +80,7 @@ func TestLicenseFeaturesSetDefaults(t *testing.T) {
|
|||||||
*f.CustomPermissionsSchemes = true
|
*f.CustomPermissionsSchemes = true
|
||||||
*f.GuestAccountsPermissions = true
|
*f.GuestAccountsPermissions = true
|
||||||
*f.EmailNotificationContents = true
|
*f.EmailNotificationContents = true
|
||||||
|
*f.IDLoadedPushNotifications = true
|
||||||
|
|
||||||
f.SetDefaults()
|
f.SetDefaults()
|
||||||
|
|
||||||
@@ -98,6 +101,7 @@ func TestLicenseFeaturesSetDefaults(t *testing.T) {
|
|||||||
CheckTrue(t, *f.MessageExport)
|
CheckTrue(t, *f.MessageExport)
|
||||||
CheckTrue(t, *f.CustomPermissionsSchemes)
|
CheckTrue(t, *f.CustomPermissionsSchemes)
|
||||||
CheckTrue(t, *f.GuestAccountsPermissions)
|
CheckTrue(t, *f.GuestAccountsPermissions)
|
||||||
|
CheckTrue(t, *f.IDLoadedPushNotifications)
|
||||||
CheckFalse(t, *f.FutureFeatures)
|
CheckFalse(t, *f.FutureFeatures)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,6 +177,7 @@ func TestLicenseToFromJson(t *testing.T) {
|
|||||||
CheckBool(t, *f1.MessageExport, *f.MessageExport)
|
CheckBool(t, *f1.MessageExport, *f.MessageExport)
|
||||||
CheckBool(t, *f1.CustomPermissionsSchemes, *f.CustomPermissionsSchemes)
|
CheckBool(t, *f1.CustomPermissionsSchemes, *f.CustomPermissionsSchemes)
|
||||||
CheckBool(t, *f1.GuestAccountsPermissions, *f.GuestAccountsPermissions)
|
CheckBool(t, *f1.GuestAccountsPermissions, *f.GuestAccountsPermissions)
|
||||||
|
CheckBool(t, *f1.IDLoadedPushNotifications, *f.IDLoadedPushNotifications)
|
||||||
CheckBool(t, *f1.FutureFeatures, *f.FutureFeatures)
|
CheckBool(t, *f1.FutureFeatures, *f.FutureFeatures)
|
||||||
|
|
||||||
invalid := `{"asdf`
|
invalid := `{"asdf`
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ const (
|
|||||||
PUSH_NOTIFY_APPLE_REACT_NATIVE = "apple_rn"
|
PUSH_NOTIFY_APPLE_REACT_NATIVE = "apple_rn"
|
||||||
PUSH_NOTIFY_ANDROID_REACT_NATIVE = "android_rn"
|
PUSH_NOTIFY_ANDROID_REACT_NATIVE = "android_rn"
|
||||||
|
|
||||||
PUSH_TYPE_ID_LOADED = "id_loaded"
|
|
||||||
PUSH_TYPE_MESSAGE = "message"
|
PUSH_TYPE_MESSAGE = "message"
|
||||||
PUSH_TYPE_CLEAR = "clear"
|
PUSH_TYPE_CLEAR = "clear"
|
||||||
PUSH_TYPE_UPDATE_BADGE = "update_badge"
|
PUSH_TYPE_UPDATE_BADGE = "update_badge"
|
||||||
@@ -41,6 +40,7 @@ type PushNotificationAck struct {
|
|||||||
ClientPlatform string `json:"platform"`
|
ClientPlatform string `json:"platform"`
|
||||||
NotificationType string `json:"type"`
|
NotificationType string `json:"type"`
|
||||||
PostId string `json:"post_id,omitempty"`
|
PostId string `json:"post_id,omitempty"`
|
||||||
|
IsIdLoaded bool `json:"is_id_loaded"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PushNotification struct {
|
type PushNotification struct {
|
||||||
@@ -65,6 +65,7 @@ type PushNotification struct {
|
|||||||
OverrideIconUrl string `json:"override_icon_url,omitempty"`
|
OverrideIconUrl string `json:"override_icon_url,omitempty"`
|
||||||
FromWebhook string `json:"from_webhook,omitempty"`
|
FromWebhook string `json:"from_webhook,omitempty"`
|
||||||
Version string `json:"version,omitempty"`
|
Version string `json:"version,omitempty"`
|
||||||
|
IsIdLoaded bool `json:"is_id_loaded"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (me *PushNotification) ToJson() string {
|
func (me *PushNotification) ToJson() string {
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ func GetClientLicense(l *model.License) map[string]string {
|
|||||||
props["Announcement"] = strconv.FormatBool(*l.Features.Announcement)
|
props["Announcement"] = strconv.FormatBool(*l.Features.Announcement)
|
||||||
props["Elasticsearch"] = strconv.FormatBool(*l.Features.Elasticsearch)
|
props["Elasticsearch"] = strconv.FormatBool(*l.Features.Elasticsearch)
|
||||||
props["DataRetention"] = strconv.FormatBool(*l.Features.DataRetention)
|
props["DataRetention"] = strconv.FormatBool(*l.Features.DataRetention)
|
||||||
|
props["IDLoadedPushNotifications"] = strconv.FormatBool(*l.Features.IDLoadedPushNotifications)
|
||||||
props["IssuedAt"] = strconv.FormatInt(l.IssuedAt, 10)
|
props["IssuedAt"] = strconv.FormatInt(l.IssuedAt, 10)
|
||||||
props["StartsAt"] = strconv.FormatInt(l.StartsAt, 10)
|
props["StartsAt"] = strconv.FormatInt(l.StartsAt, 10)
|
||||||
props["ExpiresAt"] = strconv.FormatInt(l.ExpiresAt, 10)
|
props["ExpiresAt"] = strconv.FormatInt(l.ExpiresAt, 10)
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user