From 5f37741fe33ba93607ad51a782ff5da569135048 Mon Sep 17 00:00:00 2001 From: Philipp Heckel Date: Tue, 22 Mar 2022 19:43:08 -0400 Subject: [PATCH] :generics-intensifies: --- cmd/access.go | 6 +++--- cmd/serve.go | 4 ++-- cmd/user.go | 2 +- go.mod | 12 ++++++------ go.sum | 16 ++++++++++------ server/server.go | 4 ++-- server/smtp_sender.go | 2 +- server/types.go | 4 ++-- util/gzip_handler.go | 2 +- util/util.go | 18 ++++-------------- util/util_test.go | 12 ++++++------ 11 files changed, 38 insertions(+), 44 deletions(-) diff --git a/cmd/access.go b/cmd/access.go index b3cacfa5..d36a54de 100644 --- a/cmd/access.go +++ b/cmd/access.go @@ -91,11 +91,11 @@ func execUserAccess(c *cli.Context) error { } func changeAccess(c *cli.Context, manager auth.Manager, username string, topic string, perms string) error { - if !util.InStringList([]string{"", "read-write", "rw", "read-only", "read", "ro", "write-only", "write", "wo", "none", "deny"}, perms) { + if !util.Contains([]string{"", "read-write", "rw", "read-only", "read", "ro", "write-only", "write", "wo", "none", "deny"}, perms) { return errors.New("permission must be one of: read-write, read-only, write-only, or deny (or the aliases: read, ro, write, wo, none)") } - read := util.InStringList([]string{"read-write", "rw", "read-only", "read", "ro"}, perms) - write := util.InStringList([]string{"read-write", "rw", "write-only", "write", "wo"}, perms) + read := util.Contains([]string{"read-write", "rw", "read-only", "read", "ro"}, perms) + write := util.Contains([]string{"read-write", "rw", "write-only", "write", "wo"}, perms) user, err := manager.User(username) if err == auth.ErrNotFound { return fmt.Errorf("user %s does not exist", username) diff --git a/cmd/serve.go b/cmd/serve.go index 2fd878d5..837debcc 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -136,9 +136,9 @@ func execServe(c *cli.Context) error { return errors.New("if attachment-cache-dir is set, base-url must also be set") } else if baseURL != "" && !strings.HasPrefix(baseURL, "http://") && !strings.HasPrefix(baseURL, "https://") { return errors.New("if set, base-url must start with http:// or https://") - } else if !util.InStringList([]string{"read-write", "read-only", "write-only", "deny-all"}, authDefaultAccess) { + } else if !util.Contains([]string{"read-write", "read-only", "write-only", "deny-all"}, authDefaultAccess) { return errors.New("if set, auth-default-access must start set to 'read-write', 'read-only', 'write-only' or 'deny-all'") - } else if !util.InStringList([]string{"app", "home"}, webRoot) { + } else if !util.Contains([]string{"app", "home"}, webRoot) { return errors.New("if set, web-root must be 'home' or 'app'") } diff --git a/cmd/user.go b/cmd/user.go index 1057ba48..fd1b8ea3 100644 --- a/cmd/user.go +++ b/cmd/user.go @@ -237,7 +237,7 @@ func createAuthManager(c *cli.Context) (auth.Manager, error) { return nil, errors.New("option auth-file not set; auth is unconfigured for this server") } else if !util.FileExists(authFile) { return nil, errors.New("auth-file does not exist; please start the server at least once to create it") - } else if !util.InStringList([]string{"read-write", "read-only", "write-only", "deny-all"}, authDefaultAccess) { + } else if !util.Contains([]string{"read-write", "read-only", "write-only", "deny-all"}, authDefaultAccess) { return nil, errors.New("if set, auth-default-access must start set to 'read-write', 'read-only' or 'deny-all'") } authDefaultRead := authDefaultAccess == "read-write" || authDefaultAccess == "read-only" diff --git a/go.mod b/go.mod index bd45a4d4..9c860791 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module heckel.io/ntfy -go 1.17 +go 1.18 require ( cloud.google.com/go/firestore v1.6.1 // indirect @@ -15,7 +15,7 @@ require ( github.com/olebedev/when v0.0.0-20211212231525-59bd4edcf9d6 github.com/stretchr/testify v1.7.0 github.com/urfave/cli/v2 v2.4.0 - golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 + golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 @@ -28,7 +28,7 @@ require ( cloud.google.com/go v0.100.2 // indirect cloud.google.com/go/compute v1.5.0 // indirect cloud.google.com/go/iam v0.3.0 // indirect - github.com/AlekSi/pointer v1.0.0 // indirect + github.com/AlekSi/pointer v1.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -40,12 +40,12 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect go.opencensus.io v0.23.0 // indirect golang.org/x/net v0.0.0-20220225172249-27dd8689420f // indirect - golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 // indirect + golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106 // indirect + google.golang.org/genproto v0.0.0-20220322021311-435b647f9ef2 // indirect google.golang.org/grpc v1.45.0 // indirect - google.golang.org/protobuf v1.27.1 // indirect + google.golang.org/protobuf v1.28.0 // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect ) diff --git a/go.sum b/go.sum index fe238256..89da262a 100644 --- a/go.sum +++ b/go.sum @@ -61,8 +61,9 @@ cloud.google.com/go/storage v1.21.0/go.mod h1:XmRlxkgPjlBONznT2dDUU/5XlpU2OjMnKu dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= firebase.google.com/go v3.13.0+incompatible h1:3TdYC3DDi6aHn20qoRkxwGqNgdjtblwVAyRLQwGn/+4= firebase.google.com/go v3.13.0+incompatible/go.mod h1:xlah6XbEyW6tbfSklcfe5FHJIwjt8toICdV5Wh9ptHs= -github.com/AlekSi/pointer v1.0.0 h1:KWCWzsvFxNLcmM5XmiqHsGTTsuwZMsLFwWF9Y+//bNE= github.com/AlekSi/pointer v1.0.0/go.mod h1:1kjywbfcPFCmncIxtk6fIEub6LKrfMz3gc5QKVOSOA8= +github.com/AlekSi/pointer v1.2.0 h1:glcy/gc4h8HnG2Z3ZECSzZ1IX1x2JxRVuDzaJwQE0+w= +github.com/AlekSi/pointer v1.2.0/go.mod h1:gZGfd3dpW4vEc/UlyfKKi1roIqcCgwOIvb0tSNSBle0= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.0.0 h1:dtDWrepsVPfW9H/4y7dDgFc2MBUSeJhlaDtK13CxFlU= github.com/BurntSushi/toml v1.0.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -244,8 +245,9 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 h1:S25/rfnfsMVgORT4/J61MJ7rdyseOZOyvLIrZEZ7s6s= +golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -406,8 +408,9 @@ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5 h1:y/woIyUBFbpQGKS0u1aHF/40WUDnek3fPOyD08H5Vng= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8 h1:OH54vjqzRWmbJ62fjuhxy7AxFFgoHN0/DPc/UrL8cAs= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -604,8 +607,8 @@ google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2 google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106 h1:ErU+UA6wxadoU8nWrsy5MZUVBs75K17zUCsUCIfrXCE= -google.golang.org/genproto v0.0.0-20220314164441-57ef72a4c106/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= +google.golang.org/genproto v0.0.0-20220322021311-435b647f9ef2 h1:3n0D2NdPGm0g0wrVJzXJWW5CBOoqgGBkDX9cRMJHZAY= +google.golang.org/genproto v0.0.0-20220322021311-435b647f9ef2/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -648,8 +651,9 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/server/server.go b/server/server.go index a0de013d..e536d617 100644 --- a/server/server.go +++ b/server/server.go @@ -918,7 +918,7 @@ func (s *Server) topicsFromIDs(ids ...string) ([]*topic, error) { defer s.mu.Unlock() topics := make([]*topic, 0) for _, id := range ids { - if util.InStringList(disallowedTopics, id) { + if util.Contains(disallowedTopics, id) { return nil, errHTTPBadRequestTopicDisallowed } if _, ok := s.topics[id]; !ok { @@ -1086,7 +1086,7 @@ func (s *Server) sendDelayedMessages() error { func (s *Server) limitRequests(next handleFunc) handleFunc { return func(w http.ResponseWriter, r *http.Request, v *visitor) error { - if util.InStringList(s.config.VisitorRequestExemptIPAddrs, v.ip) { + if util.Contains(s.config.VisitorRequestExemptIPAddrs, v.ip) { return next(w, r, v) } else if err := v.RequestAllowed(); err != nil { return errHTTPTooManyRequestsLimitRequests diff --git a/server/smtp_sender.go b/server/smtp_sender.go index 15f004c1..8551be3c 100644 --- a/server/smtp_sender.go +++ b/server/smtp_sender.go @@ -108,7 +108,7 @@ func toEmojis(tags []string) (emojisOut []string, tagsOut []string, err error) { nextTag: for _, t := range tags { // TODO Super inefficient; we should just create a .json file with a map for _, e := range emojis { - if util.InStringList(e.Aliases, t) { + if util.Contains(e.Aliases, t) { emojisOut = append(emojisOut, e.Emoji) continue nextTag } diff --git a/server/types.go b/server/types.go index 6594f050..cd41f0ed 100644 --- a/server/types.go +++ b/server/types.go @@ -169,10 +169,10 @@ func (q *queryFilter) Pass(msg *message) bool { if messagePriority == 0 { messagePriority = 3 // For query filters, default priority (3) is the same as "not set" (0) } - if len(q.Priority) > 0 && !util.InIntList(q.Priority, messagePriority) { + if len(q.Priority) > 0 && !util.Contains(q.Priority, messagePriority) { return false } - if len(q.Tags) > 0 && !util.InStringListAll(msg.Tags, q.Tags) { + if len(q.Tags) > 0 && !util.ContainsAll(msg.Tags, q.Tags) { return false } return true diff --git a/util/gzip_handler.go b/util/gzip_handler.go index 613df48e..bac4efc9 100644 --- a/util/gzip_handler.go +++ b/util/gzip_handler.go @@ -31,7 +31,7 @@ func Gzip(next http.Handler) http.Handler { } var gzPool = sync.Pool{ - New: func() interface{} { + New: func() any { w := gzip.NewWriter(ioutil.Discard) return w }, diff --git a/util/util.go b/util/util.go index e05736fc..27950da7 100644 --- a/util/util.go +++ b/util/util.go @@ -33,8 +33,8 @@ func FileExists(filename string) bool { return stat != nil } -// InStringList returns true if needle is contained in haystack -func InStringList(haystack []string, needle string) bool { +// Contains returns true if needle is contained in haystack +func Contains[T comparable](haystack []T, needle T) bool { for _, s := range haystack { if s == needle { return true @@ -43,8 +43,8 @@ func InStringList(haystack []string, needle string) bool { return false } -// InStringListAll returns true if all needles are contained in haystack -func InStringListAll(haystack []string, needles []string) bool { +// ContainsAll returns true if all needles are contained in haystack +func ContainsAll[T comparable](haystack []T, needles []T) bool { matches := 0 for _, s := range haystack { for _, needle := range needles { @@ -56,16 +56,6 @@ func InStringListAll(haystack []string, needles []string) bool { return matches == len(needles) } -// InIntList returns true if needle is contained in haystack -func InIntList(haystack []int, needle int) bool { - for _, s := range haystack { - if s == needle { - return true - } - } - return false -} - // SplitNoEmpty splits a string using strings.Split, but filters out empty strings func SplitNoEmpty(s string, sep string) []string { res := make([]string, 0) diff --git a/util/util_test.go b/util/util_test.go index 45ff3de6..83e1c716 100644 --- a/util/util_test.go +++ b/util/util_test.go @@ -52,20 +52,20 @@ func TestFileExists(t *testing.T) { func TestInStringList(t *testing.T) { s := []string{"one", "two"} - require.True(t, InStringList(s, "two")) - require.False(t, InStringList(s, "three")) + require.True(t, Contains(s, "two")) + require.False(t, Contains(s, "three")) } func TestInStringListAll(t *testing.T) { s := []string{"one", "two", "three", "four"} - require.True(t, InStringListAll(s, []string{"two", "four"})) - require.False(t, InStringListAll(s, []string{"three", "five"})) + require.True(t, ContainsAll(s, []string{"two", "four"})) + require.False(t, ContainsAll(s, []string{"three", "five"})) } func TestInIntList(t *testing.T) { s := []int{1, 2} - require.True(t, InIntList(s, 2)) - require.False(t, InIntList(s, 3)) + require.True(t, Contains(s, 2)) + require.False(t, Contains(s, 3)) } func TestSplitNoEmpty(t *testing.T) {