diff options
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | app/notification.go | 130 | ||||
-rw-r--r-- | app/notification_test.go | 302 | ||||
-rw-r--r-- | cmd/mattermost/commands/server.go | 20 | ||||
-rw-r--r-- | cmd/mattermost/commands/server_test.go | 10 | ||||
-rw-r--r-- | config/default.json | 1 | ||||
-rw-r--r-- | i18n/de.json | 44 | ||||
-rw-r--r-- | i18n/en.json | 86 | ||||
-rw-r--r-- | i18n/es.json | 44 | ||||
-rw-r--r-- | i18n/fr.json | 44 | ||||
-rw-r--r-- | i18n/it.json | 44 | ||||
-rw-r--r-- | i18n/ja.json | 80 | ||||
-rw-r--r-- | i18n/ko.json | 44 | ||||
-rw-r--r-- | i18n/nl.json | 44 | ||||
-rw-r--r-- | i18n/pl.json | 44 | ||||
-rw-r--r-- | i18n/pt-BR.json | 44 | ||||
-rw-r--r-- | i18n/ru.json | 44 | ||||
-rw-r--r-- | i18n/tr.json | 44 | ||||
-rw-r--r-- | i18n/zh-CN.json | 44 | ||||
-rw-r--r-- | i18n/zh-TW.json | 44 | ||||
-rw-r--r-- | model/config.go | 45 | ||||
-rw-r--r-- | model/config_test.go | 90 | ||||
-rw-r--r-- | utils/config.go | 2 |
23 files changed, 1014 insertions, 282 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d19e4f63..b8b904efe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,3 @@ # Mattermost Changelog -Please see [Mattermost Team Edition Changelog](http://docs.mattermost.com/administration/changelog.html) in product documentation. +Please see [Mattermost Changelog](http://docs.mattermost.com/administration/changelog.html) in product documentation. diff --git a/app/notification.go b/app/notification.go index 0fbc33060..401675f4e 100644 --- a/app/notification.go +++ b/app/notification.go @@ -23,6 +23,11 @@ import ( "github.com/nicksnyder/go-i18n/i18n" ) +const ( + THREAD_ANY = "any" + THREAD_ROOT = "root" +) + func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *model.Channel, sender *model.User, parentPostList *model.PostList) ([]string, *model.AppError) { pchan := a.Srv.Store.User().GetAllProfilesInChannel(channel.Id, true) cmnchan := a.Srv.Store.Channel().GetAllChannelMembersNotifyPropsForChannel(channel.Id, true) @@ -47,6 +52,7 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod } mentionedUserIds := make(map[string]bool) + threadMentionedUserIds := make(map[string]string) allActivityPushUserIds := []string{} hereNotification := false channelNotification := false @@ -106,8 +112,16 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod if len(post.RootId) > 0 && parentPostList != nil { for _, threadPost := range parentPostList.Posts { profile := profileMap[threadPost.UserId] - if profile != nil && (profile.NotifyProps["comments"] == "any" || (profile.NotifyProps["comments"] == "root" && threadPost.Id == parentPostList.Order[0])) { - mentionedUserIds[threadPost.UserId] = true + if profile != nil && (profile.NotifyProps["comments"] == THREAD_ANY || (profile.NotifyProps["comments"] == THREAD_ROOT && threadPost.Id == parentPostList.Order[0])) { + if threadPost.Id == parentPostList.Order[0] { + threadMentionedUserIds[threadPost.UserId] = THREAD_ROOT + } else { + threadMentionedUserIds[threadPost.UserId] = THREAD_ANY + } + + if _, ok := mentionedUserIds[threadPost.UserId]; !ok { + mentionedUserIds[threadPost.UserId] = false + } } } } @@ -145,6 +159,7 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod updateMentionChans = append(updateMentionChans, a.Srv.Store.Channel().IncrementMentionCount(post.ChannelId, id)) } + var senderUsername string senderName := "" channelName := "" if post.IsSystemMessage() { @@ -152,8 +167,10 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod } else { if value, ok := post.Props["override_username"]; ok && post.Props["from_webhook"] == "true" { senderName = value.(string) + senderUsername = value.(string) } else { senderName = sender.Username + senderUsername = sender.Username } } @@ -170,13 +187,6 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod channelName = channel.DisplayName } - var senderUsername string - if value, ok := post.Props["override_username"]; ok && post.Props["from_webhook"] == "true" { - senderUsername = value.(string) - } else { - senderUsername = sender.Username - } - if a.Config().EmailSettings.SendEmailNotifications { for _, id := range mentionedUsersList { if profileMap[id] == nil { @@ -216,7 +226,9 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod } } - if userAllowsEmails && status.Status != model.STATUS_ONLINE && profileMap[id].DeleteAt == 0 { + autoResponderRelated := status.Status == model.STATUS_OUT_OF_OFFICE || post.Type == model.POST_AUTO_RESPONDER + + if userAllowsEmails && status.Status != model.STATUS_ONLINE && profileMap[id].DeleteAt == 0 && !autoResponderRelated { a.sendNotificationEmail(post, profileMap[id], channel, team, channelName, senderName, sender) } } @@ -294,7 +306,22 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod } if ShouldSendPushNotification(profileMap[id], channelMemberNotifyPropsMap[id], true, status, post) { - a.sendPushNotification(post, profileMap[id], channel, senderName, channelName, true) + replyToThreadType := "" + if value, ok := threadMentionedUserIds[id]; ok { + replyToThreadType = value + } + + a.sendPushNotification( + post, + profileMap[id], + channel, + channelName, + sender, + senderName, + mentionedUserIds[id], + (channelNotification || allNotification), + replyToThreadType, + ) } } @@ -311,7 +338,17 @@ func (a *App) SendNotifications(post *model.Post, team *model.Team, channel *mod } if ShouldSendPushNotification(profileMap[id], channelMemberNotifyPropsMap[id], false, status, post) { - a.sendPushNotification(post, profileMap[id], channel, senderName, channelName, false) + a.sendPushNotification( + post, + profileMap[id], + channel, + channelName, + sender, + senderName, + false, + false, + "", + ) } } } @@ -655,14 +692,26 @@ func (a *App) GetMessageForNotification(post *model.Post, translateFunc i18n.Tra } } -func (a *App) sendPushNotification(post *model.Post, user *model.User, channel *model.Channel, senderName, channelName string, wasMentioned bool) *model.AppError { +func (a *App) sendPushNotification(post *model.Post, user *model.User, channel *model.Channel, channelName string, sender *model.User, senderName string, + explicitMention, channelWideMention bool, replyToThreadType string) *model.AppError { + contentsConfig := *a.Config().EmailSettings.PushNotificationContents sessions, err := a.getMobileAppSessions(user.Id) if err != nil { return err } if channel.Type == model.CHANNEL_DIRECT { - channelName = senderName + if senderName == utils.T("system.message.name") { + channelName = senderName + } else { + preference, prefError := a.GetPreferenceByCategoryAndNameForUser(user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "name_format") + if prefError != nil { + channelName = fmt.Sprintf("@%v", senderName) + } else { + channelName = fmt.Sprintf("@%v", sender.GetDisplayName(preference.Value)) + senderName = channelName + } + } } msg := model.PushNotification{} @@ -678,9 +727,12 @@ func (a *App) sendPushNotification(post *model.Post, user *model.User, channel * msg.ChannelId = channel.Id msg.PostId = post.Id msg.RootId = post.RootId - msg.ChannelName = channel.Name msg.SenderId = post.UserId + if contentsConfig != model.GENERIC_NO_CHANNEL_NOTIFICATION || channel.Type == model.CHANNEL_DIRECT { + msg.ChannelName = channelName + } + if ou, ok := post.Props["override_username"].(string); ok { msg.OverrideUsername = ou } @@ -696,7 +748,7 @@ func (a *App) sendPushNotification(post *model.Post, user *model.User, channel * userLocale := utils.GetUserTranslations(user.Locale) hasFiles := post.FileIds != nil && len(post.FileIds) > 0 - msg.Message, msg.Category = a.getPushNotificationMessage(post.Message, wasMentioned, hasFiles, senderName, channelName, channel.Type, userLocale) + msg.Message = a.getPushNotificationMessage(post.Message, explicitMention, channelWideMention, hasFiles, senderName, channelName, channel.Type, replyToThreadType, userLocale) for _, session := range sessions { tmpMessage := *model.PushNotificationFromJson(strings.NewReader(msg.ToJson())) @@ -718,56 +770,44 @@ func (a *App) sendPushNotification(post *model.Post, user *model.User, channel * return nil } -func (a *App) getPushNotificationMessage(postMessage string, wasMentioned bool, hasFiles bool, senderName string, channelName string, channelType string, userLocale i18n.TranslateFunc) (string, string) { +func (a *App) getPushNotificationMessage(postMessage string, explicitMention, channelWideMention, hasFiles bool, + senderName, channelName, channelType, replyToThreadType string, userLocale i18n.TranslateFunc) string { message := "" - category := "" contentsConfig := *a.Config().EmailSettings.PushNotificationContents if contentsConfig == model.FULL_NOTIFICATION { - category = model.CATEGORY_CAN_REPLY - if channelType == model.CHANNEL_DIRECT { - message = senderName + ": " + model.ClearMentionTags(postMessage) + message = model.ClearMentionTags(postMessage) } else { - message = senderName + userLocale("api.post.send_notifications_and_forget.push_in") + channelName + ": " + model.ClearMentionTags(postMessage) - } - } else if contentsConfig == model.GENERIC_NO_CHANNEL_NOTIFICATION { - if channelType == model.CHANNEL_DIRECT { - category = model.CATEGORY_CAN_REPLY - - message = senderName + userLocale("api.post.send_notifications_and_forget.push_message") - } else if wasMentioned { - message = senderName + userLocale("api.post.send_notifications_and_forget.push_mention_no_channel") - } else { - message = senderName + userLocale("api.post.send_notifications_and_forget.push_non_mention_no_channel") + message = "@" + senderName + ": " + model.ClearMentionTags(postMessage) } } else { if channelType == model.CHANNEL_DIRECT { - category = model.CATEGORY_CAN_REPLY - - message = senderName + userLocale("api.post.send_notifications_and_forget.push_message") - } else if wasMentioned { - category = model.CATEGORY_CAN_REPLY - - message = senderName + userLocale("api.post.send_notifications_and_forget.push_mention") + channelName + message = userLocale("api.post.send_notifications_and_forget.push_message") + } else if channelWideMention { + message = "@" + senderName + userLocale("api.post.send_notification_and_forget.push_channel_mention") + } else if explicitMention { + message = "@" + senderName + userLocale("api.post.send_notifications_and_forget.push_explicit_mention") + } else if replyToThreadType == THREAD_ROOT { + message = "@" + senderName + userLocale("api.post.send_notification_and_forget.push_comment_on_post") + } else if replyToThreadType == THREAD_ANY { + message = "@" + senderName + userLocale("api.post.send_notification_and_forget.push_comment_on_thread") } else { - message = senderName + userLocale("api.post.send_notifications_and_forget.push_non_mention") + channelName + message = "@" + senderName + userLocale("api.post.send_notifications_and_forget.push_general_message") } } // If the post only has images then push an appropriate message if len(postMessage) == 0 && hasFiles { if channelType == model.CHANNEL_DIRECT { - message = senderName + userLocale("api.post.send_notifications_and_forget.push_image_only_dm") - } else if contentsConfig == model.GENERIC_NO_CHANNEL_NOTIFICATION { - message = senderName + userLocale("api.post.send_notifications_and_forget.push_image_only_no_channel") + message = strings.Trim(userLocale("api.post.send_notifications_and_forget.push_image_only"), " ") } else { - message = senderName + userLocale("api.post.send_notifications_and_forget.push_image_only") + channelName + message = "@" + senderName + userLocale("api.post.send_notifications_and_forget.push_image_only") } } - return message, category + return message } func (a *App) ClearPushNotification(userId string, channelId string) { diff --git a/app/notification_test.go b/app/notification_test.go index 8fbcf3a78..1a4fb2859 100644 --- a/app/notification_test.go +++ b/app/notification_test.go @@ -1389,207 +1389,327 @@ func TestGetPushNotificationMessage(t *testing.T) { for name, tc := range map[string]struct { Message string - WasMentioned bool + explicitMention bool + channelWideMention bool HasFiles bool + replyToThreadType string Locale string PushNotificationContents string ChannelType string - ExpectedMessage string - ExpectedCategory string + ExpectedMessage string }{ "full message, public channel, no mention": { - Message: "this is a message", - ChannelType: model.CHANNEL_OPEN, - ExpectedMessage: "user in channel: this is a message", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + Message: "this is a message", + ChannelType: model.CHANNEL_OPEN, + ExpectedMessage: "@user: this is a message", }, "full message, public channel, mention": { - Message: "this is a message", - WasMentioned: true, - ChannelType: model.CHANNEL_OPEN, - ExpectedMessage: "user in channel: this is a message", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + Message: "this is a message", + explicitMention: true, + ChannelType: model.CHANNEL_OPEN, + ExpectedMessage: "@user: this is a message", + }, + "full message, public channel, channel wide mention": { + Message: "this is a message", + channelWideMention: true, + ChannelType: model.CHANNEL_OPEN, + ExpectedMessage: "@user: this is a message", + }, + "full message, public channel, commented on post": { + Message: "this is a message", + replyToThreadType: THREAD_ROOT, + ChannelType: model.CHANNEL_OPEN, + ExpectedMessage: "@user: this is a message", + }, + "full message, public channel, commented on thread": { + Message: "this is a message", + replyToThreadType: THREAD_ANY, + ChannelType: model.CHANNEL_OPEN, + ExpectedMessage: "@user: this is a message", }, "full message, private channel, no mention": { - Message: "this is a message", - ChannelType: model.CHANNEL_PRIVATE, - ExpectedMessage: "user in channel: this is a message", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + Message: "this is a message", + ChannelType: model.CHANNEL_PRIVATE, + ExpectedMessage: "@user: this is a message", }, "full message, private channel, mention": { - Message: "this is a message", - WasMentioned: true, - ChannelType: model.CHANNEL_PRIVATE, - ExpectedMessage: "user in channel: this is a message", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + Message: "this is a message", + explicitMention: true, + ChannelType: model.CHANNEL_PRIVATE, + ExpectedMessage: "@user: this is a message", + }, + "full message, private channel, commented on post": { + Message: "this is a message", + replyToThreadType: THREAD_ROOT, + ChannelType: model.CHANNEL_PRIVATE, + ExpectedMessage: "@user: this is a message", + }, + "full message, private channel, commented on thread": { + Message: "this is a message", + replyToThreadType: THREAD_ANY, + ChannelType: model.CHANNEL_PRIVATE, + ExpectedMessage: "@user: this is a message", }, "full message, group message channel, no mention": { - Message: "this is a message", - ChannelType: model.CHANNEL_GROUP, - ExpectedMessage: "user in channel: this is a message", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + Message: "this is a message", + ChannelType: model.CHANNEL_GROUP, + ExpectedMessage: "@user: this is a message", }, "full message, group message channel, mention": { - Message: "this is a message", - WasMentioned: true, - ChannelType: model.CHANNEL_GROUP, - ExpectedMessage: "user in channel: this is a message", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + Message: "this is a message", + explicitMention: true, + ChannelType: model.CHANNEL_GROUP, + ExpectedMessage: "@user: this is a message", + }, + "full message, group message channel, commented on post": { + Message: "this is a message", + replyToThreadType: THREAD_ROOT, + ChannelType: model.CHANNEL_GROUP, + ExpectedMessage: "@user: this is a message", + }, + "full message, group message channel, commented on thread": { + Message: "this is a message", + replyToThreadType: THREAD_ANY, + ChannelType: model.CHANNEL_GROUP, + ExpectedMessage: "@user: this is a message", }, "full message, direct message channel, no mention": { - Message: "this is a message", - ChannelType: model.CHANNEL_DIRECT, - ExpectedMessage: "user: this is a message", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + Message: "this is a message", + ChannelType: model.CHANNEL_DIRECT, + ExpectedMessage: "this is a message", }, "full message, direct message channel, mention": { - Message: "this is a message", - WasMentioned: true, - ChannelType: model.CHANNEL_DIRECT, - ExpectedMessage: "user: this is a message", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + Message: "this is a message", + explicitMention: true, + ChannelType: model.CHANNEL_DIRECT, + ExpectedMessage: "this is a message", + }, + "full message, direct message channel, commented on post": { + Message: "this is a message", + replyToThreadType: THREAD_ROOT, + ChannelType: model.CHANNEL_DIRECT, + ExpectedMessage: "this is a message", + }, + "full message, direct message channel, commented on thread": { + Message: "this is a message", + replyToThreadType: THREAD_ANY, + ChannelType: model.CHANNEL_DIRECT, + ExpectedMessage: "this is a message", }, "generic message with channel, public channel, no mention": { Message: "this is a message", PushNotificationContents: model.GENERIC_NOTIFICATION, ChannelType: model.CHANNEL_OPEN, - ExpectedMessage: "user posted in channel", + ExpectedMessage: "@user posted a message.", }, "generic message with channel, public channel, mention": { Message: "this is a message", - WasMentioned: true, + explicitMention: true, PushNotificationContents: model.GENERIC_NOTIFICATION, ChannelType: model.CHANNEL_OPEN, - ExpectedMessage: "user mentioned you in channel", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + ExpectedMessage: "@user mentioned you.", + }, + "generic message with channel, public channel, channel wide mention": { + Message: "this is a message", + channelWideMention: true, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_OPEN, + ExpectedMessage: "@user notified the channel.", + }, + "generic message, public channel, commented on post": { + Message: "this is a message", + replyToThreadType: THREAD_ROOT, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_OPEN, + ExpectedMessage: "@user commented on your post.", + }, + "generic message, public channel, commented on thread": { + Message: "this is a message", + replyToThreadType: THREAD_ANY, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_OPEN, + ExpectedMessage: "@user commented on a thread you participated in.", }, "generic message with channel, private channel, no mention": { Message: "this is a message", PushNotificationContents: model.GENERIC_NOTIFICATION, ChannelType: model.CHANNEL_PRIVATE, - ExpectedMessage: "user posted in channel", + ExpectedMessage: "@user posted a message.", }, "generic message with channel, private channel, mention": { Message: "this is a message", - WasMentioned: true, + explicitMention: true, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_PRIVATE, + ExpectedMessage: "@user mentioned you.", + }, + "generic message with channel, private channel, channel wide mention": { + Message: "this is a message", + channelWideMention: true, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_PRIVATE, + ExpectedMessage: "@user notified the channel.", + }, + "generic message, public private, commented on post": { + Message: "this is a message", + replyToThreadType: THREAD_ROOT, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_PRIVATE, + ExpectedMessage: "@user commented on your post.", + }, + "generic message, public private, commented on thread": { + Message: "this is a message", + replyToThreadType: THREAD_ANY, PushNotificationContents: model.GENERIC_NOTIFICATION, ChannelType: model.CHANNEL_PRIVATE, - ExpectedMessage: "user mentioned you in channel", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + ExpectedMessage: "@user commented on a thread you participated in.", }, "generic message with channel, group message channel, no mention": { Message: "this is a message", PushNotificationContents: model.GENERIC_NOTIFICATION, ChannelType: model.CHANNEL_GROUP, - ExpectedMessage: "user posted in channel", + ExpectedMessage: "@user posted a message.", }, "generic message with channel, group message channel, mention": { Message: "this is a message", - WasMentioned: true, + explicitMention: true, PushNotificationContents: model.GENERIC_NOTIFICATION, ChannelType: model.CHANNEL_GROUP, - ExpectedMessage: "user mentioned you in channel", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + ExpectedMessage: "@user mentioned you.", + }, + "generic message with channel, group message channel, channel wide mention": { + Message: "this is a message", + channelWideMention: true, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_GROUP, + ExpectedMessage: "@user notified the channel.", + }, + "generic message, group message channel, commented on post": { + Message: "this is a message", + replyToThreadType: THREAD_ROOT, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_GROUP, + ExpectedMessage: "@user commented on your post.", + }, + "generic message, group message channel, commented on thread": { + Message: "this is a message", + replyToThreadType: THREAD_ANY, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_GROUP, + ExpectedMessage: "@user commented on a thread you participated in.", }, "generic message with channel, direct message channel, no mention": { Message: "this is a message", PushNotificationContents: model.GENERIC_NOTIFICATION, ChannelType: model.CHANNEL_DIRECT, - ExpectedMessage: "user sent you a direct message", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + ExpectedMessage: "sent you a message.", }, "generic message with channel, direct message channel, mention": { Message: "this is a message", - WasMentioned: true, + explicitMention: true, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_DIRECT, + ExpectedMessage: "sent you a message.", + }, + "generic message with channel, direct message channel, channel wide mention": { + Message: "this is a message", + channelWideMention: true, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_DIRECT, + ExpectedMessage: "sent you a message.", + }, + "generic message, direct message channel, commented on post": { + Message: "this is a message", + replyToThreadType: THREAD_ROOT, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_DIRECT, + ExpectedMessage: "sent you a message.", + }, + "generic message, direct message channel, commented on thread": { + Message: "this is a message", + replyToThreadType: THREAD_ANY, PushNotificationContents: model.GENERIC_NOTIFICATION, ChannelType: model.CHANNEL_DIRECT, - ExpectedMessage: "user sent you a direct message", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + ExpectedMessage: "sent you a message.", }, "generic message without channel, public channel, no mention": { Message: "this is a message", PushNotificationContents: model.GENERIC_NO_CHANNEL_NOTIFICATION, ChannelType: model.CHANNEL_OPEN, - ExpectedMessage: "user posted a message", + ExpectedMessage: "@user posted a message.", }, "generic message without channel, public channel, mention": { Message: "this is a message", - WasMentioned: true, + explicitMention: true, PushNotificationContents: model.GENERIC_NO_CHANNEL_NOTIFICATION, ChannelType: model.CHANNEL_OPEN, - ExpectedMessage: "user mentioned you", + ExpectedMessage: "@user mentioned you.", }, "generic message without channel, private channel, no mention": { Message: "this is a message", PushNotificationContents: model.GENERIC_NO_CHANNEL_NOTIFICATION, ChannelType: model.CHANNEL_PRIVATE, - ExpectedMessage: "user posted a message", + ExpectedMessage: "@user posted a message.", }, "generic message without channel, private channel, mention": { Message: "this is a message", - WasMentioned: true, + explicitMention: true, PushNotificationContents: model.GENERIC_NO_CHANNEL_NOTIFICATION, ChannelType: model.CHANNEL_PRIVATE, - ExpectedMessage: "user mentioned you", + ExpectedMessage: "@user mentioned you.", }, "generic message without channel, group message channel, no mention": { Message: "this is a message", PushNotificationContents: model.GENERIC_NO_CHANNEL_NOTIFICATION, ChannelType: model.CHANNEL_GROUP, - ExpectedMessage: "user posted a message", + ExpectedMessage: "@user posted a message.", }, "generic message without channel, group message channel, mention": { Message: "this is a message", - WasMentioned: true, + explicitMention: true, PushNotificationContents: model.GENERIC_NO_CHANNEL_NOTIFICATION, ChannelType: model.CHANNEL_GROUP, - ExpectedMessage: "user mentioned you", + ExpectedMessage: "@user mentioned you.", }, "generic message without channel, direct message channel, no mention": { Message: "this is a message", PushNotificationContents: model.GENERIC_NO_CHANNEL_NOTIFICATION, ChannelType: model.CHANNEL_DIRECT, - ExpectedMessage: "user sent you a direct message", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + ExpectedMessage: "sent you a message.", }, "generic message without channel, direct message channel, mention": { Message: "this is a message", - WasMentioned: true, + explicitMention: true, PushNotificationContents: model.GENERIC_NO_CHANNEL_NOTIFICATION, ChannelType: model.CHANNEL_DIRECT, - ExpectedMessage: "user sent you a direct message", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + ExpectedMessage: "sent you a message.", }, "only files, public channel": { - HasFiles: true, - ChannelType: model.CHANNEL_OPEN, - ExpectedMessage: "user uploaded one or more files in channel", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + HasFiles: true, + ChannelType: model.CHANNEL_OPEN, + ExpectedMessage: "@user attached a file.", }, "only files, private channel": { - HasFiles: true, - ChannelType: model.CHANNEL_PRIVATE, - ExpectedMessage: "user uploaded one or more files in channel", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + HasFiles: true, + ChannelType: model.CHANNEL_PRIVATE, + ExpectedMessage: "@user attached a file.", }, "only files, group message channel": { - HasFiles: true, - ChannelType: model.CHANNEL_GROUP, - ExpectedMessage: "user uploaded one or more files in channel", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + HasFiles: true, + ChannelType: model.CHANNEL_GROUP, + ExpectedMessage: "@user attached a file.", }, "only files, direct message channel": { - HasFiles: true, - ChannelType: model.CHANNEL_DIRECT, - ExpectedMessage: "user uploaded one or more files in a direct message", - ExpectedCategory: model.CATEGORY_CAN_REPLY, + HasFiles: true, + ChannelType: model.CHANNEL_DIRECT, + ExpectedMessage: "attached a file.", }, "only files without channel, public channel": { HasFiles: true, PushNotificationContents: model.GENERIC_NO_CHANNEL_NOTIFICATION, ChannelType: model.CHANNEL_OPEN, - ExpectedMessage: "user uploaded one or more files", + ExpectedMessage: "@user attached a file.", }, } { t.Run(name, func(t *testing.T) { @@ -1607,18 +1727,18 @@ func TestGetPushNotificationMessage(t *testing.T) { *cfg.EmailSettings.PushNotificationContents = pushNotificationContents }) - if actualMessage, actualCategory := th.App.getPushNotificationMessage( + if actualMessage := th.App.getPushNotificationMessage( tc.Message, - tc.WasMentioned, + tc.explicitMention, + tc.channelWideMention, tc.HasFiles, "user", "channel", tc.ChannelType, + tc.replyToThreadType, utils.GetUserTranslations(locale), ); actualMessage != tc.ExpectedMessage { t.Fatalf("Received incorrect push notification message `%v`, expected `%v`", actualMessage, tc.ExpectedMessage) - } else if actualCategory != tc.ExpectedCategory { - t.Fatalf("Received incorrect push notification category `%v`, expected `%v`", actualCategory, tc.ExpectedCategory) } }) } diff --git a/cmd/mattermost/commands/server.go b/cmd/mattermost/commands/server.go index 67e2f69c5..10b44ad83 100644 --- a/cmd/mattermost/commands/server.go +++ b/cmd/mattermost/commands/server.go @@ -6,7 +6,6 @@ package commands import ( "fmt" "net" - "net/http" "net/url" "os" "os/signal" @@ -74,6 +73,11 @@ func runServer(configFileLocation string, disableConfigWatch bool, usedPlatform if usedPlatform { mlog.Error("The platform binary has been deprecated, please switch to using the mattermost binary.") } + + if _, err := url.ParseRequestURI(*a.Config().ServiceSettings.SiteURL); err != nil { + mlog.Error("SiteURL must be set. Some features will operate incorrectly if the SiteURL is not set. See documentation for details: http://about.mattermost.com/default-site-url") + } + mlog.Info(fmt.Sprintf("Current version is %v (%v/%v/%v/%v)", model.CurrentVersion, model.BuildNumber, model.BuildDate, model.BuildHash, model.BuildHashEnterprise)) mlog.Info(fmt.Sprintf("Enterprise Enabled: %v", model.BuildEnterpriseReady)) mlog.Info(fmt.Sprintf("Current working directory is %v", pwd)) @@ -132,19 +136,7 @@ func runServer(configFileLocation string, disableConfigWatch bool, usedPlatform // Enable developer settings if this is a "dev" build if model.BuildNumber == "dev" { - a.UpdateConfig(func(cfg *model.Config) { - *cfg.ServiceSettings.EnableDeveloper = true - if *cfg.ServiceSettings.SiteURL == "" { - *cfg.ServiceSettings.SiteURL = "http://localhost:8065" - } - }) - } - - // SiteURL should be set at this point. Either by a user or by the dev mode above - // This is here instead of in config.IsValid because there are many tests that make the assumption - // that the default config is valid. Which it is not. - if _, err := url.ParseRequestURI(*a.Config().ServiceSettings.SiteURL); err != nil { - return model.NewAppError("Config.IsValid", "model.config.is_valid.site_url.app_error", nil, "", http.StatusBadRequest) + a.UpdateConfig(func(cfg *model.Config) { *cfg.ServiceSettings.EnableDeveloper = true }) } resetStatuses(a) diff --git a/cmd/mattermost/commands/server_test.go b/cmd/mattermost/commands/server_test.go index a0c7c6948..0f825e316 100644 --- a/cmd/mattermost/commands/server_test.go +++ b/cmd/mattermost/commands/server_test.go @@ -11,7 +11,6 @@ import ( "testing" "github.com/mattermost/mattermost-server/jobs" - "github.com/mattermost/mattermost-server/model" "github.com/mattermost/mattermost-server/utils" "github.com/stretchr/testify/require" ) @@ -21,7 +20,6 @@ type ServerTestHelper struct { disableConfigWatch bool interruptChan chan os.Signal originalInterval int - oldBuildNumber string } func SetupServerTest() *ServerTestHelper { @@ -43,20 +41,14 @@ func SetupServerTest() *ServerTestHelper { interruptChan: interruptChan, originalInterval: originalInterval, } - - // Run in dev mode so SiteURL gets set - th.oldBuildNumber = model.BuildNumber - model.BuildNumber = "dev" - return th } func (th *ServerTestHelper) TearDownServerTest() { jobs.DEFAULT_WATCHER_POLLING_INTERVAL = th.originalInterval - model.BuildNumber = th.oldBuildNumber } -func TestRunServerSiteURL(t *testing.T) { +func TestRunServerSuccess(t *testing.T) { th := SetupServerTest() defer th.TearDownServerTest() diff --git a/config/default.json b/config/default.json index 3548339d0..9f35ad7d1 100644 --- a/config/default.json +++ b/config/default.json @@ -97,6 +97,7 @@ "ExperimentalPrimaryTeam": "" }, "DisplaySettings": { + "CustomUrlSchemes": [], "ExperimentalTimezone": false }, "ClientRequirements": { diff --git a/i18n/de.json b/i18n/de.json index 58c4829e8..314fbfdfb 100644 --- a/i18n/de.json +++ b/i18n/de.json @@ -2515,6 +2515,18 @@ "translation": "Gruppennachricht" }, { + "id": "api.templates.deactivate_body.info", + "translation": "You deactivated your account on {{ .SiteURL }}.<br>If this change wasn't initiated by you or you want to reactivate your account, contact your system administrator." + }, + { + "id": "api.templates.deactivate_body.title", + "translation": "Your account has been deactivated at {{ .ServerURL }}" + }, + { + "id": "api.templates.deactivate_subject", + "translation": "[{{ .SiteName }}] Your account at {{ .ServerURL }} has been deactivated" + }, + { "id": "api.templates.email_change_body.info", "translation": "Ihre E-Mail-Adresse für {{.TeamDisplayName}} wurde in {{.NewEmail}} geändert.<br>Wenn Sie diese Änderungen nicht durchgeführt haben, kontaktieren Sie bitte den Systemadministrator." }, @@ -3023,6 +3035,10 @@ "translation": "SAML 2.0 ist auf diesem Server nicht konfiguriert oder wird nicht unterstützt." }, { + "id": "api.user.send_deactivate_email_and_forget.failed.error", + "translation": "Failed to send the deactivate account email successfully" + }, + { "id": "api.user.send_email_change_email_and_forget.error", "translation": "Die E-Mail-Änderungsbenachrichtigung konnte nicht erfolgreich versendet werden" }, @@ -3071,6 +3087,10 @@ "translation": "Sie können den Aktivitätsstatus des SSO-Kontos nicht ändern. Bitte ändern Sie diesen über den SSO-Server." }, { + "id": "api.user.update_active.not_enable.app_error", + "translation": "You cannot deactivate yourself because this feature is not enabled. Please contact your System Administrator." + }, + { "id": "api.user.update_active.permissions.app_error", "translation": "Sie haben nicht die erforderlichen Berechtigungen" }, @@ -3719,10 +3739,6 @@ "translation": "Ungültige Kommentar-Auslöser-Benachrichtigungs-Eigenschaft des Benutzers." }, { - "id": "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", - "translation": "Ungültiger Wert für Desktop-Benachrichtigungdauer-Eigenschaft des Benutzers." - }, - { "id": "app.import.validate_user_import_data.notify_props_desktop_invalid.error", "translation": "Ungültiger Wert für Desktop-Benachrichtigungs-Eigenschaft des Benutzers." }, @@ -3855,6 +3871,10 @@ "translation": "Konnte Plugin nicht deaktivieren" }, { + "id": "app.plugin.delete_plugin_status_state.app_error", + "translation": "Unable to delete plugin status state." + }, + { "id": "app.plugin.disabled.app_error", "translation": "Plugins wurden deaktiviert. Bitte prüfen Sie Ihre Logs für Details." }, @@ -3899,10 +3919,18 @@ "translation": "Plugin ist nicht installiert" }, { + "id": "app.plugin.prepackaged.app_error", + "translation": "Cannot install prepackaged plugin" + }, + { "id": "app.plugin.remove.app_error", "translation": "Konnte Plugin nicht löschen" }, { + "id": "app.plugin.set_plugin_status_state.app_error", + "translation": "Unable to set plugin status state." + }, + { "id": "app.plugin.upload_disabled.app_error", "translation": "Plugins und/oder Plugin-Uploads wurden deaktiviert." }, @@ -4799,6 +4827,10 @@ "translation": "Konnte Multipart-Anfrage nicht erstellen" }, { + "id": "model.cluster.is_valid.id.app_error", + "translation": "Ungültige Id" + }, + { "id": "model.command.is_valid.create_at.app_error", "translation": "Erstellt am muss eine gültige Zeit sein" }, @@ -7527,6 +7559,10 @@ "translation": "Der Kanal konnte nicht gefunden werden" }, { + "id": "web.incoming_webhook.channel_locked.app_error", + "translation": "This webhook is not permitted to post to the requested channel" + }, + { "id": "web.incoming_webhook.disabled.app_error", "translation": "Eingehende Webhoocks wurden durch den Systemadministrator deaktiviert." }, diff --git a/i18n/en.json b/i18n/en.json index 0fc9a733f..ac3cb4110 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -1976,39 +1976,31 @@ }, { "id": "api.post.send_notifications_and_forget.push_image_only", - "translation": " uploaded one or more files in " + "translation": " attached a file." }, { - "id": "api.post.send_notifications_and_forget.push_image_only_dm", - "translation": " uploaded one or more files in a direct message" + "id": "api.post.send_notifications_and_forget.push_explicit_mention", + "translation": " mentioned you." }, { - "id": "api.post.send_notifications_and_forget.push_image_only_no_channel", - "translation": " uploaded one or more files" + "id": "api.post.send_notification_and_forget.push_channel_mention", + "translation": " notified the channel." }, { - "id": "api.post.send_notifications_and_forget.push_in", - "translation": " in " + "id": "api.post.send_notification_and_forget.push_comment_on_post", + "translation": " commented on your post." }, { - "id": "api.post.send_notifications_and_forget.push_mention", - "translation": " mentioned you in " - }, - { - "id": "api.post.send_notifications_and_forget.push_mention_no_channel", - "translation": " mentioned you" + "id": "api.post.send_notification_and_forget.push_comment_on_thread", + "translation": " commented on a thread you participated in." }, { "id": "api.post.send_notifications_and_forget.push_message", - "translation": " sent you a direct message" - }, - { - "id": "api.post.send_notifications_and_forget.push_non_mention", - "translation": " posted in " + "translation": "sent you a message." }, { - "id": "api.post.send_notifications_and_forget.push_non_mention_no_channel", - "translation": " posted a message" + "id": "api.post.send_notifications_and_forget.push_general_message", + "translation": " posted a message." }, { "id": "api.post.send_notifications_and_forget.push_notification.error", @@ -2583,6 +2575,18 @@ "translation": "Group Message" }, { + "id": "api.templates.deactivate_body.info", + "translation": "You deactivated your account on {{ .SiteURL }}.<br>If this change wasn't initiated by you or you want to reactivate your account, contact your system administrator." + }, + { + "id": "api.templates.deactivate_body.title", + "translation": "Your account has been deactivated at {{ .ServerURL }}" + }, + { + "id": "api.templates.deactivate_subject", + "translation": "[{{ .SiteName }}] Your account at {{ .ServerURL }} has been deactivated" + }, + { "id": "api.templates.email_change_body.info", "translation": "Your email address for {{.TeamDisplayName}} has been changed to {{.NewEmail}}.<br>If you did not make this change, please contact the system administrator." }, @@ -2819,22 +2823,6 @@ "translation": "[{{ .SiteName }}] You joined {{ .ServerURL }}" }, { - "id": "api.templates.deactivate_subject", - "translation": "[{{ .SiteName }}] Your account at {{ .ServerURL }} has been deactivated" - }, - { - "id": "api.templates.deactivate_body.title", - "translation": "Your account has been deactivated at {{ .ServerURL }}" - }, - { - "id": "api.templates.deactivate_body.info", - "translation": "You deactivated your account on {{ .SiteURL }}.<br>If this change wasn't initiated by you or you want to reactivate your account, contact your system administrator." - }, - { - "id": "api.user.send_deactivate_email_and_forget.failed.error", - "translation": "Failed to send the deactivate account email successfully" - }, - { "id": "api.user.activate_mfa.email_and_ldap_only.app_error", "translation": "MFA is not available for this account type" }, @@ -3107,6 +3095,10 @@ "translation": "SAML 2.0 is not configured or supported on this server." }, { + "id": "api.user.send_deactivate_email_and_forget.failed.error", + "translation": "Failed to send the deactivate account email successfully" + }, + { "id": "api.user.send_email_change_email_and_forget.error", "translation": "Failed to send email change notification email successfully" }, @@ -3155,14 +3147,14 @@ "translation": "You can not modify the activation status of SSO accounts. Please modify through the SSO server." }, { - "id": "api.user.update_active.permissions.app_error", - "translation": "You do not have the appropriate permissions" - }, - { "id": "api.user.update_active.not_enable.app_error", "translation": "You cannot deactivate yourself because this feature is not enabled. Please contact your System Administrator." }, { + "id": "api.user.update_active.permissions.app_error", + "translation": "You do not have the appropriate permissions" + }, + { "id": "api.user.update_mfa.not_available.app_error", "translation": "MFA not configured or available on this server" }, @@ -5019,6 +5011,10 @@ "translation": "Message retention must be one day or longer." }, { + "id": "model.config.is_valid.display.custom_url_schemes.app_error", + "translation": "The custom URL scheme {{.Scheme}} is invalid. Custom URL schemes must start with a letter and contain only letters, numbers, plus (+), period (.), and hyphen (-)." + }, + { "id": "model.config.is_valid.elastic_search.aggregate_posts_after_days.app_error", "translation": "Elasticsearch AggregatePostsAfterDays setting must be a number greater than or equal to 1" }, @@ -5328,7 +5324,7 @@ }, { "id": "model.config.is_valid.site_url.app_error", - "translation": "Site URL must be set, a valid URL, and start with http:// or https://" + "translation": "Site URL must be a valid URL and start with http:// or https://" }, { "id": "model.config.is_valid.site_url_email_batching.app_error", @@ -6915,10 +6911,6 @@ "translation": "Unable to get roles" }, { - "id": "web.incoming_webhook.channel_locked.app_error", - "translation": "This webhook is not permitted to post to the requested channel" - }, - { "id": "store.sql_role.permanent_delete_all.app_error", "translation": "We could not permanently delete all the roles" }, @@ -7727,6 +7719,10 @@ "translation": "Couldn't find the channel" }, { + "id": "web.incoming_webhook.channel_locked.app_error", + "translation": "This webhook is not permitted to post to the requested channel" + }, + { "id": "web.incoming_webhook.disabled.app_error", "translation": "Incoming webhooks have been disabled by the system admin." }, diff --git a/i18n/es.json b/i18n/es.json index af93e16ec..d88651d15 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -2515,6 +2515,18 @@ "translation": "Mensaje de Grupo" }, { + "id": "api.templates.deactivate_body.info", + "translation": "You deactivated your account on {{ .SiteURL }}.<br>If this change wasn't initiated by you or you want to reactivate your account, contact your system administrator." + }, + { + "id": "api.templates.deactivate_body.title", + "translation": "Your account has been deactivated at {{ .ServerURL }}" + }, + { + "id": "api.templates.deactivate_subject", + "translation": "[{{ .SiteName }}] Your account at {{ .ServerURL }} has been deactivated" + }, + { "id": "api.templates.email_change_body.info", "translation": "Tu dirección de correo electrónico para {{.TeamDisplayName}} ha sido cambiada por {{.NewEmail}}.<br>Si este cambio no fue realizado por ti, por favor contacta un administrador de sistema." }, @@ -3023,6 +3035,10 @@ "translation": "SAML 2.0 no está configurado o no es soportado en este servidor" }, { + "id": "api.user.send_deactivate_email_and_forget.failed.error", + "translation": "Failed to send the deactivate account email successfully" + }, + { "id": "api.user.send_email_change_email_and_forget.error", "translation": "Error al enviar la notificación por correo electrónico del cambio satisfactorio del correo electrónico" }, @@ -3071,6 +3087,10 @@ "translation": "No puedes modificar el estado de activación para cuentas de tipo SSO. Por favor, haz la modificación a través del servicio SSO." }, { + "id": "api.user.update_active.not_enable.app_error", + "translation": "You cannot deactivate yourself because this feature is not enabled. Please contact your System Administrator." + }, + { "id": "api.user.update_active.permissions.app_error", "translation": "No tienes los permisos apropiados" }, @@ -3719,10 +3739,6 @@ "translation": "La propiedad de notificación por comentarios del usuario no es válida." }, { - "id": "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", - "translation": "La propiedad de la duración para la notificación de escritorio del usuario no es válida." - }, - { "id": "app.import.validate_user_import_data.notify_props_desktop_invalid.error", "translation": "Las propiedades de notificación de escritorio del usuario no es válida." }, @@ -3855,6 +3871,10 @@ "translation": "No puede desactivar el plugin" }, { + "id": "app.plugin.delete_plugin_status_state.app_error", + "translation": "Unable to delete plugin status state." + }, + { "id": "app.plugin.disabled.app_error", "translation": "Los Complementos han sido inhabilitados. Por favor revisa los logs para más detalles." }, @@ -3899,10 +3919,18 @@ "translation": "El Plugin no está instalado" }, { + "id": "app.plugin.prepackaged.app_error", + "translation": "Cannot install prepackaged plugin" + }, + { "id": "app.plugin.remove.app_error", "translation": "No se puede eliminar el plugin" }, { + "id": "app.plugin.set_plugin_status_state.app_error", + "translation": "Unable to set plugin status state." + }, + { "id": "app.plugin.upload_disabled.app_error", "translation": "Los Complementos y/o la carga de complementos han sido deshabilitados." }, @@ -4799,6 +4827,10 @@ "translation": "Incapaz de construir una solicitud multipart" }, { + "id": "model.cluster.is_valid.id.app_error", + "translation": "Id inválido" + }, + { "id": "model.command.is_valid.create_at.app_error", "translation": "Fecha de Creación debe ser válida" }, @@ -7527,6 +7559,10 @@ "translation": "No se encontró el canal" }, { + "id": "web.incoming_webhook.channel_locked.app_error", + "translation": "Este webhook no tiene autorización para publicar en el canal solicitado" + }, + { "id": "web.incoming_webhook.disabled.app_error", "translation": "Webhooks entrantes han sido inhabilitados por el administrador del sistema." }, diff --git a/i18n/fr.json b/i18n/fr.json index 7fca34fd0..49a43b342 100644 --- a/i18n/fr.json +++ b/i18n/fr.json @@ -2515,6 +2515,18 @@ "translation": "Message de groupe" }, { + "id": "api.templates.deactivate_body.info", + "translation": "You deactivated your account on {{ .SiteURL }}.<br>If this change wasn't initiated by you or you want to reactivate your account, contact your system administrator." + }, + { + "id": "api.templates.deactivate_body.title", + "translation": "Your account has been deactivated at {{ .ServerURL }}" + }, + { + "id": "api.templates.deactivate_subject", + "translation": "[{{ .SiteName }}] Your account at {{ .ServerURL }} has been deactivated" + }, + { "id": "api.templates.email_change_body.info", "translation": "Votre adresse e-mail pour {{.TeamDisplayName}} a été remplacée par {{.NewEmail}}.<br>Si vous n'êtes pas à l'origine de cette action, veuillez contacter votre administrateur système." }, @@ -3023,6 +3035,10 @@ "translation": "SAML 2.0 n'est pas configuré ou supporté sur ce serveur." }, { + "id": "api.user.send_deactivate_email_and_forget.failed.error", + "translation": "Failed to send the deactivate account email successfully" + }, + { "id": "api.user.send_email_change_email_and_forget.error", "translation": "Impossible d'envoyer l'e-mail de notification de changement d'adresse e-mail" }, @@ -3071,6 +3087,10 @@ "translation": "Vous ne pouvez pas modifier le statut d'activation des comptes utilisant l'authentification unique (SSO). Veuillez modifier ce compte dans votre serveur d'authentification unique (SSO)." }, { + "id": "api.user.update_active.not_enable.app_error", + "translation": "You cannot deactivate yourself because this feature is not enabled. Please contact your System Administrator." + }, + { "id": "api.user.update_active.permissions.app_error", "translation": "Vous n'avez pas les permissions requises" }, @@ -3719,10 +3739,6 @@ "translation": "La propriété de déclencheur de notification de commentaire est invalide pour l'utilisateur." }, { - "id": "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", - "translation": "La valeur de la propriété de durée de notification de bureau est invalide pour l'utilisateur." - }, - { "id": "app.import.validate_user_import_data.notify_props_desktop_invalid.error", "translation": "La valeur de la propriété de notification de bureau est invalide pour l'utilisateur." }, @@ -3855,6 +3871,10 @@ "translation": "Impossible de désactiver le plugin" }, { + "id": "app.plugin.delete_plugin_status_state.app_error", + "translation": "Unable to delete plugin status state." + }, + { "id": "app.plugin.disabled.app_error", "translation": "Les plugins ont été désactivés. Veuillez consulter vos journaux (logs) pour plus d'information." }, @@ -3899,10 +3919,18 @@ "translation": "Le plugin n'est pas installé" }, { + "id": "app.plugin.prepackaged.app_error", + "translation": "Cannot install prepackaged plugin" + }, + { "id": "app.plugin.remove.app_error", "translation": "Impossible de supprimer le plugin" }, { + "id": "app.plugin.set_plugin_status_state.app_error", + "translation": "Unable to set plugin status state." + }, + { "id": "app.plugin.upload_disabled.app_error", "translation": "Les plugins et/ou l'envoi de plugins ont été désactivés." }, @@ -4799,6 +4827,10 @@ "translation": "Impossible construire la requête composite (multipart)" }, { + "id": "model.cluster.is_valid.id.app_error", + "translation": "Id invalide" + }, + { "id": "model.command.is_valid.create_at.app_error", "translation": "La date de création doit être une date valide" }, @@ -7527,6 +7559,10 @@ "translation": "Impossible de trouver le canal" }, { + "id": "web.incoming_webhook.channel_locked.app_error", + "translation": "This webhook is not permitted to post to the requested channel" + }, + { "id": "web.incoming_webhook.disabled.app_error", "translation": "Les webhooks entrants ont été désactivées par l'administrateur système." }, diff --git a/i18n/it.json b/i18n/it.json index b063ffbb9..977580691 100644 --- a/i18n/it.json +++ b/i18n/it.json @@ -2515,6 +2515,18 @@ "translation": "Messaggio di gruppo" }, { + "id": "api.templates.deactivate_body.info", + "translation": "You deactivated your account on {{ .SiteURL }}.<br>If this change wasn't initiated by you or you want to reactivate your account, contact your system administrator." + }, + { + "id": "api.templates.deactivate_body.title", + "translation": "Your account has been deactivated at {{ .ServerURL }}" + }, + { + "id": "api.templates.deactivate_subject", + "translation": "[{{ .SiteName }}] Your account at {{ .ServerURL }} has been deactivated" + }, + { "id": "api.templates.email_change_body.info", "translation": "Il tuo indirizzo email per {{.TeamDisplayName}} è stato cambiato in {{.NewEmail}}.<br>Se non vuoi questo cambiamento, contatta il tuo amministratore di sistema." }, @@ -3023,6 +3035,10 @@ "translation": "SAML 2.0 non configurato o non supportato su questo server." }, { + "id": "api.user.send_deactivate_email_and_forget.failed.error", + "translation": "Failed to send the deactivate account email successfully" + }, + { "id": "api.user.send_email_change_email_and_forget.error", "translation": "Invio notifica email di cambio email avvenuto con successo fallita" }, @@ -3071,6 +3087,10 @@ "translation": "Non è possibile modificare lo stato di attivazione degli account SSO. Vanno modificati sul server SSO." }, { + "id": "api.user.update_active.not_enable.app_error", + "translation": "You cannot deactivate yourself because this feature is not enabled. Please contact your System Administrator." + }, + { "id": "api.user.update_active.permissions.app_error", "translation": "Non possiedi i permessi per proseguire con l'operazione" }, @@ -3719,10 +3739,6 @@ "translation": "Proprietà scatena notifiche commento non valida per l'utente." }, { - "id": "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", - "translation": "Proprietà durata notifiche desktop non valida per l'utente." - }, - { "id": "app.import.validate_user_import_data.notify_props_desktop_invalid.error", "translation": "Proprietà notifiche su desktop non valida per l'utente." }, @@ -3855,6 +3871,10 @@ "translation": "Impossibile disattivare il plugin" }, { + "id": "app.plugin.delete_plugin_status_state.app_error", + "translation": "Impossibile eliminare lo stato del plugin." + }, + { "id": "app.plugin.disabled.app_error", "translation": "I plugin sono disattivati. Controllare i log per ulteriori informazioni." }, @@ -3899,10 +3919,18 @@ "translation": "Il plugin non è installato" }, { + "id": "app.plugin.prepackaged.app_error", + "translation": "Impossibile installare il plugin preconfigurato" + }, + { "id": "app.plugin.remove.app_error", "translation": "Impossibile eliminare il plugin" }, { + "id": "app.plugin.set_plugin_status_state.app_error", + "translation": "Impossibile impostare lo stato del plugin." + }, + { "id": "app.plugin.upload_disabled.app_error", "translation": "I plugin e/o il caricamento dei plugin è stato disattivato." }, @@ -4799,6 +4827,10 @@ "translation": "Impossibile costruire la richiesta multipart" }, { + "id": "model.cluster.is_valid.id.app_error", + "translation": "ID non valido" + }, + { "id": "model.command.is_valid.create_at.app_error", "translation": "Creato alle deve essere un tempo valido" }, @@ -7527,6 +7559,10 @@ "translation": "Impossibile trovare il canale" }, { + "id": "web.incoming_webhook.channel_locked.app_error", + "translation": "Questo webhook non ha i permessi di pubblicare nel canale richiesto" + }, + { "id": "web.incoming_webhook.disabled.app_error", "translation": "I webhook in ingresso sono stati disabilitati dall'amministratore del sistema." }, diff --git a/i18n/ja.json b/i18n/ja.json index daa007a3a..a70d7437e 100644 --- a/i18n/ja.json +++ b/i18n/ja.json @@ -824,7 +824,7 @@ }, { "id": "api.command_invite.private_channel.app_error", - "translation": "Could not find the channel {{.Channel}}. Please use the channel handle to identify channels." + "translation": "チャンネル {{.Channel}} が見つかりませんでした。チャンネルの指定にはチャンネルのハンドル名を使用してください。" }, { "id": "api.command_invite.success", @@ -2515,6 +2515,18 @@ "translation": "グループメッセージ" }, { + "id": "api.templates.deactivate_body.info", + "translation": "You deactivated your account on {{ .SiteURL }}.<br>If this change wasn't initiated by you or you want to reactivate your account, contact your system administrator." + }, + { + "id": "api.templates.deactivate_body.title", + "translation": "Your account has been deactivated at {{ .ServerURL }}" + }, + { + "id": "api.templates.deactivate_subject", + "translation": "[{{ .SiteName }}] Your account at {{ .ServerURL }} has been deactivated" + }, + { "id": "api.templates.email_change_body.info", "translation": "あなたの{{.TeamDisplayName}}用の電子メールアドレスが{{.NewEmail}}に変更されました。<br>あなたが変更したのでなければ、システム管理者に問い合わせてください。" }, @@ -3023,6 +3035,10 @@ "translation": "SAML 2.0 は、このサーバーでは設定されていないかサポートされていません。" }, { + "id": "api.user.send_deactivate_email_and_forget.failed.error", + "translation": "Failed to send the deactivate account email successfully" + }, + { "id": "api.user.send_email_change_email_and_forget.error", "translation": "電子メールアドレス変更通知の電子メールを送信できませんでした" }, @@ -3071,6 +3087,10 @@ "translation": "シングルサインオンアカウントのアクティベーション状態を変更することはできません。シングルサインオンサーバーを通じて変更してください。" }, { + "id": "api.user.update_active.not_enable.app_error", + "translation": "You cannot deactivate yourself because this feature is not enabled. Please contact your System Administrator." + }, + { "id": "api.user.update_active.permissions.app_error", "translation": "あなたには必要な権限が付与されていません" }, @@ -3719,10 +3739,6 @@ "translation": "ユーザーのコメント通知トリガーの設定が不正です。" }, { - "id": "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", - "translation": "ユーザーのデスクトップ通知持続時間の設定値が不正です。" - }, - { "id": "app.import.validate_user_import_data.notify_props_desktop_invalid.error", "translation": "ユーザーのデスクトップ通知の設定値が不正です。" }, @@ -3780,15 +3796,15 @@ }, { "id": "app.notification.body.intro.direct.generic", - "translation": "{{.SenderName}} からの新しいダイレクトメッセージがあります" + "translation": "@{{.SenderName}} からの新しいダイレクトメッセージがあります" }, { "id": "app.notification.body.intro.group_message.full", - "translation": "新しいダイレクトメッセージがあります。" + "translation": "新しいグループメッセージがあります。" }, { "id": "app.notification.body.intro.group_message.generic", - "translation": "{{.SenderName}} からの新しいダイレクトメッセージがあります" + "translation": "@{{.SenderName}} からの新しいグループメッセージがあります" }, { "id": "app.notification.body.intro.notification.full", @@ -3796,11 +3812,11 @@ }, { "id": "app.notification.body.intro.notification.generic", - "translation": "{{.SenderName}} からの新しい通知があります" + "translation": "@{{.SenderName}} からの新しい通知があります" }, { "id": "app.notification.body.text.direct.full", - "translation": "{{.SenderName}} - {{.Hour}}:{{.Minute}} {{.Timezone}}, {{.Month}} {{.Day}}" + "translation": "@{{.SenderName}} - {{.Hour}}:{{.Minute}} {{.Timezone}}, {{.Month}} {{.Day}}" }, { "id": "app.notification.body.text.direct.generic", @@ -3808,7 +3824,7 @@ }, { "id": "app.notification.body.text.group_message.full", - "translation": "チャンネル: {{.ChannelName}}<br>{{.SenderName}} - {{.Hour}}:{{.Minute}} {{.TimeZone}}, {{.Month}} {{.Day}}" + "translation": "チャンネル: {{.ChannelName}}<br>@{{.SenderName}} - {{.Hour}}:{{.Minute}} {{.TimeZone}}, {{.Month}} {{.Day}}" }, { "id": "app.notification.body.text.group_message.generic", @@ -3816,7 +3832,7 @@ }, { "id": "app.notification.body.text.notification.full", - "translation": "チャンネル: {{.ChannelName}}<br>{{.SenderName}} - {{.Hour}}:{{.Minute}} {{.TimeZone}}, {{.Month}} {{.Day}}" + "translation": "チャンネル: {{.ChannelName}}<br>@{{.SenderName}} - {{.Hour}}:{{.Minute}} {{.TimeZone}}, {{.Month}} {{.Day}}" }, { "id": "app.notification.body.text.notification.generic", @@ -3824,15 +3840,15 @@ }, { "id": "app.notification.subject.direct.full", - "translation": "[{{ .SiteName}}] {{.Month}} {{.Day}}, {{.Year}} {{.SenderDisplayName}} からの新しいダイレクトメッセージ" + "translation": "[{{.SiteName}}] {{.Month}} {{.Day}}, {{.Year}} @{{.SenderDisplayName}} からの新しいダイレクトメッセージ" }, { "id": "app.notification.subject.group_message.full", - "translation": "[{{.SiteName}}] {{.Month}} {{.Day}}, {{.Year}} {{.TeamName}}の通知" + "translation": "[{{ .SiteName }}] {{.Month}} {{.Day}}, {{.Year}} {{.ChannelName}}の新しいグループメッセージ" }, { "id": "app.notification.subject.group_message.generic", - "translation": "[{{.SiteName}}] {{.Month}} {{.Day}}, {{.Year}} の新着通知[{{.SiteName}}] {{.Month}} {{.Day}}, {{.Year}} の新着通知" + "translation": "[{{ .SiteName }}] {{.Month}} {{.Day}}, {{.Year}} 新しいグループメッセージ" }, { "id": "app.notification.subject.notification.full", @@ -3855,6 +3871,10 @@ "translation": "プラグインを無効化できませんでした" }, { + "id": "app.plugin.delete_plugin_status_state.app_error", + "translation": "プラグインステータスの状態を削除できませんでした。" + }, + { "id": "app.plugin.disabled.app_error", "translation": "プラグインは無効化されています。詳しくはログを確認してください。" }, @@ -3899,10 +3919,18 @@ "translation": "プラグインはインストールされていません" }, { + "id": "app.plugin.prepackaged.app_error", + "translation": "パッケージング済みプラグインはインストールできません" + }, + { "id": "app.plugin.remove.app_error", "translation": "プラグインを削除できませんでした" }, { + "id": "app.plugin.set_plugin_status_state.app_error", + "translation": "プラスインステータスの状態を設定できませんでした。" + }, + { "id": "app.plugin.upload_disabled.app_error", "translation": "プラグインのアップロードは無効化されています。" }, @@ -4799,6 +4827,10 @@ "translation": "マルチパートリクエストを構築できませんでした" }, { + "id": "model.cluster.is_valid.id.app_error", + "translation": "不正なIDです" + }, + { "id": "model.command.is_valid.create_at.app_error", "translation": "作成日時は有効な時刻にしてください" }, @@ -5036,23 +5068,23 @@ }, { "id": "model.config.is_valid.ldap_email", - "translation": "AD/LDAP項目 \"電子メール属性値\" は必須です。" + "translation": "AD/LDAP項目 \"電子メール属性\" は必須です。" }, { "id": "model.config.is_valid.ldap_firstname", - "translation": "AD/LDAP項目 \"名前(ファーストネーム)の属性値\" は必須です。" + "translation": "AD/LDAP項目 \"名前(ファーストネーム)の属性\" は必須です。" }, { "id": "model.config.is_valid.ldap_id", - "translation": "AD/LDAP項目 \"ID属性値\" は必須です。" + "translation": "AD/LDAP項目 \"ID属性\" は必須です。" }, { "id": "model.config.is_valid.ldap_lastname", - "translation": "AD/LDAP項目 \"苗字(ラストネーム)の属性値\" は必須です。" + "translation": "AD/LDAP項目 \"苗字(ラストネーム)の属性\" は必須です。" }, { "id": "model.config.is_valid.ldap_login_id", - "translation": "AD/LDAP項目 \"ID属性値\" は必須です。" + "translation": "AD/LDAP項目 \"ログインID属性\" は必須です。" }, { "id": "model.config.is_valid.ldap_max_page_size.app_error", @@ -5080,7 +5112,7 @@ }, { "id": "model.config.is_valid.ldap_username", - "translation": "AD/LDAP項目 \"ユーザー名の属性値\" は必須です。" + "translation": "AD/LDAP項目 \"ユーザー名の属性\" は必須です。" }, { "id": "model.config.is_valid.listen_address.app_error", @@ -5228,7 +5260,7 @@ }, { "id": "model.config.is_valid.site_url.app_error", - "translation": "サイトURLを正しく設定してください。URLはhttp://またはhttps://で始まります。" + "translation": "サイトURLにhttp://またはhttps://で始まるURLを設定する必要があります" }, { "id": "model.config.is_valid.site_url_email_batching.app_error", @@ -7527,6 +7559,10 @@ "translation": "チャンネルが見付かりません" }, { + "id": "web.incoming_webhook.channel_locked.app_error", + "translation": "このウェブフックは要求されたチャンネルに投稿する権限がありません" + }, + { "id": "web.incoming_webhook.disabled.app_error", "translation": "内向きのウェブフックはシステム管理者によって無効化されています。" }, diff --git a/i18n/ko.json b/i18n/ko.json index d9c06ffca..b790c9945 100644 --- a/i18n/ko.json +++ b/i18n/ko.json @@ -2515,6 +2515,18 @@ "translation": "그룹 메세지" }, { + "id": "api.templates.deactivate_body.info", + "translation": "You deactivated your account on {{ .SiteURL }}.<br>If this change wasn't initiated by you or you want to reactivate your account, contact your system administrator." + }, + { + "id": "api.templates.deactivate_body.title", + "translation": "Your account has been deactivated at {{ .ServerURL }}" + }, + { + "id": "api.templates.deactivate_subject", + "translation": "[{{ .SiteName }}] Your account at {{ .ServerURL }} has been deactivated" + }, + { "id": "api.templates.email_change_body.info", "translation": "{{.TeamDisplayName}} 이메일이 {{.NewEmail}}(으)로 변경되었습니다.<br> 잘못 변경된 경우, 시스템 관리자에게 문의하세요." }, @@ -3023,6 +3035,10 @@ "translation": "SAML이 설정되지 않았거나 서버에서 지원하지 않습니다" }, { + "id": "api.user.send_deactivate_email_and_forget.failed.error", + "translation": "Failed to send the deactivate account email successfully" + }, + { "id": "api.user.send_email_change_email_and_forget.error", "translation": "이메일 변경 알림 메일을 발송하지 못하였습니다." }, @@ -3071,6 +3087,10 @@ "translation": "You can not modify the activation status of LDAP accounts. Please modify through the LDAP server." }, { + "id": "api.user.update_active.not_enable.app_error", + "translation": "You cannot deactivate yourself because this feature is not enabled. Please contact your System Administrator." + }, + { "id": "api.user.update_active.permissions.app_error", "translation": "작업을 할 수 있는 권한이 없습니다" }, @@ -3719,10 +3739,6 @@ "translation": "Invalid Comment Trigger Notify Prop for user." }, { - "id": "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", - "translation": "Invalid Desktop Duration Notify Prop value for user." - }, - { "id": "app.import.validate_user_import_data.notify_props_desktop_invalid.error", "translation": "Invalid Desktop Notify Prop value for user." }, @@ -3855,6 +3871,10 @@ "translation": "Unable to deactivate plugin" }, { + "id": "app.plugin.delete_plugin_status_state.app_error", + "translation": "Unable to delete plugin status state." + }, + { "id": "app.plugin.disabled.app_error", "translation": "Plugins have been disabled. Please check your logs for details." }, @@ -3899,10 +3919,18 @@ "translation": "Plugin is not installed" }, { + "id": "app.plugin.prepackaged.app_error", + "translation": "Cannot install prepackaged plugin" + }, + { "id": "app.plugin.remove.app_error", "translation": "Unable to delete plugin" }, { + "id": "app.plugin.set_plugin_status_state.app_error", + "translation": "Unable to set plugin status state." + }, + { "id": "app.plugin.upload_disabled.app_error", "translation": "Plugins and/or plugin uploads have been disabled." }, @@ -4799,6 +4827,10 @@ "translation": "Unable to build multipart request" }, { + "id": "model.cluster.is_valid.id.app_error", + "translation": "잘못된 ID" + }, + { "id": "model.command.is_valid.create_at.app_error", "translation": "Create at must be a valid time" }, @@ -7527,6 +7559,10 @@ "translation": "채널을 찾을 수 없습니다" }, { + "id": "web.incoming_webhook.channel_locked.app_error", + "translation": "This webhook is not permitted to post to the requested channel" + }, + { "id": "web.incoming_webhook.disabled.app_error", "translation": "Incoming webhook은 관리자가 사용할 수 없게 설정했습니다." }, diff --git a/i18n/nl.json b/i18n/nl.json index 14edb8d66..b1b6961e9 100644 --- a/i18n/nl.json +++ b/i18n/nl.json @@ -2515,6 +2515,18 @@ "translation": "Group Message" }, { + "id": "api.templates.deactivate_body.info", + "translation": "You deactivated your account on {{ .SiteURL }}.<br>If this change wasn't initiated by you or you want to reactivate your account, contact your system administrator." + }, + { + "id": "api.templates.deactivate_body.title", + "translation": "Your account has been deactivated at {{ .ServerURL }}" + }, + { + "id": "api.templates.deactivate_subject", + "translation": "[{{ .SiteName }}] Your account at {{ .ServerURL }} has been deactivated" + }, + { "id": "api.templates.email_change_body.info", "translation": "Uw e-mailadres voor {{.TeamDisplayName}} is veranderd naar {{.NewEmail}}.<br>Als u deze wijziging niet zelf gemaakt hebt, neem kontakt op met de systeembeheerder." }, @@ -3023,6 +3035,10 @@ "translation": "SAML wordt niet ondersteund, of is niet geconfigureerd op deze server." }, { + "id": "api.user.send_deactivate_email_and_forget.failed.error", + "translation": "Failed to send the deactivate account email successfully" + }, + { "id": "api.user.send_email_change_email_and_forget.error", "translation": "Aanpassings mail voor notificatie kon niet verstuurd worden" }, @@ -3071,6 +3087,10 @@ "translation": "Je kan niet de activatie status veranderen van AD/LDAP account. Wijzig dit via de AD/LDAP server." }, { + "id": "api.user.update_active.not_enable.app_error", + "translation": "You cannot deactivate yourself because this feature is not enabled. Please contact your System Administrator." + }, + { "id": "api.user.update_active.permissions.app_error", "translation": "U beschikt niet over de juiste rechten" }, @@ -3719,10 +3739,6 @@ "translation": "Invalid Comment Trigger Notify Prop for user." }, { - "id": "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", - "translation": "Invalid Desktop Duration Notify Prop value for user." - }, - { "id": "app.import.validate_user_import_data.notify_props_desktop_invalid.error", "translation": "Invalid Desktop Notify Prop value for user." }, @@ -3855,6 +3871,10 @@ "translation": "Unable to deactivate plugin" }, { + "id": "app.plugin.delete_plugin_status_state.app_error", + "translation": "Unable to delete plugin status state." + }, + { "id": "app.plugin.disabled.app_error", "translation": "Plugins have been disabled. Please check your logs for details." }, @@ -3899,10 +3919,18 @@ "translation": "Plugin is not installed" }, { + "id": "app.plugin.prepackaged.app_error", + "translation": "Cannot install prepackaged plugin" + }, + { "id": "app.plugin.remove.app_error", "translation": "Unable to delete plugin" }, { + "id": "app.plugin.set_plugin_status_state.app_error", + "translation": "Unable to set plugin status state." + }, + { "id": "app.plugin.upload_disabled.app_error", "translation": "Plugins and/or plugin uploads have been disabled." }, @@ -4799,6 +4827,10 @@ "translation": "Unable to build multipart request" }, { + "id": "model.cluster.is_valid.id.app_error", + "translation": "Ongeldig Id" + }, + { "id": "model.command.is_valid.create_at.app_error", "translation": "Aangemaakt op moet een geldige tijd zijn" }, @@ -7527,6 +7559,10 @@ "translation": "Het kanaal kan niet gevonden worden" }, { + "id": "web.incoming_webhook.channel_locked.app_error", + "translation": "This webhook is not permitted to post to the requested channel" + }, + { "id": "web.incoming_webhook.disabled.app_error", "translation": "Commando's zijn uitgeschakeld door de beheerder." }, diff --git a/i18n/pl.json b/i18n/pl.json index aa95466a5..01f3f47c4 100644 --- a/i18n/pl.json +++ b/i18n/pl.json @@ -2515,6 +2515,18 @@ "translation": "Wiadomość grupowa" }, { + "id": "api.templates.deactivate_body.info", + "translation": "You deactivated your account on {{ .SiteURL }}.<br>If this change wasn't initiated by you or you want to reactivate your account, contact your system administrator." + }, + { + "id": "api.templates.deactivate_body.title", + "translation": "Your account has been deactivated at {{ .ServerURL }}" + }, + { + "id": "api.templates.deactivate_subject", + "translation": "[{{ .SiteName }}] Your account at {{ .ServerURL }} has been deactivated" + }, + { "id": "api.templates.email_change_body.info", "translation": "Twój adres e-mail na {{.TeamDisplayName}} został zmieniony na {{.NewEmail}}.<br>Jeśli to nie ty dokonałeś tej zmiany, skontaktuj się z administratorem systemu." }, @@ -3023,6 +3035,10 @@ "translation": "Użycie SAML 2.0 nie zostało skonfigurowane lub nie jest wspierane na tym serwerze." }, { + "id": "api.user.send_deactivate_email_and_forget.failed.error", + "translation": "Failed to send the deactivate account email successfully" + }, + { "id": "api.user.send_email_change_email_and_forget.error", "translation": "Nie udało się pomyślnie wysłać emaila z powiadomieniem o zmianie adresu email" }, @@ -3071,6 +3087,10 @@ "translation": "Nie możesz zmieniać stanu aktywacji kont SSO. Proszę je zmodyfikować przez serwer SSO." }, { + "id": "api.user.update_active.not_enable.app_error", + "translation": "You cannot deactivate yourself because this feature is not enabled. Please contact your System Administrator." + }, + { "id": "api.user.update_active.permissions.app_error", "translation": "Nie posiadasz wymaganych uprawnień" }, @@ -3719,10 +3739,6 @@ "translation": "Nieprawidłowy ciąg znaków powiadamiania o komentarzu dla użytkownika." }, { - "id": "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", - "translation": "Invalid Desktop Duration Notify Prop value for user." - }, - { "id": "app.import.validate_user_import_data.notify_props_desktop_invalid.error", "translation": "Invalid Desktop Notify Prop value for user." }, @@ -3855,6 +3871,10 @@ "translation": "Nie udało się skasować reakcji" }, { + "id": "app.plugin.delete_plugin_status_state.app_error", + "translation": "Unable to delete plugin status state." + }, + { "id": "app.plugin.disabled.app_error", "translation": "Plugins have been disabled. Please check your logs for details." }, @@ -3899,10 +3919,18 @@ "translation": "Plugin is not installed" }, { + "id": "app.plugin.prepackaged.app_error", + "translation": "Cannot install prepackaged plugin" + }, + { "id": "app.plugin.remove.app_error", "translation": "Nie udało się skasować reakcji" }, { + "id": "app.plugin.set_plugin_status_state.app_error", + "translation": "Unable to set plugin status state." + }, + { "id": "app.plugin.upload_disabled.app_error", "translation": "Plugins and/or plugin uploads have been disabled." }, @@ -4799,6 +4827,10 @@ "translation": "Unable to build multipart request" }, { + "id": "model.cluster.is_valid.id.app_error", + "translation": "Nieprawidłowy identyfikator" + }, + { "id": "model.command.is_valid.create_at.app_error", "translation": "Utworzono dnia musi być poprawnym czasem" }, @@ -7527,6 +7559,10 @@ "translation": "Nie odnaleziono kanału" }, { + "id": "web.incoming_webhook.channel_locked.app_error", + "translation": "This webhook is not permitted to post to the requested channel" + }, + { "id": "web.incoming_webhook.disabled.app_error", "translation": "Przychodzące webhooki zostały wyłączone przez Administratora." }, diff --git a/i18n/pt-BR.json b/i18n/pt-BR.json index 5b299756a..53725c4a2 100644 --- a/i18n/pt-BR.json +++ b/i18n/pt-BR.json @@ -2515,6 +2515,18 @@ "translation": "Grupo de mensagem" }, { + "id": "api.templates.deactivate_body.info", + "translation": "You deactivated your account on {{ .SiteURL }}.<br>If this change wasn't initiated by you or you want to reactivate your account, contact your system administrator." + }, + { + "id": "api.templates.deactivate_body.title", + "translation": "Your account has been deactivated at {{ .ServerURL }}" + }, + { + "id": "api.templates.deactivate_subject", + "translation": "[{{ .SiteName }}] Your account at {{ .ServerURL }} has been deactivated" + }, + { "id": "api.templates.email_change_body.info", "translation": "Seu endereço de email para {{.TeamDisplayName}} foi alterado para {{.NewEmail}}.<br>Se você não fez está mudança, por favor contate o administrador do sistema." }, @@ -3023,6 +3035,10 @@ "translation": "SAML 2.0 não está configurado ou disponível neste servidor." }, { + "id": "api.user.send_deactivate_email_and_forget.failed.error", + "translation": "Failed to send the deactivate account email successfully" + }, + { "id": "api.user.send_email_change_email_and_forget.error", "translation": "Erro ao enviar email de troca de notificação" }, @@ -3071,6 +3087,10 @@ "translation": "Você não pode modificar o status de ativação de contas SSO. Por favor modifique através do servidor SSO." }, { + "id": "api.user.update_active.not_enable.app_error", + "translation": "You cannot deactivate yourself because this feature is not enabled. Please contact your System Administrator." + }, + { "id": "api.user.update_active.permissions.app_error", "translation": "Você não tem a permissão apropriada" }, @@ -3719,10 +3739,6 @@ "translation": "Inválido Comment Trigger Notify Prop para o usuário." }, { - "id": "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", - "translation": "Valor inválido Duration Notify Prop para o usuário." - }, - { "id": "app.import.validate_user_import_data.notify_props_desktop_invalid.error", "translation": "Valor inválido Desktop Notify Prop para o usuário." }, @@ -3855,6 +3871,10 @@ "translation": "Não é possível desativar o plugin" }, { + "id": "app.plugin.delete_plugin_status_state.app_error", + "translation": "Unable to delete plugin status state." + }, + { "id": "app.plugin.disabled.app_error", "translation": "Os plugins foram desativados. Verifique os seus logs para obter detalhes." }, @@ -3899,10 +3919,18 @@ "translation": "Plugin não está instalado" }, { + "id": "app.plugin.prepackaged.app_error", + "translation": "Cannot install prepackaged plugin" + }, + { "id": "app.plugin.remove.app_error", "translation": "Não é possível deletar o plugin" }, { + "id": "app.plugin.set_plugin_status_state.app_error", + "translation": "Unable to set plugin status state." + }, + { "id": "app.plugin.upload_disabled.app_error", "translation": "Plugins e/ou envio de plugin foi desabilitado." }, @@ -4799,6 +4827,10 @@ "translation": "Não foi possível construir a requisição multipart" }, { + "id": "model.cluster.is_valid.id.app_error", + "translation": "ID inválida" + }, + { "id": "model.command.is_valid.create_at.app_error", "translation": "Create deve ser um tempo válido" }, @@ -7527,6 +7559,10 @@ "translation": "Não foi possível encontrar o canal" }, { + "id": "web.incoming_webhook.channel_locked.app_error", + "translation": "This webhook is not permitted to post to the requested channel" + }, + { "id": "web.incoming_webhook.disabled.app_error", "translation": "Webhooks de entrada foram desabilitados pelo administrador do sistema." }, diff --git a/i18n/ru.json b/i18n/ru.json index e34d1b8b0..6d3570b9d 100644 --- a/i18n/ru.json +++ b/i18n/ru.json @@ -2515,6 +2515,18 @@ "translation": "Групповые сообщения" }, { + "id": "api.templates.deactivate_body.info", + "translation": "You deactivated your account on {{ .SiteURL }}.<br>If this change wasn't initiated by you or you want to reactivate your account, contact your system administrator." + }, + { + "id": "api.templates.deactivate_body.title", + "translation": "Your account has been deactivated at {{ .ServerURL }}" + }, + { + "id": "api.templates.deactivate_subject", + "translation": "[{{ .SiteName }}] Your account at {{ .ServerURL }} has been deactivated" + }, + { "id": "api.templates.email_change_body.info", "translation": "Ваш адрес электронной почты для {{.TeamDisplayName}} изменен на {{.NewEmail}}. <br> Если Вы не делали это изменение, пожалуйста, обратитесь к системному администратору." }, @@ -3023,6 +3035,10 @@ "translation": "SAML 2.0 не настроен или не поддерживается на этом сервере." }, { + "id": "api.user.send_deactivate_email_and_forget.failed.error", + "translation": "Failed to send the deactivate account email successfully" + }, + { "id": "api.user.send_email_change_email_and_forget.error", "translation": "Не удалось отправить письмо с уведомленим о смене адреса электронной почты" }, @@ -3071,6 +3087,10 @@ "translation": "Вы не можете изменять состояние активности учетных записей AD/LDAP. Пожалуйста, измените его через сервер AD/LDAP." }, { + "id": "api.user.update_active.not_enable.app_error", + "translation": "You cannot deactivate yourself because this feature is not enabled. Please contact your System Administrator." + }, + { "id": "api.user.update_active.permissions.app_error", "translation": "У вас нет соответствующих прав" }, @@ -3719,10 +3739,6 @@ "translation": "Invalid Comment Trigger Notify Prop for user." }, { - "id": "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", - "translation": "Invalid Desktop Duration Notify Prop value for user." - }, - { "id": "app.import.validate_user_import_data.notify_props_desktop_invalid.error", "translation": "Invalid Desktop Notify Prop value for user." }, @@ -3855,6 +3871,10 @@ "translation": "Не удалось отключить плагин" }, { + "id": "app.plugin.delete_plugin_status_state.app_error", + "translation": "Unable to delete plugin status state." + }, + { "id": "app.plugin.disabled.app_error", "translation": "Plugins have been disabled. Please check your logs for details." }, @@ -3899,10 +3919,18 @@ "translation": "Plugin is not installed" }, { + "id": "app.plugin.prepackaged.app_error", + "translation": "Cannot install prepackaged plugin" + }, + { "id": "app.plugin.remove.app_error", "translation": "Не удалось удалить плагин" }, { + "id": "app.plugin.set_plugin_status_state.app_error", + "translation": "Unable to set plugin status state." + }, + { "id": "app.plugin.upload_disabled.app_error", "translation": "Plugins and/or plugin uploads have been disabled." }, @@ -4799,6 +4827,10 @@ "translation": "Unable to build multipart request" }, { + "id": "model.cluster.is_valid.id.app_error", + "translation": "Недопустимый идентификатор" + }, + { "id": "model.command.is_valid.create_at.app_error", "translation": "\"Создать в\" должно быть корректным временем" }, @@ -7527,6 +7559,10 @@ "translation": "Не удалось найти канал" }, { + "id": "web.incoming_webhook.channel_locked.app_error", + "translation": "This webhook is not permitted to post to the requested channel" + }, + { "id": "web.incoming_webhook.disabled.app_error", "translation": "Входящие вебхуки были отключены системным администратором." }, diff --git a/i18n/tr.json b/i18n/tr.json index 091f358ef..c6b52ab8c 100644 --- a/i18n/tr.json +++ b/i18n/tr.json @@ -2515,6 +2515,18 @@ "translation": "Grup İletisi" }, { + "id": "api.templates.deactivate_body.info", + "translation": "You deactivated your account on {{ .SiteURL }}.<br>If this change wasn't initiated by you or you want to reactivate your account, contact your system administrator." + }, + { + "id": "api.templates.deactivate_body.title", + "translation": "Your account has been deactivated at {{ .ServerURL }}" + }, + { + "id": "api.templates.deactivate_subject", + "translation": "[{{ .SiteName }}] Your account at {{ .ServerURL }} has been deactivated" + }, + { "id": "api.templates.email_change_body.info", "translation": "{{.TeamDisplayName}} takımındaki e-posta adresiniz {{.NewEmail}} olarak değiştirildi.<br>Bu değişikliği siz yapmadıysanız sistem yöneticisi ile görüşün." }, @@ -3023,6 +3035,10 @@ "translation": "SAML 2.0 ayarları yapılmamış ya da bu sunucu tarafından desteklenmiyor." }, { + "id": "api.user.send_deactivate_email_and_forget.failed.error", + "translation": "Failed to send the deactivate account email successfully" + }, + { "id": "api.user.send_email_change_email_and_forget.error", "translation": "E-posta adresi değişikliği bildirim e-postası gönderilemedi" }, @@ -3071,6 +3087,10 @@ "translation": "SSO hesaplarının etkinleştirme durumu değiştirilemez. Lütfen değişiklikleri SSO sunucusu üzerinde yapın." }, { + "id": "api.user.update_active.not_enable.app_error", + "translation": "You cannot deactivate yourself because this feature is not enabled. Please contact your System Administrator." + }, + { "id": "api.user.update_active.permissions.app_error", "translation": "İzinleriniz yeterli değil" }, @@ -3719,10 +3739,6 @@ "translation": "Kullanıcının komut tetikleyici bildirimi değeri geçersiz." }, { - "id": "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", - "translation": "Kullanıcının masaüstü süresi bildirimi değeri geçersiz." - }, - { "id": "app.import.validate_user_import_data.notify_props_desktop_invalid.error", "translation": "Kullanıcının masaüstü bildirimi değeri geçersiz." }, @@ -3855,6 +3871,10 @@ "translation": "Uygulama eki devre dışı bırakılamadı" }, { + "id": "app.plugin.delete_plugin_status_state.app_error", + "translation": "Uygulama eki durumu silinemedi." + }, + { "id": "app.plugin.disabled.app_error", "translation": "Uygulama ekleri devre dışı bırakıldı. Ayrıntılar için günlük kayıtlarına bakın." }, @@ -3899,10 +3919,18 @@ "translation": "Uygulama eki kurulmamış" }, { + "id": "app.plugin.prepackaged.app_error", + "translation": "Önceden paketlenmiş uygulama eki kurulamadı" + }, + { "id": "app.plugin.remove.app_error", "translation": "Uygulama eki silinemedi" }, { + "id": "app.plugin.set_plugin_status_state.app_error", + "translation": "Uygulama eki durumu ayarlanamadı." + }, + { "id": "app.plugin.upload_disabled.app_error", "translation": "Uygulama ekleri ya da uygulama eki yüklemeleri devre dışı bırakılmış. " }, @@ -4799,6 +4827,10 @@ "translation": "Multipart isteği oluşturulamadı" }, { + "id": "model.cluster.is_valid.id.app_error", + "translation": "Kod geçersiz" + }, + { "id": "model.command.is_valid.create_at.app_error", "translation": "Oluşturulma zamanı geçerli bir zaman olmalıdır" }, @@ -7527,6 +7559,10 @@ "translation": "Kanal bulunamadı" }, { + "id": "web.incoming_webhook.channel_locked.app_error", + "translation": "Bu web bağlantısının istenilen kanala gönderilmesine izin verilmiyor" + }, + { "id": "web.incoming_webhook.disabled.app_error", "translation": "Gelen web bağlantıları sistem yöneticisi tarafından devre dışı bırakılmış." }, diff --git a/i18n/zh-CN.json b/i18n/zh-CN.json index 43825d869..6c90253a4 100644 --- a/i18n/zh-CN.json +++ b/i18n/zh-CN.json @@ -2515,6 +2515,18 @@ "translation": "团体消息" }, { + "id": "api.templates.deactivate_body.info", + "translation": "You deactivated your account on {{ .SiteURL }}.<br>If this change wasn't initiated by you or you want to reactivate your account, contact your system administrator." + }, + { + "id": "api.templates.deactivate_body.title", + "translation": "Your account has been deactivated at {{ .ServerURL }}" + }, + { + "id": "api.templates.deactivate_subject", + "translation": "[{{ .SiteName }}] Your account at {{ .ServerURL }} has been deactivated" + }, + { "id": "api.templates.email_change_body.info", "translation": "您的邮箱地址从 {{.TeamDisplayName}} 修改为 {{.NewEmail}}。<br>如果您没有做过这个修改,请联系系统管理员。" }, @@ -3023,6 +3035,10 @@ "translation": "此服务器没有正确配置或者不支持 SAML 2.0。" }, { + "id": "api.user.send_deactivate_email_and_forget.failed.error", + "translation": "Failed to send the deactivate account email successfully" + }, + { "id": "api.user.send_email_change_email_and_forget.error", "translation": "未能发送电子邮件通知电子邮件成功" }, @@ -3071,6 +3087,10 @@ "translation": "您无法修改 SSO 帐号的激活状态。请到 SSO 服务器上修改。" }, { + "id": "api.user.update_active.not_enable.app_error", + "translation": "You cannot deactivate yourself because this feature is not enabled. Please contact your System Administrator." + }, + { "id": "api.user.update_active.permissions.app_error", "translation": "您没有对应的权限" }, @@ -3719,10 +3739,6 @@ "translation": "无效用户评论触发 Notify Prop。" }, { - "id": "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", - "translation": "用户的桌面间期 Notify Prop 值无效。" - }, - { "id": "app.import.validate_user_import_data.notify_props_desktop_invalid.error", "translation": "用户的桌面 Notify Prop 值无效。" }, @@ -3855,6 +3871,10 @@ "translation": "无法停用插件" }, { + "id": "app.plugin.delete_plugin_status_state.app_error", + "translation": "无法删除插件状态。" + }, + { "id": "app.plugin.disabled.app_error", "translation": "日志已停用。请检查您的日志了解详情。" }, @@ -3899,10 +3919,18 @@ "translation": "插件未安装" }, { + "id": "app.plugin.prepackaged.app_error", + "translation": "无法安装预包装插件" + }, + { "id": "app.plugin.remove.app_error", "translation": "无法删除插件" }, { + "id": "app.plugin.set_plugin_status_state.app_error", + "translation": "无法设置插件状态。" + }, + { "id": "app.plugin.upload_disabled.app_error", "translation": "插件上传已禁用。" }, @@ -4799,6 +4827,10 @@ "translation": "无法建立 multipart 请求" }, { + "id": "model.cluster.is_valid.id.app_error", + "translation": "无效 Id" + }, + { "id": "model.command.is_valid.create_at.app_error", "translation": "创建时必须是有效时间" }, @@ -7527,6 +7559,10 @@ "translation": "找不到该频道" }, { + "id": "web.incoming_webhook.channel_locked.app_error", + "translation": "This webhook is not permitted to post to the requested channel" + }, + { "id": "web.incoming_webhook.disabled.app_error", "translation": "传入webhooks已经被系统管理员禁用。" }, diff --git a/i18n/zh-TW.json b/i18n/zh-TW.json index 82ec3587e..ad4259e65 100644 --- a/i18n/zh-TW.json +++ b/i18n/zh-TW.json @@ -2515,6 +2515,18 @@ "translation": "群組訊息" }, { + "id": "api.templates.deactivate_body.info", + "translation": "You deactivated your account on {{ .SiteURL }}.<br>If this change wasn't initiated by you or you want to reactivate your account, contact your system administrator." + }, + { + "id": "api.templates.deactivate_body.title", + "translation": "Your account has been deactivated at {{ .ServerURL }}" + }, + { + "id": "api.templates.deactivate_subject", + "translation": "[{{ .SiteName }}] Your account at {{ .ServerURL }} has been deactivated" + }, + { "id": "api.templates.email_change_body.info", "translation": "您在 {{.TeamDisplayName}} 上的電子郵件地址已經變更為 {{.NewEmail}}。<br>如果這不是您所變更的,請聯繫系統管理員。" }, @@ -3023,6 +3035,10 @@ "translation": "本機不支援或未設定 SAML 2.0。" }, { + "id": "api.user.send_deactivate_email_and_forget.failed.error", + "translation": "Failed to send the deactivate account email successfully" + }, + { "id": "api.user.send_email_change_email_and_forget.error", "translation": "更改通知電子郵件傳送失敗" }, @@ -3071,6 +3087,10 @@ "translation": "不能變更 SSO 帳號的啟用狀態。請透過 SSO 伺服器變更。" }, { + "id": "api.user.update_active.not_enable.app_error", + "translation": "You cannot deactivate yourself because this feature is not enabled. Please contact your System Administrator." + }, + { "id": "api.user.update_active.permissions.app_error", "translation": "您沒有適當的權限" }, @@ -3719,10 +3739,6 @@ "translation": "使用者的註解觸發 Notify Props 無效。" }, { - "id": "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", - "translation": "使用者的桌面期間 Notify Props 無效。" - }, - { "id": "app.import.validate_user_import_data.notify_props_desktop_invalid.error", "translation": "使用者的桌面 Notify Props 無效。" }, @@ -3855,6 +3871,10 @@ "translation": "無法停用模組" }, { + "id": "app.plugin.delete_plugin_status_state.app_error", + "translation": "Unable to delete plugin status state." + }, + { "id": "app.plugin.disabled.app_error", "translation": "模組已被停用。詳情請看系統紀錄。" }, @@ -3899,10 +3919,18 @@ "translation": "模組尚未安裝" }, { + "id": "app.plugin.prepackaged.app_error", + "translation": "Cannot install prepackaged plugin" + }, + { "id": "app.plugin.remove.app_error", "translation": "無法刪除模組" }, { + "id": "app.plugin.set_plugin_status_state.app_error", + "translation": "Unable to set plugin status state." + }, + { "id": "app.plugin.upload_disabled.app_error", "translation": "模組 跟/或 上傳模組已被停用。" }, @@ -4799,6 +4827,10 @@ "translation": "無法建立 multipart 要求" }, { + "id": "model.cluster.is_valid.id.app_error", + "translation": "無效的 ID" + }, + { "id": "model.command.is_valid.create_at.app_error", "translation": "\"新增時間\"必須是一個有效時間" }, @@ -7527,6 +7559,10 @@ "translation": "找不到頻道" }, { + "id": "web.incoming_webhook.channel_locked.app_error", + "translation": "This webhook is not permitted to post to the requested channel" + }, + { "id": "web.incoming_webhook.disabled.app_error", "translation": "傳入的 Webhook已被系統管理員停用" }, diff --git a/model/config.go b/model/config.go index ba3a02d33..074632a67 100644 --- a/model/config.go +++ b/model/config.go @@ -8,6 +8,7 @@ import ( "io" "net/http" "net/url" + "regexp" "strings" "time" ) @@ -1772,10 +1773,16 @@ func (s *MessageExportSettings) SetDefaults() { } type DisplaySettings struct { + CustomUrlSchemes *[]string ExperimentalTimezone *bool } func (s *DisplaySettings) SetDefaults() { + if s.CustomUrlSchemes == nil { + customUrlSchemes := []string{} + s.CustomUrlSchemes = &customUrlSchemes + } + if s.ExperimentalTimezone == nil { s.ExperimentalTimezone = NewBool(false) } @@ -1900,10 +1907,18 @@ func (o *Config) SetDefaults() { } func (o *Config) IsValid() *AppError { + if len(*o.ServiceSettings.SiteURL) == 0 && *o.EmailSettings.EnableEmailBatching { + return NewAppError("Config.IsValid", "model.config.is_valid.site_url_email_batching.app_error", nil, "", http.StatusBadRequest) + } + if *o.ClusterSettings.Enable && *o.EmailSettings.EnableEmailBatching { return NewAppError("Config.IsValid", "model.config.is_valid.cluster_email_batching.app_error", nil, "", http.StatusBadRequest) } + if len(*o.ServiceSettings.SiteURL) == 0 && *o.ServiceSettings.AllowCookiesForSubdomains { + return NewAppError("Config.IsValid", "Allowing cookies for subdomains requires SiteURL to be set.", nil, "", http.StatusBadRequest) + } + if err := o.TeamSettings.isValid(); err != nil { return err } @@ -1960,6 +1975,10 @@ func (o *Config) IsValid() *AppError { return err } + if err := o.DisplaySettings.isValid(); err != nil { + return err + } + return nil } @@ -2209,6 +2228,12 @@ func (ss *ServiceSettings) isValid() *AppError { return NewAppError("Config.IsValid", "model.config.is_valid.login_attempts.app_error", nil, "", http.StatusBadRequest) } + if len(*ss.SiteURL) != 0 { + if _, err := url.ParseRequestURI(*ss.SiteURL); err != nil { + return NewAppError("Config.IsValid", "model.config.is_valid.site_url.app_error", nil, "", http.StatusBadRequest) + } + } + if len(*ss.WebsocketURL) != 0 { if _, err := url.ParseRequestURI(*ss.WebsocketURL); err != nil { return NewAppError("Config.IsValid", "model.config.is_valid.websocket_url.app_error", nil, "", http.StatusBadRequest) @@ -2334,6 +2359,26 @@ func (mes *MessageExportSettings) isValid(fs FileSettings) *AppError { return nil } +func (ds *DisplaySettings) isValid() *AppError { + if len(*ds.CustomUrlSchemes) != 0 { + validProtocolPattern := regexp.MustCompile(`(?i)^\s*[a-z][a-z0-9+.-]*\s*$`) + + for _, scheme := range *ds.CustomUrlSchemes { + if !validProtocolPattern.MatchString(scheme) { + return NewAppError( + "Config.IsValid", + "model.config.is_valid.display.custom_url_schemes.app_error", + map[string]interface{}{"Protocol": scheme}, + "", + http.StatusBadRequest, + ) + } + } + } + + return nil +} + func (o *Config) GetSanitizeOptions() map[string]bool { options := map[string]bool{} options["fullname"] = o.PrivacySettings.ShowFullName diff --git a/model/config_test.go b/model/config_test.go index e39ecef3b..5406d680d 100644 --- a/model/config_test.go +++ b/model/config_test.go @@ -82,13 +82,6 @@ func TestConfigDefaultFileSettingsS3SSE(t *testing.T) { } } -func TestConfigDefaultSiteURL(t *testing.T) { - c1 := Config{} - c1.SetDefaults() - - assert.Equal(t, "", *c1.ServiceSettings.SiteURL, "SiteURL should be empty by default.") -} - func TestConfigDefaultServiceSettingsExperimentalGroupUnreadChannels(t *testing.T) { c1 := Config{} c1.SetDefaults() @@ -443,3 +436,86 @@ func TestMessageExportSetDefaultsExportDisabledExportFromTimestampNonZero(t *tes require.Equal(t, int64(0), *mes.ExportFromTimestamp) require.Equal(t, 10000, *mes.BatchSize) } + +func TestDisplaySettingsIsValidCustomUrlSchemes(t *testing.T) { + tests := []struct { + name string + value []string + valid bool + }{ + { + name: "empty", + value: []string{}, + valid: true, + }, + { + name: "custom protocol", + value: []string{"steam"}, + valid: true, + }, + { + name: "multiple custom protocols", + value: []string{"bitcoin", "rss", "redis"}, + valid: true, + }, + { + name: "containing numbers", + value: []string{"ut2004", "ts3server", "h323"}, + valid: true, + }, + { + name: "containing period", + value: []string{"iris.beep"}, + valid: true, + }, + { + name: "containing hyphen", + value: []string{"ms-excel"}, + valid: true, + }, + { + name: "containing plus", + value: []string{"coap+tcp", "coap+ws"}, + valid: true, + }, + { + name: "starting with number", + value: []string{"4four"}, + valid: false, + }, + { + name: "starting with period", + value: []string{"data", ".dot"}, + valid: false, + }, + { + name: "starting with hyphen", + value: []string{"-hyphen", "dns"}, + valid: false, + }, + { + name: "invalid symbols", + value: []string{"!!fun!!"}, + valid: false, + }, + { + name: "invalid letters", + value: []string{"école"}, + valid: false, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + ds := &DisplaySettings{} + ds.SetDefaults() + + ds.CustomUrlSchemes = &test.value + + if err := ds.isValid(); err != nil && test.valid { + t.Error("Expected CustomUrlSchemes to be valid but got error:", err) + } else if err == nil && !test.valid { + t.Error("Expected CustomUrlSchemes to be invalid but got no error") + } + }) + } +} diff --git a/utils/config.go b/utils/config.go index c85da7067..8feb7d882 100644 --- a/utils/config.go +++ b/utils/config.go @@ -448,6 +448,7 @@ func GenerateClientConfig(c *model.Config, diagnosticId string, license *model.L props["WebsocketURL"] = strings.TrimRight(*c.ServiceSettings.WebsocketURL, "/") props["SiteName"] = c.TeamSettings.SiteName props["EnableTeamCreation"] = strconv.FormatBool(*c.TeamSettings.EnableTeamCreation) + props["EnableUserCreation"] = strconv.FormatBool(*c.TeamSettings.EnableUserCreation) props["EnableUserDeactivation"] = strconv.FormatBool(*c.TeamSettings.EnableUserDeactivation) props["EnableOpenServer"] = strconv.FormatBool(*c.TeamSettings.EnableOpenServer) props["RestrictDirectMessage"] = *c.TeamSettings.RestrictDirectMessage @@ -610,6 +611,7 @@ func GenerateClientConfig(c *model.Config, diagnosticId string, license *model.L props["PasswordRequireUppercase"] = strconv.FormatBool(*c.PasswordSettings.Uppercase) props["PasswordRequireNumber"] = strconv.FormatBool(*c.PasswordSettings.Number) props["PasswordRequireSymbol"] = strconv.FormatBool(*c.PasswordSettings.Symbol) + props["CustomUrlSchemes"] = strings.Join(*c.DisplaySettings.CustomUrlSchemes, ",") if license != nil { props["ExperimentalHideTownSquareinLHS"] = strconv.FormatBool(*c.TeamSettings.ExperimentalHideTownSquareinLHS) |