mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-10 19:11:08 +00:00
Add method to check organization membership (#1037)
* Add remote method to check organization membership * Use named return parameters in interface * Add membership check service * Update Gitea SDK
This commit is contained in:
parent
1e8d4cc455
commit
19dfc331f4
19 changed files with 342 additions and 14 deletions
|
@ -266,6 +266,7 @@ func setupEvilGlobals(c *cli.Context, v store.Store, r remote.Remote) {
|
||||||
server.Config.Services.Registries = setupRegistryService(c, v)
|
server.Config.Services.Registries = setupRegistryService(c, v)
|
||||||
server.Config.Services.Secrets = setupSecretService(c, v)
|
server.Config.Services.Secrets = setupSecretService(c, v)
|
||||||
server.Config.Services.Environ = setupEnvironService(c, v)
|
server.Config.Services.Environ = setupEnvironService(c, v)
|
||||||
|
server.Config.Services.Membership = setupMembershipService(c, r)
|
||||||
|
|
||||||
server.Config.Services.SignaturePrivateKey, server.Config.Services.SignaturePublicKey = setupSignatureKeys(v)
|
server.Config.Services.SignaturePrivateKey, server.Config.Services.SignaturePublicKey = setupSignatureKeys(v)
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ import (
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
|
|
||||||
"github.com/woodpecker-ci/woodpecker/server"
|
"github.com/woodpecker-ci/woodpecker/server"
|
||||||
|
"github.com/woodpecker-ci/woodpecker/server/cache"
|
||||||
"github.com/woodpecker-ci/woodpecker/server/model"
|
"github.com/woodpecker-ci/woodpecker/server/model"
|
||||||
"github.com/woodpecker-ci/woodpecker/server/plugins/environments"
|
"github.com/woodpecker-ci/woodpecker/server/plugins/environments"
|
||||||
"github.com/woodpecker-ci/woodpecker/server/plugins/registry"
|
"github.com/woodpecker-ci/woodpecker/server/plugins/registry"
|
||||||
|
@ -180,6 +181,10 @@ func setupEnvironService(c *cli.Context, s store.Store) model.EnvironService {
|
||||||
return environments.Parse(c.StringSlice("environment"))
|
return environments.Parse(c.StringSlice("environment"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupMembershipService(_ *cli.Context, r remote.Remote) cache.MembershipService {
|
||||||
|
return cache.NewMembershipService(r)
|
||||||
|
}
|
||||||
|
|
||||||
// setupRemote helper function to setup the remote from the CLI arguments.
|
// setupRemote helper function to setup the remote from the CLI arguments.
|
||||||
func setupRemote(c *cli.Context) (remote.Remote, error) {
|
func setupRemote(c *cli.Context) (remote.Remote, error) {
|
||||||
switch {
|
switch {
|
||||||
|
|
11
go.mod
11
go.mod
|
@ -3,7 +3,7 @@ module github.com/woodpecker-ci/woodpecker
|
||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
code.gitea.io/sdk/gitea v0.15.1-0.20220501190934-319a978c6c71
|
code.gitea.io/sdk/gitea v0.15.1-0.20220720025709-de34275bb64e
|
||||||
codeberg.org/6543/go-yaml2json v0.1.0
|
codeberg.org/6543/go-yaml2json v0.1.0
|
||||||
github.com/bmatcuk/doublestar/v4 v4.0.2
|
github.com/bmatcuk/doublestar/v4 v4.0.2
|
||||||
github.com/docker/cli v20.10.14+incompatible
|
github.com/docker/cli v20.10.14+incompatible
|
||||||
|
@ -20,6 +20,7 @@ require (
|
||||||
github.com/google/go-github/v39 v39.2.0
|
github.com/google/go-github/v39 v39.2.0
|
||||||
github.com/gorilla/securecookie v1.1.1
|
github.com/gorilla/securecookie v1.1.1
|
||||||
github.com/joho/godotenv v1.4.0
|
github.com/joho/godotenv v1.4.0
|
||||||
|
github.com/lafriks/ttlcache/v3 v3.1.0
|
||||||
github.com/lib/pq v1.10.5
|
github.com/lib/pq v1.10.5
|
||||||
github.com/mattn/go-sqlite3 v1.14.12
|
github.com/mattn/go-sqlite3 v1.14.12
|
||||||
github.com/melbahja/goph v1.3.0
|
github.com/melbahja/goph v1.3.0
|
||||||
|
@ -34,7 +35,7 @@ require (
|
||||||
github.com/urfave/cli/v2 v2.5.1
|
github.com/urfave/cli/v2 v2.5.1
|
||||||
github.com/xanzy/go-gitlab v0.64.0
|
github.com/xanzy/go-gitlab v0.64.0
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0
|
github.com/xeipuuv/gojsonschema v1.2.0
|
||||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
|
||||||
golang.org/x/net v0.0.0-20220615171555-694bf12d69de
|
golang.org/x/net v0.0.0-20220615171555-694bf12d69de
|
||||||
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5
|
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5
|
||||||
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f
|
golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f
|
||||||
|
@ -53,11 +54,13 @@ require (
|
||||||
github.com/containerd/containerd v1.6.6 // indirect
|
github.com/containerd/containerd v1.6.6 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/davidmz/go-pageant v1.0.2 // indirect
|
||||||
github.com/docker/docker-credential-helpers v0.6.4 // indirect
|
github.com/docker/docker-credential-helpers v0.6.4 // indirect
|
||||||
github.com/docker/go-connections v0.4.0 // indirect
|
github.com/docker/go-connections v0.4.0 // indirect
|
||||||
github.com/fatih/color v1.13.0 // indirect
|
github.com/fatih/color v1.13.0 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
|
github.com/go-fed/httpsig v1.1.0 // indirect
|
||||||
github.com/go-playground/locales v0.14.0 // indirect
|
github.com/go-playground/locales v0.14.0 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.0 // indirect
|
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.10.1 // indirect
|
github.com/go-playground/validator/v10 v10.10.1 // indirect
|
||||||
|
@ -71,7 +74,7 @@ require (
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||||
github.com/hashicorp/go-hclog v1.0.0 // indirect
|
github.com/hashicorp/go-hclog v1.0.0 // indirect
|
||||||
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
|
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
|
||||||
github.com/hashicorp/go-version v1.4.0 // indirect
|
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/kr/fs v0.1.0 // indirect
|
github.com/kr/fs v0.1.0 // indirect
|
||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
github.com/leodido/go-urn v1.2.1 // indirect
|
||||||
|
@ -98,7 +101,7 @@ require (
|
||||||
github.com/ugorji/go/codec v1.2.7 // indirect
|
github.com/ugorji/go/codec v1.2.7 // indirect
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
|
||||||
golang.org/x/text v0.3.7 // indirect
|
golang.org/x/text v0.3.7 // indirect
|
||||||
golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect
|
golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect
|
||||||
golang.org/x/tools v0.1.10 // indirect
|
golang.org/x/tools v0.1.10 // indirect
|
||||||
|
|
27
go.sum
27
go.sum
|
@ -30,8 +30,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
|
||||||
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
|
||||||
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
|
||||||
code.gitea.io/sdk/gitea v0.15.1-0.20220501190934-319a978c6c71 h1:+ZqwhfAftVOAd7AcLpfh4LBdTeJIyt60vGU39zhQPyA=
|
code.gitea.io/sdk/gitea v0.15.1-0.20220720025709-de34275bb64e h1:xayGBU2DwsrA5ZyqKNpXB91w3BfnkNcLDWZ7Ynn/w+g=
|
||||||
code.gitea.io/sdk/gitea v0.15.1-0.20220501190934-319a978c6c71/go.mod h1:MuMGvUxT8BmFHa0gHhHsrnz91QfmziXuFffm9AuhMCo=
|
code.gitea.io/sdk/gitea v0.15.1-0.20220720025709-de34275bb64e/go.mod h1:aRmrQC3CAHdJAU1LQt0C9zqzqI8tUB/5oQtNE746aYE=
|
||||||
codeberg.org/6543/go-yaml2json v0.1.0 h1:njuf3a8QgsmBXJFiH+7wNR01biBS4MU+XeWE7W3bnus=
|
codeberg.org/6543/go-yaml2json v0.1.0 h1:njuf3a8QgsmBXJFiH+7wNR01biBS4MU+XeWE7W3bnus=
|
||||||
codeberg.org/6543/go-yaml2json v0.1.0/go.mod h1:mz61q14LWF4ZABrgMEDMmk3t9dPi6zgR1uBh2VKV2RQ=
|
codeberg.org/6543/go-yaml2json v0.1.0/go.mod h1:mz61q14LWF4ZABrgMEDMmk3t9dPi6zgR1uBh2VKV2RQ=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
|
@ -111,6 +111,8 @@ github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7h
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/davidmz/go-pageant v1.0.2 h1:bPblRCh5jGU+Uptpz6LgMZGD5hJoOt7otgT454WvHn0=
|
||||||
|
github.com/davidmz/go-pageant v1.0.2/go.mod h1:P2EDDnMqIwG5Rrp05dTRITj9z2zpGcD9efWSkTNKLIE=
|
||||||
github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/docker/cli v20.10.14+incompatible h1:dSBKJOVesDgHo7rbxlYjYsXe7gPzrTT+/cKQgpDAazg=
|
github.com/docker/cli v20.10.14+incompatible h1:dSBKJOVesDgHo7rbxlYjYsXe7gPzrTT+/cKQgpDAazg=
|
||||||
|
@ -158,6 +160,8 @@ github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs=
|
||||||
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
|
||||||
github.com/go-ap/httpsig v0.0.0-20210714162115-62a09257db51 h1:cytjZGyqtAu9JspfDt9ThCJ2KKCT/kPGDPCKWIZv8dw=
|
github.com/go-ap/httpsig v0.0.0-20210714162115-62a09257db51 h1:cytjZGyqtAu9JspfDt9ThCJ2KKCT/kPGDPCKWIZv8dw=
|
||||||
github.com/go-ap/httpsig v0.0.0-20210714162115-62a09257db51/go.mod h1:+4SUDMvPlRMUPW5PlMTbxj3U5a4fWasBIbakUw7Kp6c=
|
github.com/go-ap/httpsig v0.0.0-20210714162115-62a09257db51/go.mod h1:+4SUDMvPlRMUPW5PlMTbxj3U5a4fWasBIbakUw7Kp6c=
|
||||||
|
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
|
||||||
|
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
@ -305,8 +309,9 @@ github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdv
|
||||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4=
|
github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
|
||||||
|
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
|
@ -405,6 +410,8 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/lafriks/ttlcache/v3 v3.1.0 h1:/ths7O17AjV3hDkNo06fEfqwsDMd/Vbx9Em7yhD4V2k=
|
||||||
|
github.com/lafriks/ttlcache/v3 v3.1.0/go.mod h1:oxu8nlxF496noT0VKBf2gDQWHA6VDjoGFnn4qw9wAac=
|
||||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
||||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||||
|
@ -658,6 +665,7 @@ go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
|
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
|
||||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||||
|
@ -681,13 +689,15 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
|
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f h1:OeJjE6G4dgCY4PIXvIRQbE8+RX+uXZyGhUy/ksMGJoc=
|
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY=
|
||||||
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/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-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-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
|
@ -710,6 +720,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
|
||||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||||
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI=
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
|
@ -855,8 +866,8 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211031064116-611d5d643895/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
|
||||||
golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
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 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
|
||||||
|
|
63
server/cache/membership.go
vendored
Normal file
63
server/cache/membership.go
vendored
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
// Copyright 2022 Woodpecker Authors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/woodpecker-ci/woodpecker/server/model"
|
||||||
|
"github.com/woodpecker-ci/woodpecker/server/remote"
|
||||||
|
|
||||||
|
"github.com/lafriks/ttlcache/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MembershipService is a service to check for user membership.
|
||||||
|
type MembershipService interface {
|
||||||
|
// Get returns if the user is a member of the organization.
|
||||||
|
Get(ctx context.Context, u *model.User, name string) (*model.OrgPerm, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type membershipCache struct {
|
||||||
|
Remote remote.Remote
|
||||||
|
Cache *ttlcache.Cache[string, *model.OrgPerm]
|
||||||
|
TTL time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMembershipService creates a new membership service.
|
||||||
|
func NewMembershipService(r remote.Remote) MembershipService {
|
||||||
|
return &membershipCache{
|
||||||
|
TTL: 10 * time.Minute,
|
||||||
|
Remote: r,
|
||||||
|
Cache: ttlcache.New(ttlcache.WithDisableTouchOnHit[string, *model.OrgPerm]()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get returns if the user is a member of the organization.
|
||||||
|
func (c *membershipCache) Get(ctx context.Context, u *model.User, name string) (*model.OrgPerm, error) {
|
||||||
|
key := u.Login + "/" + name
|
||||||
|
// Error can be safely ignored, as cache can only return error from loaders.
|
||||||
|
item, _ := c.Cache.Get(key)
|
||||||
|
if item != nil && !item.IsExpired() {
|
||||||
|
return item.Value(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
perm, err := c.Remote.OrgMembership(ctx, u, name)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.Cache.Set(key, perm, c.TTL)
|
||||||
|
return perm, nil
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"crypto"
|
"crypto"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/woodpecker-ci/woodpecker/server/cache"
|
||||||
"github.com/woodpecker-ci/woodpecker/server/logging"
|
"github.com/woodpecker-ci/woodpecker/server/logging"
|
||||||
"github.com/woodpecker-ci/woodpecker/server/model"
|
"github.com/woodpecker-ci/woodpecker/server/model"
|
||||||
"github.com/woodpecker-ci/woodpecker/server/plugins/config"
|
"github.com/woodpecker-ci/woodpecker/server/plugins/config"
|
||||||
|
@ -38,6 +39,7 @@ var Config = struct {
|
||||||
Registries model.RegistryService
|
Registries model.RegistryService
|
||||||
Environ model.EnvironService
|
Environ model.EnvironService
|
||||||
Remote remote.Remote
|
Remote remote.Remote
|
||||||
|
Membership cache.MembershipService
|
||||||
ConfigService config.Extension
|
ConfigService config.Extension
|
||||||
SignaturePrivateKey crypto.PrivateKey
|
SignaturePrivateKey crypto.PrivateKey
|
||||||
SignaturePublicKey crypto.PublicKey
|
SignaturePublicKey crypto.PublicKey
|
||||||
|
|
|
@ -40,3 +40,9 @@ type Perm struct {
|
||||||
func (Perm) TableName() string {
|
func (Perm) TableName() string {
|
||||||
return "perms"
|
return "perms"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OrgPerm defines a organization permission for an individual user.
|
||||||
|
type OrgPerm struct {
|
||||||
|
Member bool `json:"member"`
|
||||||
|
Admin bool `json:"admin"`
|
||||||
|
}
|
||||||
|
|
|
@ -301,6 +301,16 @@ func (c *config) Hook(ctx context.Context, req *http.Request) (*model.Repo, *mod
|
||||||
return parseHook(req)
|
return parseHook(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OrgMembership returns if user is member of organization and if user
|
||||||
|
// is admin/owner in this organization.
|
||||||
|
func (c *config) OrgMembership(ctx context.Context, u *model.User, owner string) (*model.OrgPerm, error) {
|
||||||
|
perm, err := c.newClient(ctx, u).GetUserWorkspaceMembership(owner, u.Login)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &model.OrgPerm{Member: perm != "", Admin: perm == "owner"}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// helper function to return the bitbucket oauth2 client
|
// helper function to return the bitbucket oauth2 client
|
||||||
func (c *config) newClient(ctx context.Context, u *model.User) *internal.Client {
|
func (c *config) newClient(ctx context.Context, u *model.User) *internal.Client {
|
||||||
if u == nil {
|
if u == nil {
|
||||||
|
|
|
@ -46,6 +46,7 @@ const (
|
||||||
pathSource = "%s/2.0/repositories/%s/%s/src/%s/%s"
|
pathSource = "%s/2.0/repositories/%s/%s/src/%s/%s"
|
||||||
pathStatus = "%s/2.0/repositories/%s/%s/commit/%s/statuses/build"
|
pathStatus = "%s/2.0/repositories/%s/%s/commit/%s/statuses/build"
|
||||||
pathBranches = "%s/2.0/repositories/%s/%s/refs/branches"
|
pathBranches = "%s/2.0/repositories/%s/%s/refs/branches"
|
||||||
|
pathOrgPerms = "%s/2.0/workspaces/%s/permissions?%s"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
type Client struct {
|
||||||
|
@ -182,6 +183,28 @@ func (c *Client) ListBranches(owner, name string) ([]*Branch, error) {
|
||||||
return out.Values, err
|
return out.Values, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) GetUserWorkspaceMembership(workspace, user string) (string, error) {
|
||||||
|
out := new(WorkspaceMembershipResp)
|
||||||
|
opts := &ListOpts{Page: 1, PageLen: 100}
|
||||||
|
for {
|
||||||
|
uri := fmt.Sprintf(pathOrgPerms, c.base, workspace, opts.Encode())
|
||||||
|
_, err := c.do(uri, get, nil, out)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
for _, m := range out.Values {
|
||||||
|
if m.User.Nickname == user {
|
||||||
|
return m.Permission, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(out.Next) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
opts.Page++
|
||||||
|
}
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) do(rawurl, method string, in, out interface{}) (*string, error) {
|
func (c *Client) do(rawurl, method string, in, out interface{}) (*string, error) {
|
||||||
uri, err := url.Parse(rawurl)
|
uri, err := url.Parse(rawurl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -171,6 +171,19 @@ type PullRequestHook struct {
|
||||||
} `json:"pullrequest"`
|
} `json:"pullrequest"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type WorkspaceMembershipResp struct {
|
||||||
|
Page int `json:"page"`
|
||||||
|
Pages int `json:"pagelen"`
|
||||||
|
Size int `json:"size"`
|
||||||
|
Next string `json:"next"`
|
||||||
|
Values []struct {
|
||||||
|
Permission string `json:"permission"`
|
||||||
|
User struct {
|
||||||
|
Nickname string `json:"nickname"`
|
||||||
|
}
|
||||||
|
} `json:"values"`
|
||||||
|
}
|
||||||
|
|
||||||
type ListOpts struct {
|
type ListOpts struct {
|
||||||
Page int
|
Page int
|
||||||
PageLen int
|
PageLen int
|
||||||
|
|
|
@ -245,6 +245,13 @@ func (c *Config) Hook(ctx context.Context, r *http.Request) (*model.Repo, *model
|
||||||
return parseHook(r, c.URL)
|
return parseHook(r, c.URL)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OrgMembership returns if user is member of organization and if user
|
||||||
|
// is admin/owner in this organization.
|
||||||
|
func (c *Config) OrgMembership(ctx context.Context, u *model.User, owner string) (*model.OrgPerm, error) {
|
||||||
|
// TODO: Not implemented currently
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
func CreateConsumer(URL, ConsumerKey string, PrivateKey *rsa.PrivateKey) *oauth.Consumer {
|
func CreateConsumer(URL, ConsumerKey string, PrivateKey *rsa.PrivateKey) *oauth.Consumer {
|
||||||
consumer := oauth.NewRSAConsumer(
|
consumer := oauth.NewRSAConsumer(
|
||||||
ConsumerKey,
|
ConsumerKey,
|
||||||
|
|
|
@ -301,6 +301,13 @@ func (c *Coding) Hook(ctx context.Context, r *http.Request) (*model.Repo, *model
|
||||||
return repo, build, err
|
return repo, build, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OrgMembership returns if user is member of organization and if user
|
||||||
|
// is admin/owner in this organization.
|
||||||
|
func (c *Coding) OrgMembership(ctx context.Context, u *model.User, owner string) (*model.OrgPerm, error) {
|
||||||
|
// TODO: Not supported in Coding OAuth API
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// helper function to return the Coding oauth2 context using an HTTPClient that
|
// helper function to return the Coding oauth2 context using an HTTPClient that
|
||||||
// disables TLS verification if disabled in the remote settings.
|
// disables TLS verification if disabled in the remote settings.
|
||||||
func (c *Coding) newContext(ctx context.Context) context.Context {
|
func (c *Coding) newContext(ctx context.Context) context.Context {
|
||||||
|
|
|
@ -458,6 +458,31 @@ func (c *Gitea) Hook(ctx context.Context, r *http.Request) (*model.Repo, *model.
|
||||||
return parseHook(r)
|
return parseHook(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OrgMembership returns if user is member of organization and if user
|
||||||
|
// is admin/owner in this organization.
|
||||||
|
func (c *Gitea) OrgMembership(ctx context.Context, u *model.User, owner string) (*model.OrgPerm, error) {
|
||||||
|
client, err := c.newClientToken(ctx, u.Token)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
member, _, err := client.CheckOrgMembership(owner, u.Login)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !member {
|
||||||
|
return &model.OrgPerm{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
perm, _, err := client.GetOrgPermissions(owner, u.Login)
|
||||||
|
if err != nil {
|
||||||
|
return &model.OrgPerm{Member: member}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.OrgPerm{Member: member, Admin: perm.IsAdmin || perm.IsOwner}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// helper function to return the Gitea client with Token
|
// helper function to return the Gitea client with Token
|
||||||
func (c *Gitea) newClientToken(ctx context.Context, token string) (*gitea.Client, error) {
|
func (c *Gitea) newClientToken(ctx context.Context, token string) (*gitea.Client, error) {
|
||||||
httpClient := &http.Client{}
|
httpClient := &http.Client{}
|
||||||
|
|
|
@ -305,6 +305,18 @@ func (c *client) Deactivate(ctx context.Context, u *model.User, r *model.Repo, l
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OrgMembership returns if user is member of organization and if user
|
||||||
|
// is admin/owner in this organization.
|
||||||
|
func (c *client) OrgMembership(ctx context.Context, u *model.User, owner string) (*model.OrgPerm, error) {
|
||||||
|
client := c.newClientToken(ctx, u.Token)
|
||||||
|
org, _, err := client.Organizations.GetOrgMembership(ctx, u.Login, owner)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.OrgPerm{Member: org.GetState() == "active", Admin: org.GetRole() == "admin"}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// helper function to return the GitHub oauth2 context using an HTTPClient that
|
// helper function to return the GitHub oauth2 context using an HTTPClient that
|
||||||
// disables TLS verification if disabled in the remote settings.
|
// disables TLS verification if disabled in the remote settings.
|
||||||
func (c *client) newContext(ctx context.Context) context.Context {
|
func (c *client) newContext(ctx context.Context) context.Context {
|
||||||
|
|
|
@ -554,6 +554,62 @@ func (g *Gitlab) Hook(ctx context.Context, req *http.Request) (*model.Repo, *mod
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OrgMembership returns if user is member of organization and if user
|
||||||
|
// is admin/owner in this organization.
|
||||||
|
func (g *Gitlab) OrgMembership(ctx context.Context, u *model.User, owner string) (*model.OrgPerm, error) {
|
||||||
|
client, err := newClient(g.URL, u.Token, g.SkipVerify)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
groups, _, err := client.Groups.ListGroups(&gitlab.ListGroupsOptions{
|
||||||
|
ListOptions: gitlab.ListOptions{
|
||||||
|
Page: 1,
|
||||||
|
PerPage: 100,
|
||||||
|
},
|
||||||
|
Search: gitlab.String(owner),
|
||||||
|
}, gitlab.WithContext(ctx))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var gid int
|
||||||
|
for _, group := range groups {
|
||||||
|
if group.Name == owner {
|
||||||
|
gid = group.ID
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if gid == 0 {
|
||||||
|
return &model.OrgPerm{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
opts := &gitlab.ListGroupMembersOptions{
|
||||||
|
ListOptions: gitlab.ListOptions{
|
||||||
|
Page: 1,
|
||||||
|
PerPage: 100,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 1; true; i++ {
|
||||||
|
opts.Page = i
|
||||||
|
members, _, err := client.Groups.ListAllGroupMembers(gid, opts, gitlab.WithContext(ctx))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, member := range members {
|
||||||
|
if member.Username == u.Login {
|
||||||
|
return &model.OrgPerm{Member: true, Admin: member.AccessLevel >= gitlab.OwnerPermissions}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(members) < opts.PerPage {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &model.OrgPerm{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (g *Gitlab) loadChangedFilesFromMergeRequest(ctx context.Context, tmpRepo *model.Repo, build *model.Build, mergeIID int) (*model.Build, error) {
|
func (g *Gitlab) loadChangedFilesFromMergeRequest(ctx context.Context, tmpRepo *model.Repo, build *model.Build, mergeIID int) (*model.Build, error) {
|
||||||
_store, ok := store.TryFromContext(ctx)
|
_store, ok := store.TryFromContext(ctx)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -290,6 +290,25 @@ func (c *client) Hook(ctx context.Context, r *http.Request) (*model.Repo, *model
|
||||||
return parseHook(r)
|
return parseHook(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OrgMembership returns if user is member of organization and if user
|
||||||
|
// is admin/owner in this organization.
|
||||||
|
func (c *client) OrgMembership(ctx context.Context, u *model.User, owner string) (*model.OrgPerm, error) {
|
||||||
|
client := c.newClientToken(u.Token)
|
||||||
|
|
||||||
|
orgs, err := client.ListMyOrgs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, org := range orgs {
|
||||||
|
if org.UserName == owner {
|
||||||
|
// TODO: API does not support checking if user is admin/owner of org
|
||||||
|
return &model.OrgPerm{Member: true}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &model.OrgPerm{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// helper function to return the Gogs client
|
// helper function to return the Gogs client
|
||||||
func (c *client) newClient() *gogs.Client {
|
func (c *client) newClient() *gogs.Client {
|
||||||
return c.newClientToken("")
|
return c.newClientToken("")
|
||||||
|
|
|
@ -228,6 +228,29 @@ func (_m *Remote) Netrc(u *model.User, r *model.Repo) (*model.Netrc, error) {
|
||||||
return r0, r1
|
return r0, r1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OrgMembership provides a mock function with given fields: ctx, u, owner
|
||||||
|
func (_m *Remote) OrgMembership(ctx context.Context, u *model.User, owner string) (*model.OrgPerm, error) {
|
||||||
|
ret := _m.Called(ctx, u, owner)
|
||||||
|
|
||||||
|
var r0 *model.OrgPerm
|
||||||
|
if rf, ok := ret.Get(0).(func(context.Context, *model.User, string) *model.OrgPerm); ok {
|
||||||
|
r0 = rf(ctx, u, owner)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(*model.OrgPerm)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(1).(func(context.Context, *model.User, string) error); ok {
|
||||||
|
r1 = rf(ctx, u, owner)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
// Perm provides a mock function with given fields: ctx, u, r
|
// Perm provides a mock function with given fields: ctx, u, r
|
||||||
func (_m *Remote) Perm(ctx context.Context, u *model.User, r *model.Repo) (*model.Perm, error) {
|
func (_m *Remote) Perm(ctx context.Context, u *model.User, r *model.Repo) (*model.Perm, error) {
|
||||||
ret := _m.Called(ctx, u, r)
|
ret := _m.Called(ctx, u, r)
|
||||||
|
|
|
@ -79,6 +79,10 @@ type Remote interface {
|
||||||
// Hook parses the post-commit hook from the Request body and returns the
|
// Hook parses the post-commit hook from the Request body and returns the
|
||||||
// required data in a standard format.
|
// required data in a standard format.
|
||||||
Hook(ctx context.Context, r *http.Request) (*model.Repo, *model.Build, error)
|
Hook(ctx context.Context, r *http.Request) (*model.Repo, *model.Build, error)
|
||||||
|
|
||||||
|
// OrgMembership returns if user is member of organization and if user
|
||||||
|
// is admin/owner in that organization.
|
||||||
|
OrgMembership(ctx context.Context, u *model.User, owner string) (*model.OrgPerm, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileMeta represents a file in version control
|
// FileMeta represents a file in version control
|
||||||
|
|
|
@ -17,11 +17,13 @@ package session
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/woodpecker-ci/woodpecker/server"
|
||||||
|
|
||||||
"github.com/woodpecker-ci/woodpecker/server/model"
|
"github.com/woodpecker-ci/woodpecker/server/model"
|
||||||
"github.com/woodpecker-ci/woodpecker/server/store"
|
"github.com/woodpecker-ci/woodpecker/server/store"
|
||||||
"github.com/woodpecker-ci/woodpecker/shared/token"
|
"github.com/woodpecker-ci/woodpecker/shared/token"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func User(c *gin.Context) *model.User {
|
func User(c *gin.Context) *model.User {
|
||||||
|
@ -116,3 +118,39 @@ func MustUser() gin.HandlerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func MustOrgMember(admin bool) gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
user := User(c)
|
||||||
|
owner := c.Param("owner")
|
||||||
|
if user == nil {
|
||||||
|
c.String(http.StatusUnauthorized, "User not authorized")
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if owner == "" {
|
||||||
|
c.String(http.StatusForbidden, "User not authorized")
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// User can access his own, admin can access all
|
||||||
|
if user.Login == owner || user.Admin {
|
||||||
|
c.Next()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
perm, err := server.Config.Services.Membership.Get(c, user, owner)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Msgf("Failed to check membership: %v", err)
|
||||||
|
c.String(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if perm == nil || (!admin && !perm.Member) || (admin && !perm.Admin) {
|
||||||
|
c.String(http.StatusForbidden, "User not authorized")
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue