PLT-7183: User/Channel NotifyProps Bulk Import. (#7019)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
489151d2d2
Коммит
4132a02319
132
app/import.go
132
app/import.go
@@ -71,6 +71,23 @@ type UserImportData struct {
|
|||||||
MessageDisplay *string `json:"message_display"`
|
MessageDisplay *string `json:"message_display"`
|
||||||
ChannelDisplayMode *string `json:"channel_display_mode"`
|
ChannelDisplayMode *string `json:"channel_display_mode"`
|
||||||
TutorialStep *string `json:"tutorial_step"`
|
TutorialStep *string `json:"tutorial_step"`
|
||||||
|
|
||||||
|
NotifyProps *UserNotifyPropsImportData `json:"notify_props"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserNotifyPropsImportData struct {
|
||||||
|
Desktop *string `json:"desktop"`
|
||||||
|
DesktopDuration *string `json:"desktop_duration"`
|
||||||
|
DesktopSound *string `json:"desktop_sound"`
|
||||||
|
|
||||||
|
Email *string `json:"email"`
|
||||||
|
|
||||||
|
Mobile *string `json:"mobile"`
|
||||||
|
MobilePushStatus *string `json:"mobile_push_status"`
|
||||||
|
|
||||||
|
ChannelTrigger *string `json:"channel"`
|
||||||
|
CommentsTrigger *string `json:"comments"`
|
||||||
|
MentionKeys *string `json:"mention_keys"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserTeamImportData struct {
|
type UserTeamImportData struct {
|
||||||
@@ -88,6 +105,7 @@ type UserChannelImportData struct {
|
|||||||
|
|
||||||
type UserChannelNotifyPropsImportData struct {
|
type UserChannelNotifyPropsImportData struct {
|
||||||
Desktop *string `json:"desktop"`
|
Desktop *string `json:"desktop"`
|
||||||
|
Mobile *string `json:"mobile"`
|
||||||
MarkUnread *string `json:"mark_unread"`
|
MarkUnread *string `json:"mark_unread"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,6 +462,7 @@ func ImportUser(data *UserImportData, dryRun bool) *model.AppError {
|
|||||||
|
|
||||||
// We want to avoid database writes if nothing has changed.
|
// We want to avoid database writes if nothing has changed.
|
||||||
hasUserChanged := false
|
hasUserChanged := false
|
||||||
|
hasNotifyPropsChanged := false
|
||||||
hasUserRolesChanged := false
|
hasUserRolesChanged := false
|
||||||
hasUserAuthDataChanged := false
|
hasUserAuthDataChanged := false
|
||||||
hasUserEmailVerifiedChanged := false
|
hasUserEmailVerifiedChanged := false
|
||||||
@@ -453,6 +472,7 @@ func ImportUser(data *UserImportData, dryRun bool) *model.AppError {
|
|||||||
user = result.Data.(*model.User)
|
user = result.Data.(*model.User)
|
||||||
} else {
|
} else {
|
||||||
user = &model.User{}
|
user = &model.User{}
|
||||||
|
user.MakeNonNil()
|
||||||
hasUserChanged = true
|
hasUserChanged = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -557,6 +577,71 @@ func ImportUser(data *UserImportData, dryRun bool) *model.AppError {
|
|||||||
}
|
}
|
||||||
user.Roles = roles
|
user.Roles = roles
|
||||||
|
|
||||||
|
if data.NotifyProps != nil {
|
||||||
|
if data.NotifyProps.Desktop != nil {
|
||||||
|
if value, ok := user.NotifyProps[model.DESKTOP_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Desktop {
|
||||||
|
user.AddNotifyProp(model.DESKTOP_NOTIFY_PROP, *data.NotifyProps.Desktop)
|
||||||
|
hasNotifyPropsChanged = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps.DesktopDuration != nil {
|
||||||
|
if value, ok := user.NotifyProps[model.DESKTOP_DURATION_NOTIFY_PROP]; !ok || value != *data.NotifyProps.DesktopDuration {
|
||||||
|
user.AddNotifyProp(model.DESKTOP_DURATION_NOTIFY_PROP, *data.NotifyProps.DesktopDuration)
|
||||||
|
hasNotifyPropsChanged = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps.DesktopSound != nil {
|
||||||
|
if value, ok := user.NotifyProps[model.DESKTOP_SOUND_NOTIFY_PROP]; !ok || value != *data.NotifyProps.DesktopSound {
|
||||||
|
user.AddNotifyProp(model.DESKTOP_SOUND_NOTIFY_PROP, *data.NotifyProps.DesktopSound)
|
||||||
|
hasNotifyPropsChanged = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps.Email != nil {
|
||||||
|
if value, ok := user.NotifyProps[model.EMAIL_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Email {
|
||||||
|
user.AddNotifyProp(model.EMAIL_NOTIFY_PROP, *data.NotifyProps.Email)
|
||||||
|
hasNotifyPropsChanged = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps.Mobile != nil {
|
||||||
|
if value, ok := user.NotifyProps[model.PUSH_NOTIFY_PROP]; !ok || value != *data.NotifyProps.Mobile {
|
||||||
|
user.AddNotifyProp(model.PUSH_NOTIFY_PROP, *data.NotifyProps.Mobile)
|
||||||
|
hasNotifyPropsChanged = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps.MobilePushStatus != nil {
|
||||||
|
if value, ok := user.NotifyProps[model.PUSH_STATUS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.MobilePushStatus {
|
||||||
|
user.AddNotifyProp(model.PUSH_STATUS_NOTIFY_PROP, *data.NotifyProps.MobilePushStatus)
|
||||||
|
hasNotifyPropsChanged = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps.ChannelTrigger != nil {
|
||||||
|
if value, ok := user.NotifyProps[model.CHANNEL_MENTIONS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.ChannelTrigger {
|
||||||
|
user.AddNotifyProp(model.CHANNEL_MENTIONS_NOTIFY_PROP, *data.NotifyProps.ChannelTrigger)
|
||||||
|
hasNotifyPropsChanged = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps.CommentsTrigger != nil {
|
||||||
|
if value, ok := user.NotifyProps[model.COMMENTS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.CommentsTrigger {
|
||||||
|
user.AddNotifyProp(model.COMMENTS_NOTIFY_PROP, *data.NotifyProps.CommentsTrigger)
|
||||||
|
hasNotifyPropsChanged = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps.MentionKeys != nil {
|
||||||
|
if value, ok := user.NotifyProps[model.MENTION_KEYS_NOTIFY_PROP]; !ok || value != *data.NotifyProps.MentionKeys {
|
||||||
|
user.AddNotifyProp(model.MENTION_KEYS_NOTIFY_PROP, *data.NotifyProps.MentionKeys)
|
||||||
|
hasNotifyPropsChanged = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if user.Id == "" {
|
if user.Id == "" {
|
||||||
if _, err := createUser(user); err != nil {
|
if _, err := createUser(user); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -572,6 +657,11 @@ func ImportUser(data *UserImportData, dryRun bool) *model.AppError {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if hasNotifyPropsChanged {
|
||||||
|
if _, err := UpdateUserNotifyProps(user.Id, user.NotifyProps); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
if len(password) > 0 {
|
if len(password) > 0 {
|
||||||
if err := UpdatePassword(user, password); err != nil {
|
if err := UpdatePassword(user, password); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -747,6 +837,10 @@ func ImportUserChannels(user *model.User, team *model.Team, teamMember *model.Te
|
|||||||
notifyProps[model.DESKTOP_NOTIFY_PROP] = *cdata.NotifyProps.Desktop
|
notifyProps[model.DESKTOP_NOTIFY_PROP] = *cdata.NotifyProps.Desktop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cdata.NotifyProps.Mobile != nil {
|
||||||
|
notifyProps[model.PUSH_NOTIFY_PROP] = *cdata.NotifyProps.Mobile
|
||||||
|
}
|
||||||
|
|
||||||
if cdata.NotifyProps.MarkUnread != nil {
|
if cdata.NotifyProps.MarkUnread != nil {
|
||||||
notifyProps[model.MARK_UNREAD_NOTIFY_PROP] = *cdata.NotifyProps.MarkUnread
|
notifyProps[model.MARK_UNREAD_NOTIFY_PROP] = *cdata.NotifyProps.MarkUnread
|
||||||
}
|
}
|
||||||
@@ -829,6 +923,40 @@ func validateUserImportData(data *UserImportData) *model.AppError {
|
|||||||
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.roles_invalid.error", nil, "", http.StatusBadRequest)
|
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.roles_invalid.error", nil, "", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps != nil {
|
||||||
|
if data.NotifyProps.Desktop != nil && !model.IsValidUserNotifyLevel(*data.NotifyProps.Desktop) {
|
||||||
|
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_desktop_invalid.error", nil, "", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps.DesktopDuration != nil && !model.IsValidNumberString(*data.NotifyProps.DesktopDuration) {
|
||||||
|
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_desktop_duration_invalid.error", nil, "", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps.DesktopSound != nil && !model.IsValidTrueOrFalseString(*data.NotifyProps.DesktopSound) {
|
||||||
|
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_desktop_sound_invalid.error", nil, "", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps.Email != nil && !model.IsValidTrueOrFalseString(*data.NotifyProps.Email) {
|
||||||
|
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_email_invalid.error", nil, "", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps.Mobile != nil && !model.IsValidUserNotifyLevel(*data.NotifyProps.Mobile) {
|
||||||
|
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_mobile_invalid.error", nil, "", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps.MobilePushStatus != nil && !model.IsValidPushStatusNotifyLevel(*data.NotifyProps.MobilePushStatus) {
|
||||||
|
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_mobile_push_status_invalid.error", nil, "", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps.ChannelTrigger != nil && !model.IsValidTrueOrFalseString(*data.NotifyProps.ChannelTrigger) {
|
||||||
|
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_channel_trigger_invalid.error", nil, "", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
if data.NotifyProps.CommentsTrigger != nil && !model.IsValidCommentsNotifyLevel(*data.NotifyProps.CommentsTrigger) {
|
||||||
|
return model.NewAppError("BulkImport", "app.import.validate_user_import_data.notify_props_comments_trigger_invalid.error", nil, "", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if data.Teams != nil {
|
if data.Teams != nil {
|
||||||
return validateUserTeamsImportData(data.Teams)
|
return validateUserTeamsImportData(data.Teams)
|
||||||
} else {
|
} else {
|
||||||
@@ -879,6 +1007,10 @@ func validateUserChannelsImportData(data *[]UserChannelImportData) *model.AppErr
|
|||||||
return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_notify_props_desktop.error", nil, "", http.StatusBadRequest)
|
return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_notify_props_desktop.error", nil, "", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if cdata.NotifyProps.Mobile != nil && !model.IsChannelNotifyLevelValid(*cdata.NotifyProps.Mobile) {
|
||||||
|
return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_notify_props_mobile.error", nil, "", http.StatusBadRequest)
|
||||||
|
}
|
||||||
|
|
||||||
if cdata.NotifyProps.MarkUnread != nil && !model.IsChannelMarkUnreadLevelValid(*cdata.NotifyProps.MarkUnread) {
|
if cdata.NotifyProps.MarkUnread != nil && !model.IsChannelMarkUnreadLevelValid(*cdata.NotifyProps.MarkUnread) {
|
||||||
return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_notify_props_mark_unread.error", nil, "", http.StatusBadRequest)
|
return model.NewAppError("BulkImport", "app.import.validate_user_channels_import_data.invalid_notify_props_mark_unread.error", nil, "", http.StatusBadRequest)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,30 @@ func checkPreference(t *testing.T, userId string, category string, name string,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkNotifyProp(t *testing.T, user *model.User, key string, value string) {
|
||||||
|
if actual, ok := user.NotifyProps[key]; !ok {
|
||||||
|
debug.PrintStack()
|
||||||
|
t.Fatalf("Notify prop %v not found. User: %v", key, user.Id)
|
||||||
|
} else if actual != value {
|
||||||
|
debug.PrintStack()
|
||||||
|
t.Fatalf("Notify Prop %v was %v but expected %v. User: %v", key, actual, value, user.Id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkError(t *testing.T, err *model.AppError) {
|
||||||
|
if err == nil {
|
||||||
|
debug.PrintStack()
|
||||||
|
t.Fatal("Should have returned an error.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkNoError(t *testing.T, err *model.AppError) {
|
||||||
|
if err != nil {
|
||||||
|
debug.PrintStack()
|
||||||
|
t.Fatalf("Unexpected Error: %v", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestImportValidateTeamImportData(t *testing.T) {
|
func TestImportValidateTeamImportData(t *testing.T) {
|
||||||
|
|
||||||
// Test with minimum required valid properties.
|
// Test with minimum required valid properties.
|
||||||
@@ -392,6 +416,44 @@ func TestImportValidateUserImportData(t *testing.T) {
|
|||||||
t.Fatal("Validation failed but should have been valid.")
|
t.Fatal("Validation failed but should have been valid.")
|
||||||
}
|
}
|
||||||
data.Roles = ptrStr("system_user")
|
data.Roles = ptrStr("system_user")
|
||||||
|
|
||||||
|
// Try various valid/invalid notify props.
|
||||||
|
data.NotifyProps = &UserNotifyPropsImportData{}
|
||||||
|
|
||||||
|
data.NotifyProps.Desktop = ptrStr("invalid")
|
||||||
|
checkError(t, validateUserImportData(&data))
|
||||||
|
|
||||||
|
data.NotifyProps.Desktop = ptrStr(model.USER_NOTIFY_ALL)
|
||||||
|
data.NotifyProps.DesktopDuration = ptrStr("invalid")
|
||||||
|
checkError(t, validateUserImportData(&data))
|
||||||
|
|
||||||
|
data.NotifyProps.DesktopDuration = ptrStr("5")
|
||||||
|
data.NotifyProps.DesktopSound = ptrStr("invalid")
|
||||||
|
checkError(t, validateUserImportData(&data))
|
||||||
|
|
||||||
|
data.NotifyProps.DesktopSound = ptrStr("true")
|
||||||
|
data.NotifyProps.Email = ptrStr("invalid")
|
||||||
|
checkError(t, validateUserImportData(&data))
|
||||||
|
|
||||||
|
data.NotifyProps.Email = ptrStr("true")
|
||||||
|
data.NotifyProps.Mobile = ptrStr("invalid")
|
||||||
|
checkError(t, validateUserImportData(&data))
|
||||||
|
|
||||||
|
data.NotifyProps.Mobile = ptrStr(model.USER_NOTIFY_ALL)
|
||||||
|
data.NotifyProps.MobilePushStatus = ptrStr("invalid")
|
||||||
|
checkError(t, validateUserImportData(&data))
|
||||||
|
|
||||||
|
data.NotifyProps.MobilePushStatus = ptrStr(model.STATUS_ONLINE)
|
||||||
|
data.NotifyProps.ChannelTrigger = ptrStr("invalid")
|
||||||
|
checkError(t, validateUserImportData(&data))
|
||||||
|
|
||||||
|
data.NotifyProps.ChannelTrigger = ptrStr("true")
|
||||||
|
data.NotifyProps.CommentsTrigger = ptrStr("invalid")
|
||||||
|
checkError(t, validateUserImportData(&data))
|
||||||
|
|
||||||
|
data.NotifyProps.CommentsTrigger = ptrStr(model.COMMENTS_NOTIFY_ROOT)
|
||||||
|
data.NotifyProps.MentionKeys = ptrStr("valid")
|
||||||
|
checkNoError(t, validateUserImportData(&data))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestImportValidateUserTeamsImportData(t *testing.T) {
|
func TestImportValidateUserTeamsImportData(t *testing.T) {
|
||||||
@@ -481,14 +543,21 @@ func TestImportValidateUserChannelsImportData(t *testing.T) {
|
|||||||
t.Fatal("Should have failed with invalid desktop notify props.")
|
t.Fatal("Should have failed with invalid desktop notify props.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalid desktop notify props.
|
// Invalid mobile notify props.
|
||||||
data[0].NotifyProps.Desktop = ptrStr("mention")
|
data[0].NotifyProps.Desktop = ptrStr("mention")
|
||||||
|
data[0].NotifyProps.Mobile = ptrStr("invalid")
|
||||||
|
if err := validateUserChannelsImportData(&data); err == nil {
|
||||||
|
t.Fatal("Should have failed with invalid mobile notify props.")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invalid mark_unread notify props.
|
||||||
|
data[0].NotifyProps.Mobile = ptrStr("mention")
|
||||||
data[0].NotifyProps.MarkUnread = ptrStr("invalid")
|
data[0].NotifyProps.MarkUnread = ptrStr("invalid")
|
||||||
if err := validateUserChannelsImportData(&data); err == nil {
|
if err := validateUserChannelsImportData(&data); err == nil {
|
||||||
t.Fatal("Should have failed with invalid mark_unread notify props.")
|
t.Fatal("Should have failed with invalid mark_unread notify props.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Empty notify props.
|
// Valid notify props.
|
||||||
data[0].NotifyProps.MarkUnread = ptrStr("mention")
|
data[0].NotifyProps.MarkUnread = ptrStr("mention")
|
||||||
if err := validateUserChannelsImportData(&data); err != nil {
|
if err := validateUserChannelsImportData(&data); err != nil {
|
||||||
t.Fatal("Should have succeeded with valid notify props.")
|
t.Fatal("Should have succeeded with valid notify props.")
|
||||||
@@ -1621,7 +1690,7 @@ func TestImportImportUser(t *testing.T) {
|
|||||||
// Check channel member properties.
|
// Check channel member properties.
|
||||||
if channelMember, err := GetChannelMember(channel.Id, user.Id); err != nil {
|
if channelMember, err := GetChannelMember(channel.Id, user.Id); err != nil {
|
||||||
t.Fatalf("Failed to get channel member from database.")
|
t.Fatalf("Failed to get channel member from database.")
|
||||||
} else if channelMember.Roles != "channel_user" || channelMember.NotifyProps[model.DESKTOP_NOTIFY_PROP] != "default" || channelMember.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != "all" {
|
} else if channelMember.Roles != "channel_user" || channelMember.NotifyProps[model.DESKTOP_NOTIFY_PROP] != "default" || channelMember.NotifyProps[model.PUSH_NOTIFY_PROP] != "default" || channelMember.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != "all" {
|
||||||
t.Fatalf("Channel member properties not as expected")
|
t.Fatalf("Channel member properties not as expected")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1636,6 +1705,7 @@ func TestImportImportUser(t *testing.T) {
|
|||||||
Roles: ptrStr("channel_user channel_admin"),
|
Roles: ptrStr("channel_user channel_admin"),
|
||||||
NotifyProps: &UserChannelNotifyPropsImportData{
|
NotifyProps: &UserChannelNotifyPropsImportData{
|
||||||
Desktop: ptrStr(model.USER_NOTIFY_MENTION),
|
Desktop: ptrStr(model.USER_NOTIFY_MENTION),
|
||||||
|
Mobile: ptrStr(model.USER_NOTIFY_MENTION),
|
||||||
MarkUnread: ptrStr(model.USER_NOTIFY_MENTION),
|
MarkUnread: ptrStr(model.USER_NOTIFY_MENTION),
|
||||||
},
|
},
|
||||||
Favorite: ptrBool(true),
|
Favorite: ptrBool(true),
|
||||||
@@ -1656,7 +1726,7 @@ func TestImportImportUser(t *testing.T) {
|
|||||||
|
|
||||||
if channelMember, err := GetChannelMember(channel.Id, user.Id); err != nil {
|
if channelMember, err := GetChannelMember(channel.Id, user.Id); err != nil {
|
||||||
t.Fatalf("Failed to get channel member Desktop from database.")
|
t.Fatalf("Failed to get channel member Desktop from database.")
|
||||||
} else if channelMember.Roles != "channel_user channel_admin" && channelMember.NotifyProps[model.DESKTOP_NOTIFY_PROP] == model.USER_NOTIFY_MENTION && channelMember.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] == model.USER_NOTIFY_MENTION {
|
} else if channelMember.Roles != "channel_user channel_admin" || channelMember.NotifyProps[model.DESKTOP_NOTIFY_PROP] != model.USER_NOTIFY_MENTION || channelMember.NotifyProps[model.PUSH_NOTIFY_PROP] != model.USER_NOTIFY_MENTION || channelMember.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP] != model.USER_NOTIFY_MENTION {
|
||||||
t.Fatalf("Channel member properties not as expected")
|
t.Fatalf("Channel member properties not as expected")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1726,6 +1796,105 @@ func TestImportImportUser(t *testing.T) {
|
|||||||
checkPreference(t, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "message_display", *data.MessageDisplay)
|
checkPreference(t, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "message_display", *data.MessageDisplay)
|
||||||
checkPreference(t, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "channel_display_mode", *data.ChannelDisplayMode)
|
checkPreference(t, user.Id, model.PREFERENCE_CATEGORY_DISPLAY_SETTINGS, "channel_display_mode", *data.ChannelDisplayMode)
|
||||||
checkPreference(t, user.Id, model.PREFERENCE_CATEGORY_TUTORIAL_STEPS, user.Id, *data.TutorialStep)
|
checkPreference(t, user.Id, model.PREFERENCE_CATEGORY_TUTORIAL_STEPS, user.Id, *data.TutorialStep)
|
||||||
|
|
||||||
|
// Set Notify Props
|
||||||
|
data.NotifyProps = &UserNotifyPropsImportData{
|
||||||
|
Desktop: ptrStr(model.USER_NOTIFY_ALL),
|
||||||
|
DesktopDuration: ptrStr("5"),
|
||||||
|
DesktopSound: ptrStr("true"),
|
||||||
|
Email: ptrStr("true"),
|
||||||
|
Mobile: ptrStr(model.USER_NOTIFY_ALL),
|
||||||
|
MobilePushStatus: ptrStr(model.STATUS_ONLINE),
|
||||||
|
ChannelTrigger: ptrStr("true"),
|
||||||
|
CommentsTrigger: ptrStr(model.COMMENTS_NOTIFY_ROOT),
|
||||||
|
MentionKeys: ptrStr("valid,misc"),
|
||||||
|
}
|
||||||
|
if err := ImportUser(&data, false); err != nil {
|
||||||
|
t.Fatalf("Should have succeeded.")
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err = GetUserByUsername(username)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get user from database.")
|
||||||
|
}
|
||||||
|
|
||||||
|
checkNotifyProp(t, user, model.DESKTOP_NOTIFY_PROP, model.USER_NOTIFY_ALL)
|
||||||
|
checkNotifyProp(t, user, model.DESKTOP_DURATION_NOTIFY_PROP, "5")
|
||||||
|
checkNotifyProp(t, user, model.DESKTOP_SOUND_NOTIFY_PROP, "true")
|
||||||
|
checkNotifyProp(t, user, model.EMAIL_NOTIFY_PROP, "true")
|
||||||
|
checkNotifyProp(t, user, model.PUSH_NOTIFY_PROP, model.USER_NOTIFY_ALL)
|
||||||
|
checkNotifyProp(t, user, model.PUSH_STATUS_NOTIFY_PROP, model.STATUS_ONLINE)
|
||||||
|
checkNotifyProp(t, user, model.CHANNEL_MENTIONS_NOTIFY_PROP, "true")
|
||||||
|
checkNotifyProp(t, user, model.COMMENTS_NOTIFY_PROP, model.COMMENTS_NOTIFY_ROOT)
|
||||||
|
checkNotifyProp(t, user, model.MENTION_KEYS_NOTIFY_PROP, "valid,misc")
|
||||||
|
|
||||||
|
// Change Notify Props
|
||||||
|
data.NotifyProps = &UserNotifyPropsImportData{
|
||||||
|
Desktop: ptrStr(model.USER_NOTIFY_MENTION),
|
||||||
|
DesktopDuration: ptrStr("3"),
|
||||||
|
DesktopSound: ptrStr("false"),
|
||||||
|
Email: ptrStr("false"),
|
||||||
|
Mobile: ptrStr(model.USER_NOTIFY_NONE),
|
||||||
|
MobilePushStatus: ptrStr(model.STATUS_AWAY),
|
||||||
|
ChannelTrigger: ptrStr("false"),
|
||||||
|
CommentsTrigger: ptrStr(model.COMMENTS_NOTIFY_ANY),
|
||||||
|
MentionKeys: ptrStr("misc"),
|
||||||
|
}
|
||||||
|
if err := ImportUser(&data, false); err != nil {
|
||||||
|
t.Fatalf("Should have succeeded.")
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err = GetUserByUsername(username)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get user from database.")
|
||||||
|
}
|
||||||
|
|
||||||
|
checkNotifyProp(t, user, model.DESKTOP_NOTIFY_PROP, model.USER_NOTIFY_MENTION)
|
||||||
|
checkNotifyProp(t, user, model.DESKTOP_DURATION_NOTIFY_PROP, "3")
|
||||||
|
checkNotifyProp(t, user, model.DESKTOP_SOUND_NOTIFY_PROP, "false")
|
||||||
|
checkNotifyProp(t, user, model.EMAIL_NOTIFY_PROP, "false")
|
||||||
|
checkNotifyProp(t, user, model.PUSH_NOTIFY_PROP, model.USER_NOTIFY_NONE)
|
||||||
|
checkNotifyProp(t, user, model.PUSH_STATUS_NOTIFY_PROP, model.STATUS_AWAY)
|
||||||
|
checkNotifyProp(t, user, model.CHANNEL_MENTIONS_NOTIFY_PROP, "false")
|
||||||
|
checkNotifyProp(t, user, model.COMMENTS_NOTIFY_PROP, model.COMMENTS_NOTIFY_ANY)
|
||||||
|
checkNotifyProp(t, user, model.MENTION_KEYS_NOTIFY_PROP, "misc")
|
||||||
|
|
||||||
|
// Check Notify Props get set on *create* user.
|
||||||
|
username = model.NewId()
|
||||||
|
data = UserImportData{
|
||||||
|
Username: &username,
|
||||||
|
Email: ptrStr(model.NewId() + "@example.com"),
|
||||||
|
}
|
||||||
|
data.NotifyProps = &UserNotifyPropsImportData{
|
||||||
|
Desktop: ptrStr(model.USER_NOTIFY_MENTION),
|
||||||
|
DesktopDuration: ptrStr("3"),
|
||||||
|
DesktopSound: ptrStr("false"),
|
||||||
|
Email: ptrStr("false"),
|
||||||
|
Mobile: ptrStr(model.USER_NOTIFY_NONE),
|
||||||
|
MobilePushStatus: ptrStr(model.STATUS_AWAY),
|
||||||
|
ChannelTrigger: ptrStr("false"),
|
||||||
|
CommentsTrigger: ptrStr(model.COMMENTS_NOTIFY_ANY),
|
||||||
|
MentionKeys: ptrStr("misc"),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ImportUser(&data, false); err != nil {
|
||||||
|
t.Fatalf("Should have succeeded.")
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err = GetUserByUsername(username)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Failed to get user from database.")
|
||||||
|
}
|
||||||
|
|
||||||
|
checkNotifyProp(t, user, model.DESKTOP_NOTIFY_PROP, model.USER_NOTIFY_MENTION)
|
||||||
|
checkNotifyProp(t, user, model.DESKTOP_DURATION_NOTIFY_PROP, "3")
|
||||||
|
checkNotifyProp(t, user, model.DESKTOP_SOUND_NOTIFY_PROP, "false")
|
||||||
|
checkNotifyProp(t, user, model.EMAIL_NOTIFY_PROP, "false")
|
||||||
|
checkNotifyProp(t, user, model.PUSH_NOTIFY_PROP, model.USER_NOTIFY_NONE)
|
||||||
|
checkNotifyProp(t, user, model.PUSH_STATUS_NOTIFY_PROP, model.STATUS_AWAY)
|
||||||
|
checkNotifyProp(t, user, model.CHANNEL_MENTIONS_NOTIFY_PROP, "false")
|
||||||
|
checkNotifyProp(t, user, model.COMMENTS_NOTIFY_PROP, model.COMMENTS_NOTIFY_ANY)
|
||||||
|
checkNotifyProp(t, user, model.MENTION_KEYS_NOTIFY_PROP, "misc")
|
||||||
}
|
}
|
||||||
|
|
||||||
func AssertAllPostsCount(t *testing.T, initialCount int64, change int64, teamName string) {
|
func AssertAllPostsCount(t *testing.T, initialCount int64, change int64, teamName string) {
|
||||||
|
|||||||
36
i18n/en.json
36
i18n/en.json
@@ -3355,6 +3355,10 @@
|
|||||||
"id": "app.import.validate_user_channels_import_data.invalid_notify_props_desktop.error",
|
"id": "app.import.validate_user_channels_import_data.invalid_notify_props_desktop.error",
|
||||||
"translation": "Invalid Desktop NotifyProps for User's Channel Membership."
|
"translation": "Invalid Desktop NotifyProps for User's Channel Membership."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "app.import.validate_user_channels_import_data.invalid_notify_props_mobile.error",
|
||||||
|
"translation": "Invalid Mobile NotifyProps for User's Channel Membership."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "app.import.validate_user_channels_import_data.invalid_notify_props_mark_unread.error",
|
"id": "app.import.validate_user_channels_import_data.invalid_notify_props_mark_unread.error",
|
||||||
"translation": "Invalid MarkUnread NotifyProps for User's Channel Membership."
|
"translation": "Invalid MarkUnread NotifyProps for User's Channel Membership."
|
||||||
@@ -3415,6 +3419,38 @@
|
|||||||
"id": "app.import.validate_user_import_data.username_missing.error",
|
"id": "app.import.validate_user_import_data.username_missing.error",
|
||||||
"translation": "Missing require user property: username."
|
"translation": "Missing require user property: username."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "app.import.validate_user_import_data.notify_props_desktop_invalid.error",
|
||||||
|
"translation": "Invalid Desktop Notify Prop value 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_sound_invalid.error",
|
||||||
|
"translation": "Invalid Desktop Sound Notify Prop value for user."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "app.import.validate_user_import_data.notify_props_email_invalid.error",
|
||||||
|
"translation": "Invalid Email Notify Prop value for user."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "app.import.validate_user_import_data.notify_props_mobile_invalid.error",
|
||||||
|
"translation": "Invalid Mobile Notify Prop value for user."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "app.import.validate_user_import_data.notify_props_mobile_push_status_invalid.error",
|
||||||
|
"translation": "Invalid Mobile Push Status Notify Prop for user."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "app.import.validate_user_import_data.notify_props_channel_trigger_invalid.error",
|
||||||
|
"translation": "Invalid Channel Trigger Notify Prop for user."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "app.import.validate_user_import_data.notify_props_comment_trigger_invalid.error",
|
||||||
|
"translation": "Invalid Comment Trigger Notify Prop for user."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "app.import.validate_user_teams_import_data.invalid_roles.error",
|
"id": "app.import.validate_user_teams_import_data.invalid_roles.error",
|
||||||
"translation": "Invalid roles for User's Team Membership."
|
"translation": "Invalid roles for User's Team Membership."
|
||||||
|
|||||||
@@ -16,14 +16,23 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ME = "me"
|
ME = "me"
|
||||||
USER_NOTIFY_ALL = "all"
|
USER_NOTIFY_ALL = "all"
|
||||||
USER_NOTIFY_MENTION = "mention"
|
USER_NOTIFY_MENTION = "mention"
|
||||||
USER_NOTIFY_NONE = "none"
|
USER_NOTIFY_NONE = "none"
|
||||||
DESKTOP_NOTIFY_PROP = "desktop"
|
DESKTOP_NOTIFY_PROP = "desktop"
|
||||||
MARK_UNREAD_NOTIFY_PROP = "mark_unread"
|
DESKTOP_SOUND_NOTIFY_PROP = "desktop_sound"
|
||||||
PUSH_NOTIFY_PROP = "push"
|
DESKTOP_DURATION_NOTIFY_PROP = "desktop_duration"
|
||||||
EMAIL_NOTIFY_PROP = "email"
|
MARK_UNREAD_NOTIFY_PROP = "mark_unread"
|
||||||
|
PUSH_NOTIFY_PROP = "push"
|
||||||
|
PUSH_STATUS_NOTIFY_PROP = "push_status"
|
||||||
|
EMAIL_NOTIFY_PROP = "email"
|
||||||
|
CHANNEL_MENTIONS_NOTIFY_PROP = "channel"
|
||||||
|
COMMENTS_NOTIFY_PROP = "comments"
|
||||||
|
MENTION_KEYS_NOTIFY_PROP = "mention_keys"
|
||||||
|
COMMENTS_NOTIFY_NEVER = "never"
|
||||||
|
COMMENTS_NOTIFY_ROOT = "root"
|
||||||
|
COMMENTS_NOTIFY_ANY = "any"
|
||||||
|
|
||||||
DEFAULT_LOCALE = "en"
|
DEFAULT_LOCALE = "en"
|
||||||
USER_AUTH_SERVICE_EMAIL = "email"
|
USER_AUTH_SERVICE_EMAIL = "email"
|
||||||
@@ -604,3 +613,21 @@ func CleanUsername(s string) string {
|
|||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsValidUserNotifyLevel(notifyLevel string) bool {
|
||||||
|
return notifyLevel == CHANNEL_NOTIFY_ALL ||
|
||||||
|
notifyLevel == CHANNEL_NOTIFY_MENTION ||
|
||||||
|
notifyLevel == CHANNEL_NOTIFY_NONE
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsValidPushStatusNotifyLevel(notifyLevel string) bool {
|
||||||
|
return notifyLevel == STATUS_ONLINE ||
|
||||||
|
notifyLevel == STATUS_AWAY ||
|
||||||
|
notifyLevel == STATUS_OFFLINE
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsValidCommentsNotifyLevel(notifyLevel string) bool {
|
||||||
|
return notifyLevel == COMMENTS_NOTIFY_ANY ||
|
||||||
|
notifyLevel == COMMENTS_NOTIFY_ROOT ||
|
||||||
|
notifyLevel == COMMENTS_NOTIFY_NEVER
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net"
|
||||||
"net/mail"
|
"net/mail"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"net"
|
|
||||||
|
|
||||||
goi18n "github.com/nicksnyder/go-i18n/i18n"
|
goi18n "github.com/nicksnyder/go-i18n/i18n"
|
||||||
"github.com/pborman/uuid"
|
"github.com/pborman/uuid"
|
||||||
)
|
)
|
||||||
@@ -480,3 +480,15 @@ func IsValidWebsocketUrl(rawUrl string) bool {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsValidTrueOrFalseString(value string) bool {
|
||||||
|
return value == "true" || value == "false"
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsValidNumberString(value string) bool {
|
||||||
|
if _, err := strconv.Atoi(value); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|||||||
Ссылка в новой задаче
Block a user