Skip to content

Commit ba6389b

Browse files
committed
add GH action workflows:
- dependabot to keep dependencies up to date - PR workflow to run tests and lint fix: linter findings Signed-off-by: Sandor Szücs <[email protected]>
1 parent 6bd0eb7 commit ba6389b

File tree

6 files changed

+176
-112
lines changed

6 files changed

+176
-112
lines changed

.github/dependabot.yml

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# To get started with Dependabot version updates, you'll need to specify which
2+
# package ecosystems to update and where the package manifests are located.
3+
# Please see the documentation for all configuration options:
4+
# * https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5+
# * https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
6+
version: 2
7+
updates:
8+
- package-ecosystem: "gomod"
9+
directory: "/"
10+
schedule:
11+
interval: "weekly"
12+
- package-ecosystem: "github-actions"
13+
directory: "/" # For GitHub Actions, set the directory to / to check for workflow files in .github/workflows
14+
schedule:
15+
interval: "weekly"

.github/workflows/pr.yaml

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: pr
2+
on: [ pull_request ]
3+
permissions:
4+
contents: read
5+
jobs:
6+
semgrep:
7+
if: ${{ github.actor != 'dependabot[bot]' }}
8+
runs-on: ubuntu-latest
9+
container:
10+
image: returntocorp/semgrep
11+
steps:
12+
# Retrieve the source code for the repository
13+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
14+
# Fetch the semgrep rules
15+
- run: git clone https://github.com/dgryski/semgrep-go.git
16+
# Run the rule checker using the fetched rules
17+
- run: semgrep ci -f semgrep-go
18+
19+
check-race:
20+
runs-on: ubuntu-latest
21+
steps:
22+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
23+
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
24+
with:
25+
# https://www.npmjs.com/package/semver#caret-ranges-123-025-004
26+
go-version: '^1.21'
27+
check-latest: true
28+
- run: go version
29+
- run: go test -race ./...
30+
tests:
31+
runs-on: ubuntu-latest
32+
steps:
33+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
34+
- uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491
35+
with:
36+
# https://www.npmjs.com/package/semver#caret-ranges-123-025-004
37+
go-version: '^1.21'
38+
check-latest: true
39+
- run: go version
40+
- run: go vet ./github ./google ./zalando
41+
- run: go test ./...
42+
- run: go install honnef.co/go/tools/cmd/staticcheck@latest
43+
- run: staticcheck -checks "all" ./github ./google ./zalando

example/zalando/main.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import (
88

99
"github.com/gin-gonic/gin"
1010
"github.com/golang/glog"
11-
"github.com/szuecs/gin-glog"
12-
"github.com/zalando/gin-oauth2"
11+
ginglog "github.com/szuecs/gin-glog"
12+
ginoauth2 "github.com/zalando/gin-oauth2"
1313
"github.com/zalando/gin-oauth2/zalando"
1414
)
1515

