summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/post.go53
-rw-r--r--api/post_test.go68
-rw-r--r--i18n/en.json12
-rw-r--r--i18n/es.json12
4 files changed, 145 insertions, 0 deletions
diff --git a/api/post.go b/api/post.go
index e8345b5e5..b72af7c48 100644
--- a/api/post.go
+++ b/api/post.go
@@ -249,6 +249,7 @@ func handlePostEventsAndForget(c *Context, post *model.Post, triggerWebhooks boo
}
sendNotificationsAndForget(c, post, team, channel)
+ go checkForOutOfChannelMentions(post, channel)
var user *model.User
if result := <-uchan; result.Err != nil {
@@ -728,6 +729,58 @@ func updateMentionCountAndForget(channelId, userId string) {
}()
}
+func checkForOutOfChannelMentions(post *model.Post, channel *model.Channel) {
+ // don't check for out of channel mentions in direct channels
+ if channel.Type == model.CHANNEL_DIRECT {
+ return
+ }
+
+ mentioned := getOutOfChannelMentions(post, channel.TeamId)
+
+ // TODO come up with a way to alert the client of these
+ for _, user := range mentioned {
+ l4g.Debug("%v was mentioned and wasn't in the channel", user.Username)
+ }
+}
+
+// Gets a list of users that were mentioned in a given post that aren't in the channel that the post was made in
+func getOutOfChannelMentions(post *model.Post, teamId string) []*model.User {
+ pchan := Srv.Store.User().GetProfiles(teamId)
+ mchan := Srv.Store.Channel().GetMembers(post.ChannelId)
+
+ var profiles map[string]*model.User
+ if result := <-pchan; result.Err != nil {
+ l4g.Error(utils.T("api.post.get_out_of_channel_mentions.retrieve_profiles.error"), teamId, result.Err)
+ return []*model.User{}
+ } else {
+ profiles = result.Data.(map[string]*model.User)
+ }
+
+ // only keep profiles which aren't in the current channel
+ if result := <-mchan; result.Err != nil {
+ l4g.Error(utils.T("api.post.get_out_of_channel_mentions.retrieve_members.error"), post.ChannelId, result.Err)
+ return []*model.User{}
+ } else {
+ members := result.Data.([]model.ChannelMember)
+
+ for _, member := range members {
+ delete(profiles, member.UserId)
+ }
+ }
+
+ var mentioned []*model.User
+
+ for _, profile := range profiles {
+ if pattern, err := regexp.Compile(`(\W|^)@` + regexp.QuoteMeta(profile.Username) + `(\W|$)`); err != nil {
+ l4g.Error(utils.T("api.post.get_out_of_channel_mentions.regex.error"), profile.Id, err)
+ } else if pattern.MatchString(post.Message) {
+ mentioned = append(mentioned, profile)
+ }
+ }
+
+ return mentioned
+}
+
func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
post := model.PostFromJson(r.Body)
diff --git a/api/post_test.go b/api/post_test.go
index 1a9fd2579..1b05bd39f 100644
--- a/api/post_test.go
+++ b/api/post_test.go
@@ -857,3 +857,71 @@ func TestMakeDirectChannelVisible(t *testing.T) {
t.Fatal("Failed to set direct channel to be visible for user2")
}
}
+
+func TestGetOutOfChannelMentions(t *testing.T) {
+ Setup()
+
+ team1 := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
+ team1 = Client.Must(Client.CreateTeam(team1)).Data.(*model.Team)
+
+ user1 := &model.User{TeamId: team1.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd", Username: "user1"}
+ user1 = Client.Must(Client.CreateUser(user1, "")).Data.(*model.User)
+ store.Must(Srv.Store.User().VerifyEmail(user1.Id))
+
+ user2 := &model.User{TeamId: team1.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd", Username: "user2"}
+ user2 = Client.Must(Client.CreateUser(user2, "")).Data.(*model.User)
+ store.Must(Srv.Store.User().VerifyEmail(user2.Id))
+
+ user3 := &model.User{TeamId: team1.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd", Username: "user3"}
+ user3 = Client.Must(Client.CreateUser(user3, "")).Data.(*model.User)
+ store.Must(Srv.Store.User().VerifyEmail(user3.Id))
+
+ Client.Must(Client.LoginByEmail(team1.Name, user1.Email, "pwd"))
+
+ channel1 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team1.Id}
+ channel1 = Client.Must(Client.CreateChannel(channel1)).Data.(*model.Channel)
+
+ // test a post that doesn't @mention anybody
+ post1 := &model.Post{ChannelId: channel1.Id, Message: "user1 user2 user3"}
+ if mentioned := getOutOfChannelMentions(post1, team1.Id); len(mentioned) != 0 {
+ t.Fatalf("getOutOfChannelMentions returned %v when no users were mentioned", mentioned)
+ }
+
+ // test a post that @mentions someone in the channel
+ post2 := &model.Post{ChannelId: channel1.Id, Message: "@user1 is user1"}
+ if mentioned := getOutOfChannelMentions(post2, team1.Id); len(mentioned) != 0 {
+ t.Fatalf("getOutOfChannelMentions returned %v when only users in the channel were mentioned", mentioned)
+ }
+
+ // test a post that @mentions someone not in the channel
+ post3 := &model.Post{ChannelId: channel1.Id, Message: "@user2 and @user3 aren't in the channel"}
+ if mentioned := getOutOfChannelMentions(post3, team1.Id); len(mentioned) != 2 || (mentioned[0].Id != user2.Id && mentioned[0].Id != user3.Id) || (mentioned[1].Id != user2.Id && mentioned[1].Id != user3.Id) {
+ t.Fatalf("getOutOfChannelMentions returned %v when two users outside the channel were mentioned", mentioned)
+ }
+
+ // test a post that @mentions someone not in the channel as well as someone in the channel
+ post4 := &model.Post{ChannelId: channel1.Id, Message: "@user2 and @user1 might be in the channel"}
+ if mentioned := getOutOfChannelMentions(post4, team1.Id); len(mentioned) != 1 || mentioned[0].Id != user2.Id {
+ t.Fatalf("getOutOfChannelMentions returned %v when someone in the channel and someone outside the channel were mentioned", mentioned)
+ }
+
+ Client.Must(Client.Logout())
+
+ team2 := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
+ team2 = Client.Must(Client.CreateTeam(team2)).Data.(*model.Team)
+
+ user4 := &model.User{TeamId: team2.Id, Email: model.NewId() + "corey+test@test.com", Nickname: "Corey Hulen", Password: "pwd", Username: "user4"}
+ user4 = Client.Must(Client.CreateUser(user4, "")).Data.(*model.User)
+ store.Must(Srv.Store.User().VerifyEmail(user4.Id))
+
+ Client.Must(Client.LoginByEmail(team2.Name, user4.Email, "pwd"))
+
+ channel2 := &model.Channel{DisplayName: "Test API Name", Name: "a" + model.NewId() + "a", Type: model.CHANNEL_OPEN, TeamId: team2.Id}
+ channel2 = Client.Must(Client.CreateChannel(channel2)).Data.(*model.Channel)
+
+ // test a post that @mentions someone on a different team
+ post5 := &model.Post{ChannelId: channel2.Id, Message: "@user2 and @user3 might be in the channel"}
+ if mentioned := getOutOfChannelMentions(post5, team2.Id); len(mentioned) != 0 {
+ t.Fatalf("getOutOfChannelMentions returned %v when two users on a different team were mentioned", mentioned)
+ }
+}
diff --git a/i18n/en.json b/i18n/en.json
index 2d86e1ee5..e620a1f0d 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -684,6 +684,18 @@
"translation": "You do not have the appropriate permissions"
},
{
+ "id": "api.post.get_out_of_channel_mentions.retrieve_members.error",
+ "translation": "Failed to get channel members channel_id=%v err=%v"
+ },
+ {
+ "id": "api.post.get_out_of_channel_mentions.retrieve_profiles.error",
+ "translation": "Failed to retrieve user profiles team_id=%v, err=%v"
+ },
+ {
+ "id": "api.post.get_out_of_channel_mentions.regex.error",
+ "translation": "Failed to compile @mention regex user_id=%v, err=%v"
+ },
+ {
"id": "api.post.get_post.permissions.app_error",
"translation": "You do not have the appropriate permissions"
},
diff --git a/i18n/es.json b/i18n/es.json
index 9599fe879..328571f3b 100644
--- a/i18n/es.json
+++ b/i18n/es.json
@@ -684,6 +684,18 @@
"translation": "No tienes los permisos apropiados"
},
{
+ "id": "api.post.get_out_of_channel_mentions.retrieve_members.error",
+ "translation": "Falla al obtener los miembros del canal channel_id=%v err=%v"
+ },
+ {
+ "id": "api.post.get_out_of_channel_mentions.retrieve_profiles.error",
+ "translation": "Falla al recuperar los perfiles de usuario team_id=%v, err=%v"
+ },
+ {
+ "id": "api.post.get_out_of_channel_mentions.regex.error",
+ "translation": "Failed to compile @mention regex user_id=%v, err=%v"
+ },
+ {
"id": "api.post.get_post.permissions.app_error",
"translation": "No tienes los permisos apropiados"
},