diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/notification.go | 171 | ||||
-rw-r--r-- | app/notification_test.go | 280 | ||||
-rw-r--r-- | app/team.go | 12 | ||||
-rw-r--r-- | app/team_test.go | 89 |
4 files changed, 465 insertions, 87 deletions
diff --git a/app/notification.go b/app/notification.go index 1318308f8..24e84500b 100644 --- a/app/notification.go +++ b/app/notification.go @@ -566,8 +566,6 @@ func (a *App) sendPushNotification(post *model.Post, user *model.User, channel * channelName = senderName } - userLocale := utils.GetUserTranslations(user.Locale) - msg := model.PushNotification{} if badge := <-a.Srv.Store.User().GetUnreadCount(user.Id); badge.Err != nil { msg.Badge = 1 @@ -596,44 +594,10 @@ func (a *App) sendPushNotification(post *model.Post, user *model.User, channel * msg.FromWebhook = fw } - if *a.Config().EmailSettings.PushNotificationContents == model.FULL_NOTIFICATION { - msg.Category = model.CATEGORY_CAN_REPLY - if channel.Type == model.CHANNEL_DIRECT { - msg.Message = senderName + ": " + model.ClearMentionTags(post.Message) - } else { - msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_in") + channelName + ": " + model.ClearMentionTags(post.Message) - } - } else if *a.Config().EmailSettings.PushNotificationContents == model.GENERIC_NO_CHANNEL_NOTIFICATION { - if channel.Type == model.CHANNEL_DIRECT { - msg.Category = model.CATEGORY_CAN_REPLY - msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_message") - } else if wasMentioned || channel.Type == model.CHANNEL_GROUP { - msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_mention_no_channel") - } else { - msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_non_mention_no_channel") - } - } else { - if channel.Type == model.CHANNEL_DIRECT { - msg.Category = model.CATEGORY_CAN_REPLY - msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_message") - } else if wasMentioned || channel.Type == model.CHANNEL_GROUP { - msg.Category = model.CATEGORY_CAN_REPLY - msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_mention") + channelName - } else { - msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_non_mention") + channelName - } - } - - // If the post only has images then push an appropriate message - if len(post.Message) == 0 && post.FileIds != nil && len(post.FileIds) > 0 { - if channel.Type == model.CHANNEL_DIRECT { - msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_image_only_dm") - } else { - msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_image_only") + channelName - } - } + userLocale := utils.GetUserTranslations(user.Locale) + hasFiles := post.FileIds != nil && len(post.FileIds) > 0 - //l4g.Debug("Sending push notification for user %v with msg of '%v'", user.Id, msg.Message) + msg.Message, msg.Category = a.getPushNotificationMessage(post.Message, wasMentioned, hasFiles, senderName, channelName, channel.Type, userLocale) for _, session := range sessions { tmpMessage := *model.PushNotificationFromJson(strings.NewReader(msg.ToJson())) @@ -655,6 +619,54 @@ 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) { + message := "" + category := "" + + if *a.Config().EmailSettings.PushNotificationContents == model.FULL_NOTIFICATION { + category = model.CATEGORY_CAN_REPLY + + if channelType == model.CHANNEL_DIRECT { + message = senderName + ": " + model.ClearMentionTags(postMessage) + } else { + message = senderName + userLocale("api.post.send_notifications_and_forget.push_in") + channelName + ": " + model.ClearMentionTags(postMessage) + } + } else if *a.Config().EmailSettings.PushNotificationContents == 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") + } + } 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 + } else { + message = senderName + userLocale("api.post.send_notifications_and_forget.push_non_mention") + channelName + } + } + + // 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 { + message = senderName + userLocale("api.post.send_notifications_and_forget.push_image_only") + channelName + } + } + + return message, category +} + func (a *App) ClearPushNotification(userId string, channelId string) { a.Go(func() { // Sleep is to allow the read replicas a chance to fully sync @@ -819,44 +831,52 @@ func GetExplicitMentions(message string, keywords map[string][]string) *Explicit ret.MentionedUserIds[id] = true } } + checkForMention := func(word string) bool { + isMention := false + + if word == "@here" { + ret.HereMentioned = true + } + if word == "@channel" { + ret.ChannelMentioned = true + } + + if word == "@all" { + ret.AllMentioned = true + } + + // Non-case-sensitive check for regular keys + if ids, match := keywords[strings.ToLower(word)]; match { + addMentionedUsers(ids) + isMention = true + } + + // Case-sensitive check for first name + if ids, match := keywords[word]; match { + addMentionedUsers(ids) + isMention = true + } + + return isMention + } processText := func(text string) { for _, word := range strings.FieldsFunc(text, func(c rune) bool { // Split on any whitespace or punctuation that can't be part of an at mention or emoji pattern return !(c == ':' || c == '.' || c == '-' || c == '_' || c == '@' || unicode.IsLetter(c) || unicode.IsNumber(c)) }) { - isMention := false - // skip word with format ':word:' with an assumption that it is an emoji format only if word[0] == ':' && word[len(word)-1] == ':' { continue } - if word == "@here" { - ret.HereMentioned = true - } - - if word == "@channel" { - ret.ChannelMentioned = true - } - - if word == "@all" { - ret.AllMentioned = true - } - - // Non-case-sensitive check for regular keys - if ids, match := keywords[strings.ToLower(word)]; match { - addMentionedUsers(ids) - isMention = true - } - - // Case-sensitive check for first name - if ids, match := keywords[word]; match { - addMentionedUsers(ids) - isMention = true + if checkForMention(word) { + continue } - if isMention { + // remove trailing '.', as that is the end of a sentence + word = strings.TrimSuffix(word, ".") + if checkForMention(word) { continue } @@ -867,27 +887,10 @@ func GetExplicitMentions(message string, keywords map[string][]string) *Explicit }) for _, splitWord := range splitWords { - if splitWord == "@here" { - ret.HereMentioned = true - } - - if splitWord == "@all" { - ret.AllMentioned = true - } - - if splitWord == "@channel" { - ret.ChannelMentioned = true - } - - // Non-case-sensitive check for regular keys - if ids, match := keywords[strings.ToLower(splitWord)]; match { - addMentionedUsers(ids) + if checkForMention(splitWord) { + continue } - - // Case-sensitive check for first name - if ids, match := keywords[splitWord]; match { - addMentionedUsers(ids) - } else if _, ok := systemMentions[splitWord]; !ok && strings.HasPrefix(splitWord, "@") { + if _, ok := systemMentions[splitWord]; !ok && strings.HasPrefix(splitWord, "@") { username := splitWord[1:] ret.OtherPotentialMentions = append(ret.OtherPotentialMentions, username) } diff --git a/app/notification_test.go b/app/notification_test.go index 11f4df685..43703c019 100644 --- a/app/notification_test.go +++ b/app/notification_test.go @@ -109,6 +109,33 @@ func TestGetExplicitMentions(t *testing.T) { }, }, }, + "OnePersonWithPeriodAtEndOfUsername": { + Message: "this is a message for @user.name.", + Keywords: map[string][]string{"@user.name.": {id1}}, + Expected: &ExplicitMentions{ + MentionedUserIds: map[string]bool{ + id1: true, + }, + }, + }, + "OnePersonWithPeriodAtEndOfUsernameButNotSimilarName": { + Message: "this is a message for @user.name.", + Keywords: map[string][]string{"@user.name.": {id1}, "@user.name": {id2}}, + Expected: &ExplicitMentions{ + MentionedUserIds: map[string]bool{ + id1: true, + }, + }, + }, + "OnePersonAtEndOfSentence": { + Message: "this is a message for @user.", + Keywords: map[string][]string{"@user": {id1}}, + Expected: &ExplicitMentions{ + MentionedUserIds: map[string]bool{ + id1: true, + }, + }, + }, "OnePersonWithoutAtMention": { Message: "this is a message for @user", Keywords: map[string][]string{"this": {id1}}, @@ -179,6 +206,24 @@ func TestGetExplicitMentions(t *testing.T) { }, }, }, + "AtUserWithPeriodAtEndOfSentence": { + Message: "this is a message for @user.period.", + Keywords: map[string][]string{"@user.period": {id1}}, + Expected: &ExplicitMentions{ + MentionedUserIds: map[string]bool{ + id1: true, + }, + }, + }, + "UserWithPeriodAtEndOfSentence": { + Message: "this is a message for user.period.", + Keywords: map[string][]string{"user.period": {id1}}, + Expected: &ExplicitMentions{ + MentionedUserIds: map[string]bool{ + id1: true, + }, + }, + }, "PotentialOutOfChannelUser": { Message: "this is an message for @potential and @user", Keywords: map[string][]string{"@user": {id1}}, @@ -1166,3 +1211,238 @@ func TestGetNotificationEmailBodyGenericNotificationDirectChannel(t *testing.T) t.Fatal("Expected email text '" + teamURL + "'. Got " + body) } } + +func TestGetPushNotificationMessage(t *testing.T) { + th := Setup() + defer th.TearDown() + + for name, tc := range map[string]struct { + Message string + WasMentioned bool + HasFiles bool + Locale string + PushNotificationContents string + ChannelType string + + ExpectedMessage string + ExpectedCategory 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, + }, + "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, + }, + "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, + }, + "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, + }, + "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, + }, + "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, + }, + "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, + }, + "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, + }, + "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", + }, + "generic message with channel, public channel, mention": { + Message: "this is a message", + WasMentioned: true, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_OPEN, + ExpectedMessage: "user mentioned you in channel", + ExpectedCategory: model.CATEGORY_CAN_REPLY, + }, + "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", + }, + "generic message with channel, private channel, mention": { + Message: "this is a message", + WasMentioned: true, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_PRIVATE, + ExpectedMessage: "user mentioned you in channel", + ExpectedCategory: model.CATEGORY_CAN_REPLY, + }, + "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", + }, + "generic message with channel, group message channel, mention": { + Message: "this is a message", + WasMentioned: true, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_GROUP, + ExpectedMessage: "user mentioned you in channel", + ExpectedCategory: model.CATEGORY_CAN_REPLY, + }, + "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, + }, + "generic message with channel, direct message channel, mention": { + Message: "this is a message", + WasMentioned: true, + PushNotificationContents: model.GENERIC_NOTIFICATION, + ChannelType: model.CHANNEL_DIRECT, + ExpectedMessage: "user sent you a direct message", + ExpectedCategory: model.CATEGORY_CAN_REPLY, + }, + "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", + }, + "generic message without channel, public channel, mention": { + Message: "this is a message", + WasMentioned: true, + PushNotificationContents: model.GENERIC_NO_CHANNEL_NOTIFICATION, + ChannelType: model.CHANNEL_OPEN, + 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", + }, + "generic message without channel, private channel, mention": { + Message: "this is a message", + WasMentioned: true, + PushNotificationContents: model.GENERIC_NO_CHANNEL_NOTIFICATION, + ChannelType: model.CHANNEL_PRIVATE, + 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", + }, + "generic message without channel, group message channel, mention": { + Message: "this is a message", + WasMentioned: true, + PushNotificationContents: model.GENERIC_NO_CHANNEL_NOTIFICATION, + ChannelType: model.CHANNEL_GROUP, + 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, + }, + "generic message without channel, direct message channel, mention": { + Message: "this is a message", + WasMentioned: true, + PushNotificationContents: model.GENERIC_NO_CHANNEL_NOTIFICATION, + ChannelType: model.CHANNEL_DIRECT, + ExpectedMessage: "user sent you a direct message", + ExpectedCategory: model.CATEGORY_CAN_REPLY, + }, + "only files, public channel": { + HasFiles: true, + ChannelType: model.CHANNEL_OPEN, + ExpectedMessage: "user uploaded one or more files in channel", + ExpectedCategory: model.CATEGORY_CAN_REPLY, + }, + "only files, private channel": { + HasFiles: true, + ChannelType: model.CHANNEL_PRIVATE, + ExpectedMessage: "user uploaded one or more files in channel", + ExpectedCategory: model.CATEGORY_CAN_REPLY, + }, + "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, + }, + "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, + }, + } { + t.Run(name, func(t *testing.T) { + locale := tc.Locale + if locale == "" { + locale = "en" + } + + pushNotificationContents := tc.PushNotificationContents + if pushNotificationContents == "" { + pushNotificationContents = model.FULL_NOTIFICATION + } + + th.App.UpdateConfig(func(cfg *model.Config) { + *cfg.EmailSettings.PushNotificationContents = pushNotificationContents + }) + + if actualMessage, actualCategory := th.App.getPushNotificationMessage( + tc.Message, + tc.WasMentioned, + tc.HasFiles, + "user", + "channel", + tc.ChannelType, + 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/app/team.go b/app/team.go index 8e8c29e2a..a15c64c3f 100644 --- a/app/team.go +++ b/app/team.go @@ -302,10 +302,16 @@ func (a *App) joinUserToTeam(team *model.Team, user *model.User) (*model.TeamMem return rtm, true, nil } - if tmr := <-a.Srv.Store.Team().UpdateMember(tm); tmr.Err != nil { - return nil, false, tmr.Err + if membersCount := <-a.Srv.Store.Team().GetActiveMemberCount(tm.TeamId); membersCount.Err != nil { + return nil, false, membersCount.Err + } else if membersCount.Data.(int64) >= int64(*a.Config().TeamSettings.MaxUsersPerTeam) { + return nil, false, model.NewAppError("joinUserToTeam", "app.team.join_user_to_team.max_accounts.app_error", nil, "teamId="+tm.TeamId, http.StatusBadRequest) } else { - return tmr.Data.(*model.TeamMember), false, nil + if tmr := <-a.Srv.Store.Team().UpdateMember(tm); tmr.Err != nil { + return nil, false, tmr.Err + } else { + return tmr.Data.(*model.TeamMember), false, nil + } } } else { // Membership appears to be missing. Lets try to add. diff --git a/app/team_test.go b/app/team_test.go index 7cb20b6f6..a2bf44a57 100644 --- a/app/team_test.go +++ b/app/team_test.go @@ -460,3 +460,92 @@ func TestAddUserToTeamByHashMismatchedInviteId(t *testing.T) { assert.Nil(t, team) assert.Equal(t, "api.user.create_user.signup_link_mismatched_invite_id.app_error", err.Id) } + +func TestJoinUserToTeam(t *testing.T) { + th := Setup().InitBasic() + defer th.TearDown() + + id := model.NewId() + team := &model.Team{ + DisplayName: "dn_" + id, + Name: "name" + id, + Email: "success+" + id + "@simulator.amazonses.com", + Type: model.TEAM_OPEN, + } + + if _, err := th.App.CreateTeam(team); err != nil { + t.Log(err) + t.Fatal("Should create a new team") + } + + maxUsersPerTeam := th.App.Config().TeamSettings.MaxUsersPerTeam + defer func() { + th.App.UpdateConfig(func(cfg *model.Config) { cfg.TeamSettings.MaxUsersPerTeam = maxUsersPerTeam }) + th.App.SetDefaultRolesBasedOnConfig() + th.App.PermanentDeleteTeam(team) + }() + one := 1 + th.App.UpdateConfig(func(cfg *model.Config) { cfg.TeamSettings.MaxUsersPerTeam = &one }) + + t.Run("new join", func(t *testing.T) { + user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser, _ := th.App.CreateUser(&user) + defer th.App.PermanentDeleteUser(&user) + + if _, alreadyAdded, err := th.App.joinUserToTeam(team, ruser); alreadyAdded || err != nil { + t.Fatal("Should return already added equal to false and no error") + } + }) + + t.Run("join when you are a member", func(t *testing.T) { + user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser, _ := th.App.CreateUser(&user) + defer th.App.PermanentDeleteUser(&user) + + th.App.joinUserToTeam(team, ruser) + if _, alreadyAdded, err := th.App.joinUserToTeam(team, ruser); !alreadyAdded || err != nil { + t.Fatal("Should return already added and no error") + } + }) + + t.Run("re-join after leaving", func(t *testing.T) { + user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser, _ := th.App.CreateUser(&user) + defer th.App.PermanentDeleteUser(&user) + + th.App.joinUserToTeam(team, ruser) + th.App.LeaveTeam(team, ruser, ruser.Id) + if _, alreadyAdded, err := th.App.joinUserToTeam(team, ruser); alreadyAdded || err != nil { + t.Fatal("Should return already added equal to false and no error") + } + }) + + t.Run("new join with limit problem", func(t *testing.T) { + user1 := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser1, _ := th.App.CreateUser(&user1) + user2 := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser2, _ := th.App.CreateUser(&user2) + defer th.App.PermanentDeleteUser(&user1) + defer th.App.PermanentDeleteUser(&user2) + th.App.joinUserToTeam(team, ruser1) + if _, _, err := th.App.joinUserToTeam(team, ruser2); err == nil { + t.Fatal("Should fail") + } + }) + + t.Run("re-join alfter leaving with limit problem", func(t *testing.T) { + user1 := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser1, _ := th.App.CreateUser(&user1) + user2 := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""} + ruser2, _ := th.App.CreateUser(&user2) + defer th.App.PermanentDeleteUser(&user1) + defer th.App.PermanentDeleteUser(&user2) + + th.App.joinUserToTeam(team, ruser1) + th.App.LeaveTeam(team, ruser1, ruser1.Id) + th.App.joinUserToTeam(team, ruser2) + if _, _, err := th.App.joinUserToTeam(team, ruser1); err == nil { + t.Fatal("Should fail") + } + }) +} |