@@ -57,8 +57,8 @@ func main() {
5757
c.JSON(200, gin.H{"message": "Hello from private for groups and users"})
5858
})
5959
privateGroup.GET("/", func(c *gin.Context) {
60-
uid, okUid := c.Get("uid")
61-
if team, ok := c.Get("team"); ok && okUid {
60+
uid, okUID := c.Get("uid")
61+
if team, ok := c.Get("team"); ok && okUID {
6262
c.JSON(200, gin.H{"message": fmt.Sprintf("Hello from private for groups to %s member of %s", uid, team)})
6363
} else {
6464
c.JSON(200, gin.H{"message": "Hello from private for groups without uid and team"})

ginoauth2.go

+90-93
Original file line numberDiff line numberDiff line change
@@ -3,53 +3,53 @@
33
// webframework.
44
//
55
// Example:
6-
// package main
7-
// import (
8-
// "flag"
9-
// "time"
10-
// "github.com/gin-gonic/gin"
11-
// "github.com/golang/glog"
12-
// "github.com/szuecs/gin-glog"
13-
// "github.com/zalando/gin-oauth2"
14-
// "golang.org/x/oauth2"
15-
// )
166
//
17-
// var OAuth2Endpoint = oauth2.Endpoint{
18-
// AuthURL: "https://token.oauth2.corp.com/access_token",
19-
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo",
20-
// }
7+
// package main
8+
// import (
9+
// "flag"
10+
// "time"
11+
// "github.com/gin-gonic/gin"
12+
// "github.com/golang/glog"
13+
// "github.com/szuecs/gin-glog"
14+
// "github.com/zalando/gin-oauth2"
15+
// "golang.org/x/oauth2"
16+
// )
2117
//
22-
// func UidCheck(tc *TokenContainer, ctx *gin.Context) bool {
23-
// uid := tc.Scopes["uid"].(string)
24-
// if uid != "sszuecs" {
25-
// return false
26-
// }
27-
// ctx.Set("uid", uid)
28-
// return true
29-
// }
18+
// var OAuth2Endpoint = oauth2.Endpoint{
19+
// AuthURL: "https://token.oauth2.corp.com/access_token",
20+
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo",
21+
// }
3022
//
31-
// func main() {
32-
// flag.Parse()
33-
// router := gin.New()
34-
// router.Use(ginglog.Logger(3 * time.Second))
35-
// router.Use(gin.Recovery())
23+
// func UidCheck(tc *TokenContainer, ctx *gin.Context) bool {
24+
// uid := tc.Scopes["uid"].(string)
25+
// if uid != "sszuecs" {
26+
// return false
27+
// }
28+
// ctx.Set("uid", uid)
29+
// return true
30+
// }
3631
//
37-
// ginoauth2.VarianceTimer = 300 * time.Millisecond // defaults to 30s
32+
// func main() {
33+
// flag.Parse()
34+
// router := gin.New()
35+
// router.Use(ginglog.Logger(3 * time.Second))
36+
// router.Use(gin.Recovery())
3837
//
39-
// public := router.Group("/api")
40-
// public.GET("/", func(c *gin.Context) {
41-
// c.JSON(200, gin.H{"message": "Hello to public world"})
42-
// })
38+
// ginoauth2.VarianceTimer = 300 * time.Millisecond // defaults to 30s
4339
//
44-
// private := router.Group("/api/private")
45-
// private.Use(ginoauth2.Auth(UidCheck, OAuth2Endpoint))
46-
// private.GET("/", func(c *gin.Context) {
47-
// c.JSON(200, gin.H{"message": "Hello from private"})
48-
// })
40+
// public := router.Group("/api")
41+
// public.GET("/", func(c *gin.Context) {
42+
// c.JSON(200, gin.H{"message": "Hello to public world"})
43+
// })
4944
//
50-
// glog.Info("bootstrapped application")
51-
// router.Run(":8081")
45+
// private := router.Group("/api/private")
46+
// private.Use(ginoauth2.Auth(UidCheck, OAuth2Endpoint))
47+
// private.GET("/", func(c *gin.Context) {
48+
// c.JSON(200, gin.H{"message": "Hello from private"})
49+
// })
5250
//
51+
// glog.Info("bootstrapped application")
52+
// router.Run(":8081")
5353
package ginoauth2
5454

5555
import (
@@ -125,12 +125,12 @@ func infofv2(f string, args ...interface{}) {
125125
func extractToken(r *http.Request) (*oauth2.Token, error) {
126126
hdr := r.Header.Get("Authorization")
127127
if hdr == "" {
128-
return nil, errors.New("No authorization header")
128+
return nil, errors.New("no authorization header")
129129
}
130130

131131
th := strings.Split(hdr, " ")
132132
if len(th) != 2 {
133-
return nil, errors.New("Incomplete authorization header")
133+
return nil, errors.New("incomplete authorization header")
134134
}
135135

136136
return &oauth2.Token{AccessToken: th[1], TokenType: th[0]}, nil
@@ -179,10 +179,10 @@ func ParseTokenContainer(t *oauth2.Token, data map[string]interface{}) (*TokenCo
179179
exp := data["expires_in"].(float64)
180180
tok := data["access_token"].(string)
181181
if ttype != t.TokenType {
182-
return nil, errors.New("Token type mismatch")
182+
return nil, errors.New("token type mismatch")
183183
}
184184
if tok != t.AccessToken {
185-
return nil, errors.New("Mismatch between verify request and answer")
185+
return nil, errors.New("mismatch between verify request and answer")
186186
}
187187

188188
scopes := data["scope"].([]interface{})
@@ -219,9 +219,11 @@ func getTokenContainerForToken(o Options, token *oauth2.Token) (*TokenContainer,
219219
errorf("[Gin-OAuth] JSON.Unmarshal failed caused by: %s", err)
220220
return nil, err
221221
}
222-
if _, ok := data["error_description"]; ok {
223-
var s string
224-
s = data["error_description"].(string)
222+
if si, ok := data["error_description"]; ok {
223+
s, ok := si.(string)
224+
if !ok {
225+
s = ""
226+
}
225227
errorf("[Gin-OAuth] RequestAuthInfo returned an error: %s", s)
226228
return nil, errors.New(s)
227229
}
@@ -254,32 +256,30 @@ func getTokenContainer(o Options, ctx *gin.Context) (*TokenContainer, bool) {
254256
return tc, true
255257
}
256258

257-
//
258-
// TokenContainer
259-
//
260-
// Validates that the AccessToken within TokenContainer is not expired and not empty.
259+
// Valid validates that the AccessToken within TokenContainer is not
260+
// expired and not empty.
261261
func (t *TokenContainer) Valid() bool {
262262
if t.Token == nil {
263263
return false
264264
}
265265
return t.Token.Valid()
266266
}
267267

268-
// Router middleware that can be used to get an authenticated and authorized service for the whole router group.
268+
// Auth implements a router middleware that can be used to get an
269+
// authenticated and authorized service for the whole router group.
269270
// Example:
270271
//
271-
// var endpoints oauth2.Endpoint = oauth2.Endpoint{
272-
// AuthURL: "https://token.oauth2.corp.com/access_token",
273-
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo",
274-
// }
275-
// var acl []ginoauth2.AccessTuple = []ginoauth2.AccessTuple{{"employee", 1070, "sszuecs"}, {"employee", 1114, "njuettner"}}
276-
// router := gin.Default()
277-
// private := router.Group("")
278-
// private.Use(ginoauth2.Auth(ginoauth2.UidCheck, ginoauth2.endpoints))
279-
// private.GET("/api/private", func(c *gin.Context) {
280-
// c.JSON(200, gin.H{"message": "Hello from private"})
281-
// })
282-
//
272+
// var endpoints oauth2.Endpoint = oauth2.Endpoint{
273+
// AuthURL: "https://token.oauth2.corp.com/access_token",
274+
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo",
275+
// }
276+
// var acl []ginoauth2.AccessTuple = []ginoauth2.AccessTuple{{"employee", 1070, "sszuecs"}, {"employee", 1114, "njuettner"}}
277+
// router := gin.Default()
278+
// private := router.Group("")
279+
// private.Use(ginoauth2.Auth(ginoauth2.UidCheck, ginoauth2.endpoints))
280+
// private.GET("/api/private", func(c *gin.Context) {
281+
// c.JSON(200, gin.H{"message": "Hello from private"})
282+
// })
283283
func Auth(accessCheckFunction AccessCheckFunction, endpoints oauth2.Endpoint) gin.HandlerFunc {
284284
return AuthChain(endpoints, accessCheckFunction)
285285
}
@@ -289,22 +289,21 @@ func Auth(accessCheckFunction AccessCheckFunction, endpoints oauth2.Endpoint) gi
289289
// takes a chain of AccessCheckFunctions and only fails if all of them fails.
290290
// Example:
291291
//
292-
// var endpoints oauth2.Endpoint = oauth2.Endpoint{
293-
// AuthURL: "https://token.oauth2.corp.com/access_token",
294-
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo",
295-
// }
296-
// var acl []ginoauth2.AccessTuple = []ginoauth2.AccessTuple{{"employee", 1070, "sszuecs"}, {"employee", 1114, "njuettner"}}
297-
// router := gin.Default()
298-
// private := router.Group("")
299-
// checkChain := []AccessCheckFunction{
300-
// ginoauth2.UidCheck,
301-
// ginoauth2.GroupCheck,
302-
// }
303-
// private.Use(ginoauth2.AuthChain(checkChain, ginoauth2.endpoints))
304-
// private.GET("/api/private", func(c *gin.Context) {
305-
// c.JSON(200, gin.H{"message": "Hello from private"})
306-
// })
307-
//
292+
// var endpoints oauth2.Endpoint = oauth2.Endpoint{
293+
// AuthURL: "https://token.oauth2.corp.com/access_token",
294+
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo",
295+
// }
296+
// var acl []ginoauth2.AccessTuple = []ginoauth2.AccessTuple{{"employee", 1070, "sszuecs"}, {"employee", 1114, "njuettner"}}
297+
// router := gin.Default()
298+
// private := router.Group("")
299+
// checkChain := []AccessCheckFunction{
300+
// ginoauth2.UidCheck,
301+
// ginoauth2.GroupCheck,
302+
// }
303+
// private.Use(ginoauth2.AuthChain(checkChain, ginoauth2.endpoints))
304+
// private.GET("/api/private", func(c *gin.Context) {
305+
// c.JSON(200, gin.H{"message": "Hello from private"})
306+
// })
308307
func AuthChain(endpoint oauth2.Endpoint, accessCheckFunctions ...AccessCheckFunction) gin.HandlerFunc {
309308
return AuthChainOptions(Options{Endpoint: endpoint}, accessCheckFunctions...)
310309
}
@@ -322,15 +321,15 @@ func AuthChainOptions(o Options, accessCheckFunctions ...AccessCheckFunction) gi
322321
if !ok {
323322
// set LOCATION header to auth endpoint such that the user can easily get a new access-token
324323
ctx.Writer.Header().Set("Location", o.Endpoint.AuthURL)
325-
ctx.AbortWithError(http.StatusUnauthorized, errors.New("No token in context"))
324+
ctx.AbortWithError(http.StatusUnauthorized, errors.New("no token in context"))
326325
varianceControl <- false
327326
return
328327
}
329328

330329
if !tokenContainer.Valid() {
331330
// set LOCATION header to auth endpoint such that the user can easily get a new access-token
332331
ctx.Writer.Header().Set("Location", o.Endpoint.AuthURL)
333-
ctx.AbortWithError(http.StatusUnauthorized, errors.New("Invalid Token"))
332+
ctx.AbortWithError(http.StatusUnauthorized, errors.New("invalid Token"))
334333
varianceControl <- false
335334
return
336335
}
@@ -342,7 +341,7 @@ func AuthChainOptions(o Options, accessCheckFunctions ...AccessCheckFunction) gi
342341
}
343342

344343
if len(accessCheckFunctions)-1 == i {
345-
ctx.AbortWithError(http.StatusForbidden, errors.New("Access to the Resource is forbidden"))
344+
ctx.AbortWithError(http.StatusForbidden, errors.New("access to the Resource is forbidden"))
346345
varianceControl <- false
347346
return
348347
}
@@ -356,7 +355,7 @@ func AuthChainOptions(o Options, accessCheckFunctions ...AccessCheckFunction) gi
356355
return
357356
}
358357
case <-time.After(VarianceTimer):
359-
ctx.AbortWithError(http.StatusGatewayTimeout, errors.New("Authorization check overtime"))
358+
ctx.AbortWithError(http.StatusGatewayTimeout, errors.New("authorization check overtime"))
360359
infofv2("[Gin-OAuth] %12v %s overtime", time.Since(t), ctx.Request.URL.Path)
361360
return
362361
}
@@ -375,22 +374,20 @@ func AuthChainOptions(o Options, accessCheckFunctions ...AccessCheckFunction) gi
375374
//
376375
// Example:
377376
//
378-
// var endpoints oauth2.Endpoint = oauth2.Endpoint{
379-
// AuthURL: "https://token.oauth2.corp.com/access_token",
380-
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo",
381-
// }
382-
// var acl []ginoauth2.AccessTuple = []ginoauth2.AccessTuple{{"employee", 1070, "sszuecs"}, {"employee", 1114, "njuettner"}}
383-
// router := gin.Default()
384-
// router.Use(ginoauth2.RequestLogger([]string{"uid"}, "data"))
385-
//
377+
// var endpoints oauth2.Endpoint = oauth2.Endpoint{
378+
// AuthURL: "https://token.oauth2.corp.com/access_token",
379+
// TokenURL: "https://oauth2.corp.com/corp/oauth2/tokeninfo",
380+
// }
381+
// var acl []ginoauth2.AccessTuple = []ginoauth2.AccessTuple{{"employee", 1070, "sszuecs"}, {"employee", 1114, "njuettner"}}
382+
// router := gin.Default()
383+
// router.Use(ginoauth2.RequestLogger([]string{"uid"}, "data"))
386384
func RequestLogger(keys []string, contentKey string) gin.HandlerFunc {
387385
return func(c *gin.Context) {
388386
request := c.Request
389387
c.Next()
390388
err := c.Errors
391389
if request.Method != "GET" && err == nil {
392-
data, e := c.Get(contentKey)
393-
if e != false { //key is non existent
390+
if data, ok := c.Get(contentKey); !ok {
394391
values := make([]string, 0)
395392
for _, key := range keys {
396393
val, keyPresent := c.Get(key)

0 commit comments

Comments
 (0)