summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api4/image_test.go5
-rw-r--r--app/notification.go81
-rw-r--r--app/notification_test.go45
-rw-r--r--app/post.go20
-rw-r--r--app/post_test.go54
-rw-r--r--app/team.go12
-rw-r--r--app/team_test.go89
-rw-r--r--i18n/en.json4
-rw-r--r--model/config.go2
9 files changed, 197 insertions, 115 deletions
diff --git a/api4/image_test.go b/api4/image_test.go
index 236d5785d..aa3619cdd 100644
--- a/api4/image_test.go
+++ b/api4/image_test.go
@@ -37,7 +37,8 @@ func TestGetImage(t *testing.T) {
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
th.App.UpdateConfig(func(cfg *model.Config) {
- cfg.ServiceSettings.ImageProxyType = model.NewString("willnorris/imageproxy")
+ cfg.ServiceSettings.ImageProxyType = model.NewString("atmos/camo")
+ cfg.ServiceSettings.ImageProxyOptions = model.NewString("foo")
cfg.ServiceSettings.ImageProxyURL = model.NewString("https://proxy.foo.bar")
})
@@ -48,5 +49,5 @@ func TestGetImage(t *testing.T) {
resp, err = th.Client.HttpClient.Do(r)
require.NoError(t, err)
assert.Equal(t, http.StatusFound, resp.StatusCode)
- assert.Equal(t, "https://proxy.foo.bar//"+originURL, resp.Header.Get("Location"))
+ assert.Equal(t, "https://proxy.foo.bar/004afe2ef382eb5f30c4490f793f8a8c5b33d8a2/687474703a2f2f666f6f2e6261722f62617a2e676966", resp.Header.Get("Location"))
}
diff --git a/app/notification.go b/app/notification.go
index 1318308f8..e158e08d5 100644
--- a/app/notification.go
+++ b/app/notification.go
@@ -819,44 +819,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 +875,10 @@ func GetExplicitMentions(message string, keywords map[string][]string) *Explicit
})
for _, splitWord := range splitWords {
- if splitWord == "@here" {
- ret.HereMentioned = true
+ if checkForMention(splitWord) {
+ continue
}
-
- 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)
- }
-
- // 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..bd7da3db7 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}},
diff --git a/app/post.go b/app/post.go
index 1964bd3cf..a541797fa 100644
--- a/app/post.go
+++ b/app/post.go
@@ -6,8 +6,6 @@ package app
import (
"crypto/hmac"
"crypto/sha1"
- "crypto/sha256"
- "encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
@@ -950,18 +948,6 @@ func (a *App) ImageProxyAdder() func(string) string {
mac.Write([]byte(url))
digest := hex.EncodeToString(mac.Sum(nil))
return proxyURL + digest + "/" + hex.EncodeToString([]byte(url))
- case "willnorris/imageproxy":
- options := strings.Split(options, "|")
- if len(options) > 1 {
- mac := hmac.New(sha256.New, []byte(options[1]))
- mac.Write([]byte(url))
- digest := base64.URLEncoding.EncodeToString(mac.Sum(nil))
- if options[0] == "" {
- return proxyURL + "s" + digest + "/" + url
- }
- return proxyURL + options[0] + ",s" + digest + "/" + url
- }
- return proxyURL + options[0] + "/" + url
}
return url
@@ -984,12 +970,6 @@ func (a *App) ImageProxyRemover() (f func(string) string) {
}
}
}
- case "willnorris/imageproxy":
- if strings.HasPrefix(url, proxyURL) {
- if slash := strings.IndexByte(url[len(proxyURL):], '/'); slash >= 0 {
- return url[len(proxyURL)+slash+1:]
- }
- }
}
return url
diff --git a/app/post_test.go b/app/post_test.go
index c8ed726b1..ebe973270 100644
--- a/app/post_test.go
+++ b/app/post_test.go
@@ -210,38 +210,27 @@ func TestImageProxy(t *testing.T) {
ImageURL: "http://mydomain.com/myimage",
ProxiedImageURL: "https://127.0.0.1/f8dace906d23689e8d5b12c3cefbedbf7b9b72f5/687474703a2f2f6d79646f6d61696e2e636f6d2f6d79696d616765",
},
- "willnorris/imageproxy": {
- ProxyType: "willnorris/imageproxy",
- ProxyURL: "https://127.0.0.1",
- ProxyOptions: "x1000",
- ImageURL: "http://mydomain.com/myimage",
- ProxiedImageURL: "https://127.0.0.1/x1000/http://mydomain.com/myimage",
- },
- "willnorris/imageproxy_SameSite": {
- ProxyType: "willnorris/imageproxy",
+ "atmos/camo_SameSite": {
+ ProxyType: "atmos/camo",
ProxyURL: "https://127.0.0.1",
+ ProxyOptions: "foo",
ImageURL: "http://mymattermost.com/myimage",
ProxiedImageURL: "http://mymattermost.com/myimage",
},
- "willnorris/imageproxy_PathOnly": {
- ProxyType: "willnorris/imageproxy",
+ "atmos/camo_PathOnly": {
+ ProxyType: "atmos/camo",
ProxyURL: "https://127.0.0.1",
+ ProxyOptions: "foo",
ImageURL: "/myimage",
ProxiedImageURL: "/myimage",
},
- "willnorris/imageproxy_EmptyImageURL": {
- ProxyType: "willnorris/imageproxy",
+ "atmos/camo_EmptyImageURL": {
+ ProxyType: "atmos/camo",
ProxyURL: "https://127.0.0.1",
+ ProxyOptions: "foo",
ImageURL: "",
ProxiedImageURL: "",
},
- "willnorris/imageproxy_WithSigning": {
- ProxyType: "willnorris/imageproxy",
- ProxyURL: "https://127.0.0.1",
- ProxyOptions: "x1000|foo",
- ImageURL: "http://mydomain.com/myimage",
- ProxiedImageURL: "https://127.0.0.1/x1000,sbhHVoG5d60UvnNtGh6Iy6x4PaMmnsh8JfZ7JfErKjGU=/http://mydomain.com/myimage",
- },
} {
t.Run(name, func(t *testing.T) {
th.App.UpdateConfig(func(cfg *model.Config) {
@@ -356,27 +345,4 @@ func TestMakeOpenGraphURLsAbsolute(t *testing.T) {
}
})
}
-}
-
-var imageProxyBenchmarkSink *model.Post
-
-func BenchmarkPostWithProxyRemovedFromImageURLs(b *testing.B) {
- th := Setup().InitBasic()
- defer th.TearDown()
-
- th.App.UpdateConfig(func(cfg *model.Config) {
- cfg.ServiceSettings.ImageProxyType = model.NewString("willnorris/imageproxy")
- cfg.ServiceSettings.ImageProxyOptions = model.NewString("x1000|foo")
- cfg.ServiceSettings.ImageProxyURL = model.NewString("https://127.0.0.1")
- })
-
- post := &model.Post{
- Message: "![foo](http://mydomain.com/myimage)",
- }
-
- b.ResetTimer()
-
- for i := 0; i < b.N; i++ {
- imageProxyBenchmarkSink = th.App.PostWithProxyAddedToImageURLs(post)
- }
-}
+} \ No newline at end of file
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")
+ }
+ })
+}
diff --git a/i18n/en.json b/i18n/en.json
index 41fd9d982..ffdf7e5a3 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -3127,6 +3127,10 @@
"translation": "Invalid {{.Name}} parameter"
},
{
+ "id": "app.team.join_user_to_team.max_accounts.app_error",
+ "translation": "This team has reached the maximum number of allowed accounts. Contact your systems administrator to set a higher limit."
+ },
+ {
"id": "app.channel.create_channel.no_team_id.app_error",
"translation": "Must specify the team ID to create a channel"
},
diff --git a/model/config.go b/model/config.go
index 20011f7cb..7390b4fd9 100644
--- a/model/config.go
+++ b/model/config.go
@@ -2085,7 +2085,7 @@ func (ss *ServiceSettings) isValid() *AppError {
}
switch *ss.ImageProxyType {
- case "", "willnorris/imageproxy":
+ case "":
case "atmos/camo":
if *ss.ImageProxyOptions == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.atmos_camo_image_proxy_options.app_error", nil, "", http.StatusBadRequest)