diff --git a/backend/go.mod b/backend/go.mod index 9661b2b3..ebdfbf7a 100644 --- a/backend/go.mod +++ b/backend/go.mod @@ -1,6 +1,6 @@ module github.com/umputun/remark42/backend -go 1.14 +go 1.15 require ( github.com/Depado/bfchroma v1.2.0 @@ -12,12 +12,12 @@ require ( github.com/go-chi/chi v4.1.1+incompatible github.com/go-chi/cors v1.1.1 github.com/go-chi/render v1.0.1 - github.com/go-pkgz/auth v1.14.0 + github.com/go-pkgz/auth v1.15.0 github.com/go-pkgz/jrpc v0.2.0 github.com/go-pkgz/lcw v0.8.1 github.com/go-pkgz/lgr v0.10.4 github.com/go-pkgz/repeater v1.1.3 - github.com/go-pkgz/rest v1.5.0 + github.com/go-pkgz/rest v1.7.0 github.com/go-pkgz/syncs v1.1.1 github.com/google/uuid v1.1.2 github.com/gorilla/feeds v1.1.1 diff --git a/backend/go.sum b/backend/go.sum index a1ccb402..3b63b472 100644 --- a/backend/go.sum +++ b/backend/go.sum @@ -64,8 +64,8 @@ github.com/go-chi/cors v1.1.1 h1:eHuqxsIw89iXcWnWUN8R72JMibABJTN/4IOYI5WERvw= github.com/go-chi/cors v1.1.1/go.mod h1:K2Yje0VW/SJzxiyMYu6iPQYa7hMjQX2i/F491VChg1I= github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8= github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns= -github.com/go-pkgz/auth v1.14.0 h1:fVNEcn9ry8v45sclcXo2wzrFaXtWX+Q5Th2qm7FRGX4= -github.com/go-pkgz/auth v1.14.0/go.mod h1:1GVd61pXZcuJ0ZnOUdCTY08V8SreO7MJtsvEd5/WEWA= +github.com/go-pkgz/auth v1.15.0 h1:77z+YdcxHkRcjJSQc1SBtqIrZbp3p8Zo72ZRR3QKsLk= +github.com/go-pkgz/auth v1.15.0/go.mod h1:1HTdNEBMSFRCXoJLLjgCRs8t/gt2TQUaqf6wgYRvsTo= github.com/go-pkgz/expirable-cache v0.0.3 h1:rTh6qNPp78z0bQE6HDhXBHUwqnV9i09Vm6dksJLXQDc= github.com/go-pkgz/expirable-cache v0.0.3/go.mod h1:+IauqN00R2FqNRLCLA+X5YljQJrwB179PfiAoMPlTlQ= github.com/go-pkgz/jrpc v0.2.0 h1:CLy/eZyekjraVrxZV18N2R1mYLMJ/nWrgdfyIOGPY/E= @@ -76,8 +76,10 @@ github.com/go-pkgz/lgr v0.10.4 h1:l7qyFjqEZgwRgaQQSEp6tve4A3OU80VrfzpvtEX8ngw= github.com/go-pkgz/lgr v0.10.4/go.mod h1:CD0s1z6EFpIUplV067gitF77tn25JItzwHNKAPqeCF0= github.com/go-pkgz/repeater v1.1.3 h1:q6+JQF14ESSy28Dd7F+wRelY4F+41HJ0LEy/szNnMiE= github.com/go-pkgz/repeater v1.1.3/go.mod h1:hVTavuO5x3Gxnu8zW7d6sQBfAneKV8X2FjU48kGfpKw= -github.com/go-pkgz/rest v1.5.0 h1:C8SxXcXza4GiUUAn/95iCkvoIrGbS30qpwK19iqlrWQ= github.com/go-pkgz/rest v1.5.0/go.mod h1:nQaM3RhSTUAmbBZWY4hfe4buyeC9VckvhoCktiQXJxI= +github.com/go-pkgz/rest v1.6.0/go.mod h1:FKpgK5FgSqREG323OIU/JpIc0xA7dqay9BmK7LZXTQE= +github.com/go-pkgz/rest v1.7.0 h1:5KHWmYPZaJfd6+Htx8bCJ2InVSHJ85MGh8kuO72SAjU= +github.com/go-pkgz/rest v1.7.0/go.mod h1:FKpgK5FgSqREG323OIU/JpIc0xA7dqay9BmK7LZXTQE= github.com/go-pkgz/syncs v1.1.1 h1:jWN+y6FS/Xe+8z4l3QMbSnODGyaxDHGojIS+wyKIjxg= github.com/go-pkgz/syncs v1.1.1/go.mod h1:bt9lxWRRJ9vOCMGc8Big8ttjYHLKP88ofj1y38UlaHE= github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1x4= diff --git a/backend/remark.rest b/backend/remark.rest index 1a34ee08..b47d4d99 100644 --- a/backend/remark.rest +++ b/backend/remark.rest @@ -147,3 +147,17 @@ X-JWT: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJyZW1hcmsiLCJleHAiOjE2NTc3 ### ping GET {{host}}/ping + + +### create comment with bad locator.url, dev token for secret=12345, not admin +POST {{host}}/api/v1/comment +Content-Type: application/json +X-JWT: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJyZW1hcmsiLCJleHAiOjE2MTY3OTQ2NTMsImp0aSI6ImNjOGVlNzNlNjM4MzQ1Mjc1MmZjN2M3ZmQ0MmE4MDIzZDY3ZWFiMDIiLCJpYXQiOjE2MTY3OTQzNTMsImlzcyI6InJlbWFyazQyIiwidXNlciI6eyJuYW1lIjoic29tZW9uZSIsImlkIjoiYW5vbnltb3VzX2NhMjlmMjkwOTU3NGE3Zjk3YjRkNGU4YmIwOTU1N2IxMDM1ODE4YjAiLCJwaWN0dXJlIjoiaHR0cHM6Ly9kZW1vLnJlbWFyazQyLmNvbS9hcGkvdjEvYXZhdGFyLzZlMTU5OGE5MWM4MWZlZjhmOGU5MzMwODg4ZWJiZjVlMzkzODVkYTkuaW1hZ2UiLCJhdHRycyI6eyJhZG1pbiI6ZmFsc2UsImJsb2NrZWQiOmZhbHNlfX19.TUEr1qN0j9WGx1jlOL-rc14qjuenH56yI-5_xF9FSGY + +{ + "text": "comment *blah* http://radio-t.com", + "locator": { + "url": "javascript:alert('XSS1')", + "site": "{{site}}" + } +} diff --git a/backend/vendor/github.com/go-pkgz/auth/.gitignore b/backend/vendor/github.com/go-pkgz/auth/.gitignore index 4ee8214d..2c09a372 100644 --- a/backend/vendor/github.com/go-pkgz/auth/.gitignore +++ b/backend/vendor/github.com/go-pkgz/auth/.gitignore @@ -11,4 +11,5 @@ # Output of the go coverage tool, specifically when used with LiteIDE *.out .vscode -*.cov \ No newline at end of file +*.cov +Dockerfile \ No newline at end of file diff --git a/backend/vendor/github.com/go-pkgz/auth/README.md b/backend/vendor/github.com/go-pkgz/auth/README.md index 3369a2a3..5d875a14 100644 --- a/backend/vendor/github.com/go-pkgz/auth/README.md +++ b/backend/vendor/github.com/go-pkgz/auth/README.md @@ -366,10 +366,10 @@ In order to allow `aud` support the list of allowed audiences should be passed i ### Dev provider -Working with oauth2 providers can be a pain, especially during development phase. A special, development-only provider `dev` can make it less painful. This one can be registered directly, i.e. `service.AddProvider("dev", "", "")` and should be activated like this: +Working with oauth2 providers can be a pain, especially during development phase. A special, development-only provider `dev` can make it less painful. This one can be registered directly, i.e. `service.AddProvider("dev", "", "")` or `service.AddDevProvider(port)` and should be activated like this: ```go - // runs dev oauth2 server on :8084 + // runs dev oauth2 server on :8084 by default go func() { devAuthServer, err := service.DevAuth() if err != nil { diff --git a/backend/vendor/github.com/go-pkgz/auth/auth.go b/backend/vendor/github.com/go-pkgz/auth/auth.go index 1a32760b..83cde568 100644 --- a/backend/vendor/github.com/go-pkgz/auth/auth.go +++ b/backend/vendor/github.com/go-pkgz/auth/auth.go @@ -159,7 +159,7 @@ func (s *Service) Handlers() (authHandler, avatarHandler http.Handler) { for _, p := range s.providers { list = append(list, p.Name()) } - rest.RenderJSON(w, r, list) + rest.RenderJSON(w, list) return } @@ -167,7 +167,7 @@ func (s *Service) Handlers() (authHandler, avatarHandler http.Handler) { if elems[len(elems)-1] == "logout" { if len(s.providers) == 0 { w.WriteHeader(http.StatusBadRequest) - rest.RenderJSON(w, r, rest.JSON{"error": "provides not defined"}) + rest.RenderJSON(w, rest.JSON{"error": "provides not defined"}) return } s.providers[0].Handler(w, r) @@ -179,10 +179,10 @@ func (s *Service) Handlers() (authHandler, avatarHandler http.Handler) { claims, _, err := s.jwtService.Get(r) if err != nil { w.WriteHeader(http.StatusUnauthorized) - rest.RenderJSON(w, r, rest.JSON{"error": err.Error()}) + rest.RenderJSON(w, rest.JSON{"error": err.Error()}) return } - rest.RenderJSON(w, r, claims.User) + rest.RenderJSON(w, claims.User) return } @@ -191,7 +191,7 @@ func (s *Service) Handlers() (authHandler, avatarHandler http.Handler) { p, err := s.Provider(provName) if err != nil { w.WriteHeader(http.StatusBadRequest) - rest.RenderJSON(w, r, rest.JSON{"error": fmt.Sprintf("provider %s not supported", provName)}) + rest.RenderJSON(w, rest.JSON{"error": fmt.Sprintf("provider %s not supported", provName)}) return } p.Handler(w, r) @@ -242,6 +242,19 @@ func (s *Service) AddProvider(name, cid, csecret string) { s.authMiddleware.Providers = s.providers } +// AddDevProvider with a custom port +func (s *Service) AddDevProvider(port int) { + p := provider.Params{ + URL: s.opts.URL, + JwtService: s.jwtService, + Issuer: s.issuer, + AvatarSaver: s.avatarProxy, + L: s.logger, + Port: port, + } + s.providers = append(s.providers, provider.NewService(provider.NewDev(p))) +} + // AddCustomProvider adds custom provider (e.g. https://gopkg.in/oauth2.v3) func (s *Service) AddCustomProvider(name string, client Client, copts provider.CustomHandlerOpt) { p := provider.Params{ diff --git a/backend/vendor/github.com/go-pkgz/auth/go.mod b/backend/vendor/github.com/go-pkgz/auth/go.mod index 04544955..5c59a81c 100644 --- a/backend/vendor/github.com/go-pkgz/auth/go.mod +++ b/backend/vendor/github.com/go-pkgz/auth/go.mod @@ -1,12 +1,12 @@ module github.com/go-pkgz/auth -go 1.14 +go 1.15 require ( github.com/dghubble/oauth1 v0.6.0 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/go-pkgz/repeater v1.1.3 - github.com/go-pkgz/rest v1.5.0 + github.com/go-pkgz/rest v1.6.0 github.com/microcosm-cc/bluemonday v1.0.2 github.com/nullrocks/identicon v0.0.0-20180626043057-7875f45b0022 github.com/pkg/errors v0.9.1 diff --git a/backend/vendor/github.com/go-pkgz/auth/go.sum b/backend/vendor/github.com/go-pkgz/auth/go.sum index 8be83949..8db3c245 100644 --- a/backend/vendor/github.com/go-pkgz/auth/go.sum +++ b/backend/vendor/github.com/go-pkgz/auth/go.sum @@ -22,8 +22,8 @@ github.com/gavv/httpexpect v2.0.0+incompatible h1:1X9kcRshkSKEjNJJxX9Y9mQ5BRfbxU github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/go-pkgz/repeater v1.1.3 h1:q6+JQF14ESSy28Dd7F+wRelY4F+41HJ0LEy/szNnMiE= github.com/go-pkgz/repeater v1.1.3/go.mod h1:hVTavuO5x3Gxnu8zW7d6sQBfAneKV8X2FjU48kGfpKw= -github.com/go-pkgz/rest v1.5.0 h1:C8SxXcXza4GiUUAn/95iCkvoIrGbS30qpwK19iqlrWQ= -github.com/go-pkgz/rest v1.5.0/go.mod h1:nQaM3RhSTUAmbBZWY4hfe4buyeC9VckvhoCktiQXJxI= +github.com/go-pkgz/rest v1.6.0 h1:mowpdpVsgofMJsfoqeUFUrF5efXPHpXJkQDoy13OKcA= +github.com/go-pkgz/rest v1.6.0/go.mod h1:FKpgK5FgSqREG323OIU/JpIc0xA7dqay9BmK7LZXTQE= github.com/go-session/session v3.1.2+incompatible/go.mod h1:8B3iivBQjrz/JtC68Np2T1yBBLxTan3mn/3OM0CyRt0= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= @@ -110,9 +110,7 @@ github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= -github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -133,10 +131,8 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9 github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= @@ -197,20 +193,16 @@ golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190412183630-56d357773e84/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -248,9 +240,7 @@ gopkg.in/oauth2.v3 v3.12.0 h1:yOffAPoolH/i2JxwmC+pgtnY3362iPahsDpLXfDFvNg= gopkg.in/oauth2.v3 v3.12.0/go.mod h1:XEYgKqWX095YiPT+Aw5y3tCn+7/FMnlTFKrupgSiJ3I= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/backend/vendor/github.com/go-pkgz/auth/provider/dev_provider.go b/backend/vendor/github.com/go-pkgz/auth/provider/dev_provider.go index 02c932a4..e76ec33b 100644 --- a/backend/vendor/github.com/go-pkgz/auth/provider/dev_provider.go +++ b/backend/vendor/github.com/go-pkgz/auth/provider/dev_provider.go @@ -16,7 +16,7 @@ import ( "github.com/go-pkgz/auth/token" ) -const devAuthPort = 8084 +const defDevAuthPort = 8084 // DevAuthServer is a fake oauth server for development // it provides stand-alone server running on its own port and pretending to be the real oauth2. It also provides @@ -35,8 +35,11 @@ type DevAuthServer struct { // Run oauth2 dev server on port devAuthPort func (d *DevAuthServer) Run(ctx context.Context) { //nolint (gocyclo) + if d.Provider.Port == 0 { + d.Provider.Port = defDevAuthPort + } d.username = "dev_user" - d.Logf("[INFO] run local oauth2 dev server on %d, redirect url=%s", devAuthPort, d.Provider.conf.RedirectURL) + d.Logf("[INFO] run local oauth2 dev server on %d, redirect url=%s", d.Provider.Port, d.Provider.conf.RedirectURL) d.lock.Lock() var err error @@ -47,7 +50,7 @@ func (d *DevAuthServer) Run(ctx context.Context) { //nolint (gocyclo) } d.httpServer = &http.Server{ - Addr: fmt.Sprintf(":%d", devAuthPort), + Addr: fmt.Sprintf(":%d", d.Provider.Port), Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { d.Logf("[DEBUG] dev oauth request %s %s %+v", r.Method, r.URL, r.Header) switch { @@ -91,7 +94,7 @@ func (d *DevAuthServer) Run(ctx context.Context) { //nolint (gocyclo) } case strings.HasPrefix(r.URL.Path, "/user"): - ava := fmt.Sprintf("http://127.0.0.1:%d/avatar?user=%s", devAuthPort, d.username) + ava := fmt.Sprintf("http://127.0.0.1:%d/avatar?user=%s", d.Provider.Port, d.username) res := fmt.Sprintf(`{ "id": "%s", "name":"%s", @@ -150,14 +153,17 @@ func (d *DevAuthServer) Shutdown() { // NewDev makes dev oauth2 provider for admin user func NewDev(p Params) Oauth2Handler { + if p.Port == 0 { + p.Port = defDevAuthPort + } oh := initOauth2Handler(p, Oauth2Handler{ name: "dev", endpoint: oauth2.Endpoint{ - AuthURL: fmt.Sprintf("http://127.0.0.1:%d/login/oauth/authorize", devAuthPort), - TokenURL: fmt.Sprintf("http://127.0.0.1:%d/login/oauth/access_token", devAuthPort), + AuthURL: fmt.Sprintf("http://127.0.0.1:%d/login/oauth/authorize", p.Port), + TokenURL: fmt.Sprintf("http://127.0.0.1:%d/login/oauth/access_token", p.Port), }, scopes: []string{"user:email"}, - infoURL: fmt.Sprintf("http://127.0.0.1:%d/user", devAuthPort), + infoURL: fmt.Sprintf("http://127.0.0.1:%d/user", p.Port), mapUser: func(data UserData, _ []byte) token.User { userInfo := token.User{ ID: data.Value("id"), diff --git a/backend/vendor/github.com/go-pkgz/auth/provider/direct.go b/backend/vendor/github.com/go-pkgz/auth/provider/direct.go index 8cd042e0..70e22ea2 100644 --- a/backend/vendor/github.com/go-pkgz/auth/provider/direct.go +++ b/backend/vendor/github.com/go-pkgz/auth/provider/direct.go @@ -121,7 +121,7 @@ func (p DirectHandler) LoginHandler(w http.ResponseWriter, r *http.Request) { rest.SendErrorJSON(w, r, p.L, http.StatusInternalServerError, err, "failed to set token") return } - rest.RenderJSON(w, r, claims.User) + rest.RenderJSON(w, claims.User) } // getCredentials extracts user and password from request diff --git a/backend/vendor/github.com/go-pkgz/auth/provider/oauth1.go b/backend/vendor/github.com/go-pkgz/auth/provider/oauth1.go index 6d0657f1..5d227d00 100644 --- a/backend/vendor/github.com/go-pkgz/auth/provider/oauth1.go +++ b/backend/vendor/github.com/go-pkgz/auth/provider/oauth1.go @@ -160,7 +160,7 @@ func (h Oauth1Handler) AuthHandler(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, oauthClaims.Handshake.From, http.StatusTemporaryRedirect) return } - rest.RenderJSON(w, r, &u) + rest.RenderJSON(w, &u) } // LogoutHandler - GET /logout diff --git a/backend/vendor/github.com/go-pkgz/auth/provider/oauth2.go b/backend/vendor/github.com/go-pkgz/auth/provider/oauth2.go index e65586b0..4d404849 100644 --- a/backend/vendor/github.com/go-pkgz/auth/provider/oauth2.go +++ b/backend/vendor/github.com/go-pkgz/auth/provider/oauth2.go @@ -39,6 +39,8 @@ type Params struct { Csecret string Issuer string AvatarSaver AvatarSaver + + Port int // relevant for providers supporting port customization, for example dev oauth2 } // UserData is type for user information returned from oauth2 providers /info API method @@ -211,7 +213,7 @@ func (p Oauth2Handler) AuthHandler(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, oauthClaims.Handshake.From, http.StatusTemporaryRedirect) return } - rest.RenderJSON(w, r, &u) + rest.RenderJSON(w, &u) } // LogoutHandler - GET /logout diff --git a/backend/vendor/github.com/go-pkgz/auth/provider/telegram.go b/backend/vendor/github.com/go-pkgz/auth/provider/telegram.go index 3d541eba..e689e4e2 100644 --- a/backend/vendor/github.com/go-pkgz/auth/provider/telegram.go +++ b/backend/vendor/github.com/go-pkgz/auth/provider/telegram.go @@ -199,7 +199,7 @@ func (th *TelegramHandler) LoginHandler(w http.ResponseWriter, r *http.Request) } th.requests.Unlock() - rest.RenderJSON(w, r, struct { + rest.RenderJSON(w, struct { Token string `json:"token"` Bot string `json:"bot"` }{token, th.username}) @@ -246,7 +246,7 @@ func (th *TelegramHandler) LoginHandler(w http.ResponseWriter, r *http.Request) return } - rest.RenderJSON(w, r, claims.User) + rest.RenderJSON(w, claims.User) // Delete request th.requests.Lock() diff --git a/backend/vendor/github.com/go-pkgz/auth/provider/verify.go b/backend/vendor/github.com/go-pkgz/auth/provider/verify.go index 4e14e505..9adde3a3 100644 --- a/backend/vendor/github.com/go-pkgz/auth/provider/verify.go +++ b/backend/vendor/github.com/go-pkgz/auth/provider/verify.go @@ -127,7 +127,7 @@ func (e VerifyHandler) LoginHandler(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, confClaims.Handshake.From, http.StatusTemporaryRedirect) return } - rest.RenderJSON(w, r, claims.User) + rest.RenderJSON(w, claims.User) } // GET /login?site=site&user=name&address=someone@example.com @@ -189,7 +189,7 @@ func (e VerifyHandler) sendConfirmation(w http.ResponseWriter, r *http.Request) return } - rest.RenderJSON(w, r, rest.JSON{"user": user, "address": address}) + rest.RenderJSON(w, rest.JSON{"user": user, "address": address}) } // AuthHandler doesn't do anything for direct login as it has no callbacks diff --git a/backend/vendor/github.com/go-pkgz/rest/.golangci.yml b/backend/vendor/github.com/go-pkgz/rest/.golangci.yml index b64de312..831557ac 100644 --- a/backend/vendor/github.com/go-pkgz/rest/.golangci.yml +++ b/backend/vendor/github.com/go-pkgz/rest/.golangci.yml @@ -2,7 +2,7 @@ linters-settings: govet: check-shadowing: true golint: - min-confidence: 0.8 + min-confidence: 0 gocyclo: min-complexity: 15 maligned: @@ -23,11 +23,8 @@ linters-settings: - experimental disabled-checks: - wrapperFunc - - hugeParam - - rangeValCopy linters: - disable-all: true enable: - megacheck - golint @@ -37,6 +34,7 @@ linters: - structcheck - gas - gocyclo + - dupl - misspell - unparam - varcheck @@ -46,26 +44,26 @@ linters: - varcheck - stylecheck - gochecknoinits - - golint + - scopelint + - gocritic - nakedret - gosimple - prealloc - fast: false - + disable-all: true run: - # modules-download-mode: vendor + output: + format: tab skip-dirs: - vendor - concurrency: 4 issues: exclude-rules: - - text: "weak cryptographic primitive" + - text: "should have a package comment, unless it's in another file for this package" linters: - - gosec + - golint + - path: _test\.go + linters: + - dupl exclude-use-default: false - -service: - golangci-lint-version: 1.24.x diff --git a/backend/vendor/github.com/go-pkgz/rest/README.md b/backend/vendor/github.com/go-pkgz/rest/README.md index dbf7041b..243df598 100644 --- a/backend/vendor/github.com/go-pkgz/rest/README.md +++ b/backend/vendor/github.com/go-pkgz/rest/README.md @@ -17,9 +17,9 @@ Adds info to every response header: ### Ping-Pong middleware -Responds with `pong` on `GET /ping`. Also responds to anything with `/ping` suffix, like `/v2/ping` +Responds with `pong` on `GET /ping`. Also, responds to anything with `/ping` suffix, like `/v2/ping`. -example for both: +Example for both: ``` > http GET https://remark42.radio-t.com/ping @@ -58,7 +58,7 @@ example: `019/03/05 17:26:12.976 [INFO] GET - /api/v1/find?site=remark - 8e228e9 ### Recoverer middleware Recoverer is a middleware that recovers from panics, logs the panic (and a backtrace), -and returns a HTTP 500 (Internal Server Error) status if possible. +and returns an HTTP 500 (Internal Server Error) status if possible. ### OnlyFrom middleware @@ -67,7 +67,7 @@ Such IPs can be defined as complete ip (like 192.168.1.12), prefix (129.168.) or ### Metrics middleware -Metrics middleware responds to GET /metrics with list of [expvar](https://golang.org/pkg/expvar/). Optionally allows to restrict list of source ips. +Metrics middleware responds to GET /metrics with list of [expvar](https://golang.org/pkg/expvar/). Optionally allows restricting list of source ips. ### BlackWords middleware @@ -82,6 +82,11 @@ SizeLimit middleware checks if body size is above the limit and returns `StatusR It looks for `X-Request-ID` header and makes it as a random id (if not found), then populates it to the result's header and to the request's context. + +### Deprecation + +Adds rhe HTTP Deprecation response header, see [draft-dalal-deprecation-header-00](https://tools.ietf.org/id/draft-dalal-deprecation-header-00.html +) ## Helpers @@ -89,5 +94,5 @@ It looks for `X-Request-ID` header and makes it as a random id - `rest.RenderJSON` - renders json response from `interface{}` - `rest.RenderJSONFromBytes` - renders json response from `[]byte` - `rest.RenderJSONWithHTML` - renders json response with html tags and forced `charset=utf-8` -- `rest.SendErrorJSON` - makes `{error: blah, details: blah}` json body and responds with given error code. Also adds context to logged message +- `rest.SendErrorJSON` - makes `{error: blah, details: blah}` json body and responds with given error code. Also, adds context to the logged message - `rest.NewErrorLogger(l logger.Backend)` creates a struct providing shorter form of logger call diff --git a/backend/vendor/github.com/go-pkgz/rest/blackwords.go b/backend/vendor/github.com/go-pkgz/rest/blackwords.go index 62afe8e3..08f1c647 100644 --- a/backend/vendor/github.com/go-pkgz/rest/blackwords.go +++ b/backend/vendor/github.com/go-pkgz/rest/blackwords.go @@ -21,7 +21,7 @@ func BlackWords(words ...string) func(http.Handler) http.Handler { for _, word := range words { if strings.Contains(body, strings.ToLower(word)) { w.WriteHeader(http.StatusForbidden) - RenderJSON(w, r, JSON{"error": "one of blacklisted words detected"}) + RenderJSON(w, JSON{"error": "one of blacklisted words detected"}) return } } diff --git a/backend/vendor/github.com/go-pkgz/rest/go.mod b/backend/vendor/github.com/go-pkgz/rest/go.mod index a3def902..aab6b51d 100644 --- a/backend/vendor/github.com/go-pkgz/rest/go.mod +++ b/backend/vendor/github.com/go-pkgz/rest/go.mod @@ -1,9 +1,8 @@ module github.com/go-pkgz/rest -go 1.14 +go 1.15 require ( - github.com/davecgh/go-spew v1.1.1 // indirect github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.3.0 + github.com/stretchr/testify v1.6.1 ) diff --git a/backend/vendor/github.com/go-pkgz/rest/go.sum b/backend/vendor/github.com/go-pkgz/rest/go.sum index 302442b0..7034f5b8 100644 --- a/backend/vendor/github.com/go-pkgz/rest/go.sum +++ b/backend/vendor/github.com/go-pkgz/rest/go.sum @@ -1,10 +1,14 @@ +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/backend/vendor/github.com/go-pkgz/rest/httperrors.go b/backend/vendor/github.com/go-pkgz/rest/httperrors.go index af3b7c05..45bed815 100644 --- a/backend/vendor/github.com/go-pkgz/rest/httperrors.go +++ b/backend/vendor/github.com/go-pkgz/rest/httperrors.go @@ -31,7 +31,7 @@ func (e *ErrorLogger) Log(w http.ResponseWriter, r *http.Request, httpCode int, e.l.Logf("%s", errDetailsMsg(r, httpCode, err, m)) } w.WriteHeader(httpCode) - RenderJSON(w, r, JSON{"error": m}) + RenderJSON(w, JSON{"error": m}) } // SendErrorJSON sends {error: msg} with error code and logging error and caller @@ -40,7 +40,7 @@ func SendErrorJSON(w http.ResponseWriter, r *http.Request, l logger.Backend, cod l.Logf("%s", errDetailsMsg(r, code, err, msg)) } w.WriteHeader(code) - RenderJSON(w, r, JSON{"error": msg}) + RenderJSON(w, JSON{"error": msg}) } func errDetailsMsg(r *http.Request, code int, err error, msg string) string { diff --git a/backend/vendor/github.com/go-pkgz/rest/logger/logger.go b/backend/vendor/github.com/go-pkgz/rest/logger/logger.go index 7aca3a99..0865dc13 100644 --- a/backend/vendor/github.com/go-pkgz/rest/logger/logger.go +++ b/backend/vendor/github.com/go-pkgz/rest/logger/logger.go @@ -59,7 +59,6 @@ func New(options ...Option) *Middleware { } // Handler middleware prints http log -//nolint gosec func (l *Middleware) Handler(next http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { @@ -91,32 +90,32 @@ func (l *Middleware) Handler(next http.Handler) http.Handler { var bld strings.Builder if l.prefix != "" { - bld.WriteString(l.prefix) - bld.WriteString(" ") + _, _ = bld.WriteString(l.prefix) + _, _ = bld.WriteString(" ") } - bld.WriteString(fmt.Sprintf("%s - %s - %s - %d (%d) - %v", r.Method, rawurl, remoteIP, ww.status, ww.size, t2.Sub(t1))) + _, _ = bld.WriteString(fmt.Sprintf("%s - %s - %s - %d (%d) - %v", r.Method, rawurl, remoteIP, ww.status, ww.size, t2.Sub(t1))) if user != "" { - bld.WriteString(" - ") - bld.WriteString(user) + _, _ = bld.WriteString(" - ") + _, _ = bld.WriteString(user) } if l.subjFn != nil { if subj, err := l.subjFn(r); err == nil { - bld.WriteString(" - ") - bld.WriteString(subj) + _, _ = bld.WriteString(" - ") + _, _ = bld.WriteString(subj) } } if traceID := r.Header.Get("X-Request-ID"); traceID != "" { - bld.WriteString(" - ") - bld.WriteString(traceID) + _, _ = bld.WriteString(" - ") + _, _ = bld.WriteString(traceID) } if body != "" { - bld.WriteString(" - ") - bld.WriteString(body) + _, _ = bld.WriteString(" - ") + _, _ = bld.WriteString(body) } l.log.Logf("%s", bld.String()) @@ -168,7 +167,8 @@ func peek(r io.Reader, n int64) (reader io.Reader, s string, hasMore bool, err e buf := new(bytes.Buffer) _, err = io.CopyN(buf, r, n+1) if err == io.EOF { - return buf, buf.String(), false, nil + str := buf.String() + return buf, str, false, nil } if err != nil { return r, "", false, err @@ -273,5 +273,5 @@ func (c *customResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { if hj, ok := c.ResponseWriter.(http.Hijacker); ok { return hj.Hijack() } - return nil, nil, fmt.Errorf("ResponseWriter does not implement the Hijacker interface") + return nil, nil, fmt.Errorf("ResponseWriter does not implement the Hijacker interface") //nolint:golint //capital letter is OK here } diff --git a/backend/vendor/github.com/go-pkgz/rest/metrics.go b/backend/vendor/github.com/go-pkgz/rest/metrics.go index 2a57a939..13e80808 100644 --- a/backend/vendor/github.com/go-pkgz/rest/metrics.go +++ b/backend/vendor/github.com/go-pkgz/rest/metrics.go @@ -16,7 +16,7 @@ func Metrics(onlyIps ...string) func(http.Handler) http.Handler { if r.Method == "GET" && strings.HasSuffix(strings.ToLower(r.URL.Path), "/metrics") { if matched, ip := matchSourceIP(r, onlyIps); !matched { w.WriteHeader(http.StatusForbidden) - RenderJSON(w, r, JSON{"error": fmt.Sprintf("ip %s rejected", ip)}) + RenderJSON(w, JSON{"error": fmt.Sprintf("ip %s rejected", ip)}) return } expvar.Handler().ServeHTTP(w, r) diff --git a/backend/vendor/github.com/go-pkgz/rest/middleware.go b/backend/vendor/github.com/go-pkgz/rest/middleware.go index b32e240e..0e695cfd 100644 --- a/backend/vendor/github.com/go-pkgz/rest/middleware.go +++ b/backend/vendor/github.com/go-pkgz/rest/middleware.go @@ -10,7 +10,7 @@ import ( ) // AppInfo adds custom app-info to the response header -func AppInfo(app string, author string, version string) func(http.Handler) http.Handler { +func AppInfo(app, author, version string) func(http.Handler) http.Handler { f := func(h http.Handler) http.Handler { fn := func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Author", author) @@ -33,7 +33,7 @@ func Ping(next http.Handler) http.Handler { if r.Method == "GET" && strings.HasSuffix(strings.ToLower(r.URL.Path), "/ping") { w.Header().Set("Content-Type", "text/plain") w.WriteHeader(http.StatusOK) - w.Write([]byte("pong")) //nolint + _, _ = w.Write([]byte("pong")) return } next.ServeHTTP(w, r) diff --git a/backend/vendor/github.com/go-pkgz/rest/onlyfrom.go b/backend/vendor/github.com/go-pkgz/rest/onlyfrom.go index 1ca52f0b..eb24befb 100644 --- a/backend/vendor/github.com/go-pkgz/rest/onlyfrom.go +++ b/backend/vendor/github.com/go-pkgz/rest/onlyfrom.go @@ -22,14 +22,14 @@ func OnlyFrom(onlyIps ...string) func(http.Handler) http.Handler { } w.WriteHeader(http.StatusForbidden) - RenderJSON(w, r, JSON{"error": fmt.Sprintf("ip %s rejected", ip)}) + RenderJSON(w, JSON{"error": fmt.Sprintf("ip %s rejected", ip)}) } return http.HandlerFunc(fn) } } // matchSourceIP returns true if request's ip matches any of ips -func matchSourceIP(r *http.Request, ips []string) (bool, string) { +func matchSourceIP(r *http.Request, ips []string) (result bool, match string) { // try X-Real-IP first then fail back to X-Forwarded-For and finally to RemoteAddr ip := r.Header.Get("X-Real-IP") diff --git a/backend/vendor/github.com/go-pkgz/rest/rest.go b/backend/vendor/github.com/go-pkgz/rest/rest.go index 964f54e9..4a0f7858 100644 --- a/backend/vendor/github.com/go-pkgz/rest/rest.go +++ b/backend/vendor/github.com/go-pkgz/rest/rest.go @@ -13,7 +13,7 @@ import ( type JSON map[string]interface{} // RenderJSON sends data as json -func RenderJSON(w http.ResponseWriter, r *http.Request, data interface{}) { +func RenderJSON(w http.ResponseWriter, data interface{}) { buf := &bytes.Buffer{} enc := json.NewEncoder(buf) enc.SetEscapeHTML(true) @@ -22,7 +22,7 @@ func RenderJSON(w http.ResponseWriter, r *http.Request, data interface{}) { return } w.Header().Set("Content-Type", "application/json; charset=utf-8") - w.Write(buf.Bytes()) // nolint: errcheck, gosec + _, _ = w.Write(buf.Bytes()) } // RenderJSONFromBytes sends binary data as json diff --git a/backend/vendor/github.com/go-pkgz/rest/trace.go b/backend/vendor/github.com/go-pkgz/rest/trace.go index 420ff941..77d14474 100644 --- a/backend/vendor/github.com/go-pkgz/rest/trace.go +++ b/backend/vendor/github.com/go-pkgz/rest/trace.go @@ -3,7 +3,7 @@ package rest import ( "context" "crypto/rand" - "crypto/sha1" + "crypto/sha1" //nolint:gosec //not used for cryptography "encoding/hex" "fmt" "net/http" @@ -43,6 +43,6 @@ func randToken() string { if _, err := rand.Read(b); err != nil { return fmt.Sprintf("%x", time.Now().Nanosecond()) } - sum := sha1.Sum(b) + sum := sha1.Sum(b) //nolint:gosec //not used for cryptography return hex.EncodeToString(sum[:]) } diff --git a/backend/vendor/modules.txt b/backend/vendor/modules.txt index e8ddbbf9..1150f892 100644 --- a/backend/vendor/modules.txt +++ b/backend/vendor/modules.txt @@ -94,7 +94,7 @@ github.com/go-chi/cors # github.com/go-chi/render v1.0.1 ## explicit github.com/go-chi/render -# github.com/go-pkgz/auth v1.14.0 +# github.com/go-pkgz/auth v1.15.0 ## explicit github.com/go-pkgz/auth github.com/go-pkgz/auth/avatar @@ -120,7 +120,7 @@ github.com/go-pkgz/lgr ## explicit github.com/go-pkgz/repeater github.com/go-pkgz/repeater/strategy -# github.com/go-pkgz/rest v1.5.0 +# github.com/go-pkgz/rest v1.7.0 ## explicit github.com/go-pkgz/rest github.com/go-pkgz/rest/logger