diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 2d9bcddb..d5be5239 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -13,12 +13,12 @@ name: "CodeQL" on: push: - branches: [ master ] + branches: [master] pull_request: # The branches below must be a subset of the branches above - branches: [ master ] + branches: [master] schedule: - - cron: '41 23 * * 6' + - cron: "41 23 * * 6" jobs: analyze: @@ -32,23 +32,23 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'go' ] + language: ["go"] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://git.io/codeql-language-support steps: - - name: Checkout repository - uses: actions/checkout@v3 + - name: Checkout repository + uses: actions/checkout@v6 - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v4 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v4 diff --git a/.github/workflows/goreleaser.yml b/.github/workflows/goreleaser.yml index 3af3a455..dffa9d0d 100644 --- a/.github/workflows/goreleaser.yml +++ b/.github/workflows/goreleaser.yml @@ -3,7 +3,7 @@ name: Goreleaser on: push: tags: - - '*' + - "*" permissions: contents: write @@ -12,23 +12,22 @@ jobs: goreleaser: runs-on: ubuntu-latest steps: - - - name: Checkout - uses: actions/checkout@v3 + - name: Checkout repository + uses: actions/checkout@v6 with: fetch-depth: 0 - - - name: Set up Go - uses: actions/setup-go@v3 + + - name: Setup go + uses: actions/setup-go@v6 with: - go-version: 1.17 - - - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v4 + go-version-file: go.mod + check-latest: true + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v7 with: # either 'goreleaser' (default) or 'goreleaser-pro' distribution: goreleaser version: latest - args: release --rm-dist + args: release --clean env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 51f87bba..e428798f 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -6,7 +6,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - go: [1.16, 1.17, 1.18, 1.19, '1.20'] + go: [1.25, 1.26] name: ${{ matrix.os }} @ Go ${{ matrix.go }} runs-on: ${{ matrix.os }} @@ -16,17 +16,17 @@ jobs: GOPROXY: https://proxy.golang.org steps: - name: Set up Go ${{ matrix.go }} - uses: actions/setup-go@v3 + uses: actions/setup-go@v6 with: go-version: ${{ matrix.go }} - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v6 with: ref: ${{ github.ref }} - name: golangci-lint - uses: golangci/golangci-lint-action@v3 + uses: golangci/golangci-lint-action@v9 with: - version: v1.51.1 - args: --verbose --timeout 10m + version: v2.12 + args: --verbose diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index ea41103d..5840ba50 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -10,20 +10,21 @@ on: jobs: # Label of the container job runner-job: - # You must use a Linux environment when using service containers or container jobs - runs-on: ubuntu-latest + strategy: + matrix: + os: [ubuntu-latest] + go: [1.25, 1.26] + name: ${{ matrix.os }} @ Go ${{ matrix.go }} + runs-on: ${{ matrix.os }} - env: - GO111MODULE: on - GOPROXY: https://proxy.golang.org steps: - name: Start Redis - uses: supercharge/redis-github-action@1.4.0 + uses: supercharge/redis-github-action@1.8.1 with: redis-version: 4 - name: Start MongoDB 4.2 - uses: supercharge/mongodb-github-action@1.8.0 + uses: supercharge/mongodb-github-action@1.12.1 with: mongodb-version: 4.2 @@ -33,15 +34,17 @@ jobs: postgresql db: testdb postgresql user: testuser postgresql password: testpw - postgresql version: '14' + postgresql version: "14" - - uses: niden/actions-memcached@v7 + - uses: niden/actions-memcached@v8 - name: Set up Go ${{ matrix.go }} - uses: actions/setup-go@v3 + uses: actions/setup-go@v6 + with: + go-version: ${{ matrix.go }} - name: Checkout Code - uses: actions/checkout@v3 + uses: actions/checkout@v6 with: ref: ${{ github.ref }} @@ -50,4 +53,21 @@ jobs: go test -v -covermode=atomic -coverprofile=coverage.out ./... - name: Upload coverage to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v7 + + vulnerability-scanning: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Run Trivy vulnerability scanner in repo mode + uses: aquasecurity/trivy-action@v0.36.0 + with: + scan-type: "fs" + ignore-unfixed: true + format: "sarif" + output: "trivy-results.sarif" + exit-code: "1" + severity: "CRITICAL,HIGH" diff --git a/.github/workflows/trivy-scan.yml b/.github/workflows/trivy-scan.yml new file mode 100644 index 00000000..8a22c264 --- /dev/null +++ b/.github/workflows/trivy-scan.yml @@ -0,0 +1,56 @@ +name: Trivy Security Scan + +on: + push: + branches: + - master + pull_request: + branches: + - master + schedule: + # Run daily at 00:00 UTC + - cron: '0 0 * * *' + workflow_dispatch: # Allow manual trigger + +permissions: + contents: read + security-events: write # Required for uploading SARIF results + +jobs: + trivy-scan: + name: Trivy Security Scan + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Run Trivy vulnerability scanner (source code) + uses: aquasecurity/trivy-action@v0.36.0 + with: + scan-type: 'fs' + scan-ref: '.' + scanners: 'vuln,secret,misconfig' + format: 'sarif' + output: 'trivy-results.sarif' + severity: 'CRITICAL,HIGH,MEDIUM' + ignore-unfixed: true + + - name: Upload Trivy results to GitHub Security tab + uses: github/codeql-action/upload-sarif@v4 + if: always() + with: + sarif_file: 'trivy-results.sarif' + + - name: Run Trivy scanner (table output for logs) + uses: aquasecurity/trivy-action@v0.36.0 + if: always() + with: + scan-type: 'fs' + scan-ref: '.' + scanners: 'vuln,secret,misconfig' + format: 'table' + severity: 'CRITICAL,HIGH,MEDIUM' + ignore-unfixed: true + exit-code: '1' diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..47094ac6 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,50 @@ +version: "2" +linters: + default: none + enable: + - bodyclose + - dogsled + - dupl + - errcheck + - exhaustive + - gochecknoinits + - goconst + - gocritic + - gocyclo + - goprintffuncname + - gosec + - govet + - ineffassign + - lll + - misspell + - nakedret + - noctx + - nolintlint + - rowserrcheck + - staticcheck + - unconvert + - unparam + - unused + - whitespace + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + - gofumpt + - goimports + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/.goreleaser.yaml b/.goreleaser.yaml index aa5453cf..dc3a01fb 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -1,57 +1,26 @@ -project_name: queue - builds: - - - # If true, skip the build. - # Useful for library projects. - # Default is false - skip: true + - skip: true changelog: - # Set it to true if you wish to skip the changelog generation. - # This may result in an empty release notes on GitHub/GitLab/Gitea. - skip: false - - # Changelog generation implementation to use. - # - # Valid options are: - # - `git`: uses `git log`; - # - `github`: uses the compare GitHub API, appending the author login to the changelog. - # - `gitlab`: uses the compare GitLab API, appending the author name and email to the changelog. - # - `github-native`: uses the GitHub release notes generation API, disables the groups feature. - # - # Defaults to `git`. - use: git - - # Sorts the changelog by the commit's messages. - # Could either be asc, desc or empty - # Default is empty - sort: asc - - # Group commits messages by given regex and title. - # Order value defines the order of the groups. - # Proving no regex means all commits will be grouped under the default group. - # Groups are disabled when using github-native, as it already groups things by itself. - # - # Default is no groups. + use: github groups: - title: Features regexp: "^.*feat[(\\w)]*:+.*$" order: 0 - - title: 'Bug fixes' + - title: "Bug fixes" regexp: "^.*fix[(\\w)]*:+.*$" order: 1 - - title: 'Enhancements' + - title: "Enhancements" regexp: "^.*chore[(\\w)]*:+.*$" order: 2 + - title: "Refactor" + regexp: "^.*refactor[(\\w)]*:+.*$" + order: 3 + - title: "Build process updates" + regexp: ^.*?(build|ci)(\(.+\))??!?:.+$ + order: 4 + - title: "Documentation updates" + regexp: ^.*?docs?(\(.+\))??!?:.+$ + order: 4 - title: Others order: 999 - - filters: - # Commit messages matching the regexp listed here will be removed from - # the changelog - # Default is empty - exclude: - - '^docs' - - 'CICD' - - typo diff --git a/README.md b/README.md index 9984794e..4a79ee20 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # sessions -[![Run CI Lint](https://github.com/gin-contrib/sessions/actions/workflows/lint.yml/badge.svg)](https://github.com/gin-contrib/sessions/actions/workflows/lint.yml) -[![Run Testing](https://github.com/gin-contrib/sessions/actions/workflows/testing.yml/badge.svg)](https://github.com/gin-contrib/sessions/actions/workflows/testing.yml) +[![Run CI Lint](https://github.com/gin-contrib/sessions/actions/workflows/lint.yml/badge.svg?branch=master)](https://github.com/gin-contrib/sessions/actions/workflows/lint.yml) +[![Run Testing](https://github.com/gin-contrib/sessions/actions/workflows/testing.yml/badge.svg?branch=master)](https://github.com/gin-contrib/sessions/actions/workflows/testing.yml) +[![Trivy Security Scan](https://github.com/gin-contrib/sessions/actions/workflows/trivy-scan.yml/badge.svg)](https://github.com/gin-contrib/sessions/actions/workflows/trivy-scan.yml) [![codecov](https://codecov.io/gh/gin-contrib/sessions/branch/master/graph/badge.svg)](https://codecov.io/gh/gin-contrib/sessions) [![Go Report Card](https://goreportcard.com/badge/github.com/gin-contrib/sessions)](https://goreportcard.com/report/github.com/gin-contrib/sessions) [![GoDoc](https://godoc.org/github.com/gin-contrib/sessions?status.svg)](https://godoc.org/github.com/gin-contrib/sessions) -[![Join the chat at https://gitter.im/gin-gonic/gin](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/gin-gonic/gin) Gin middleware for session management with multi-backend support: @@ -13,9 +13,10 @@ Gin middleware for session management with multi-backend support: - [Redis](#redis) - [memcached](#memcached) - [MongoDB](#mongodb) -- [GoRM](#gorm) +- [GORM](#gorm) - [memstore](#memstore) - [PostgreSQL](#postgresql) +- [Filesystem](#Filesystem) ## Usage @@ -105,6 +106,56 @@ func main() { } ``` +### multiple sessions with different stores + +```go +package main + +import ( + "github.com/gin-contrib/sessions" + "github.com/gin-contrib/sessions/cookie" + "github.com/gin-gonic/gin" +) + +func main() { + r := gin.Default() + cookieStore := cookie.NewStore([]byte("secret")) + redisStore, _ := redis.NewStore(10, "tcp", "localhost:6379", "", []byte("secret")) + sessionStores := []sessions.SessionStore{ + { + Name: "a", + Store: cookieStore, + }, + { + Name: "b", + Store: redisStore, + }, + } + r.Use(sessions.SessionsManyStores(sessionStores)) + + r.GET("/hello", func(c *gin.Context) { + sessionA := sessions.DefaultMany(c, "a") + sessionB := sessions.DefaultMany(c, "b") + + if sessionA.Get("hello") != "world!" { + sessionA.Set("hello", "world!") + sessionA.Save() + } + + if sessionB.Get("hello") != "world?" { + sessionB.Set("hello", "world?") + sessionB.Save() + } + + c.JSON(200, gin.H{ + "a": sessionA.Get("hello"), + "b": sessionB.Get("hello"), + }) + }) + r.Run(":8000") +} +``` + ## Backend Examples ### cookie-based @@ -251,6 +302,7 @@ func main() { ### MongoDB #### mgo + ```go package main @@ -291,7 +343,8 @@ func main() { ``` #### mongo-driver -``` + +```go package main import ( @@ -371,9 +424,8 @@ func main() { } ``` -### GoRM +### GORM -[embedmd]:# (_example/gorm/main.go go) ```go package main @@ -456,3 +508,40 @@ func main() { r.Run(":8000") } ``` + +### Filesystem + +```go +package main + +import ( + "github.com/gin-contrib/sessions" + "github.com/gin-contrib/sessions/filesystem" + "github.com/gin-gonic/gin" +) + +func main() { + r := gin.Default() + + var sessionPath = "/tmp/" // in case of empty string, the system's default tmp folder is used + + store := filesystem.NewStore(sessionPath,[]byte("secret")) + r.Use(sessions.Sessions("mysession", store)) + + r.GET("/incr", func(c *gin.Context) { + session := sessions.Default(c) + var count int + v := session.Get("count") + if v == nil { + count = 0 + } else { + count = v.(int) + count++ + } + session.Set("count", count) + session.Save() + c.JSON(200, gin.H{"count": count}) + }) + r.Run(":8000") +} +``` diff --git a/_example/filesystem/main.go b/_example/filesystem/main.go new file mode 100644 index 00000000..3ea148d7 --- /dev/null +++ b/_example/filesystem/main.go @@ -0,0 +1,30 @@ +package main + +import ( + sessions "github.com/geschke/gin-contrib-sessions" + "github.com/geschke/gin-contrib-sessions/filesystem" + "github.com/gin-gonic/gin" +) + +func main() { + sessionPath := "/tmp/" + r := gin.Default() + store := filesystem.NewStore(sessionPath, []byte("secret")) + r.Use(sessions.Sessions("mysession", store)) + + r.GET("/incr", func(c *gin.Context) { + session := sessions.Default(c) + var count int + v := session.Get("count") + if v == nil { + count = 0 + } else { + count = v.(int) + count++ + } + session.Set("count", count) + session.Save() + c.JSON(200, gin.H{"count": count}) + }) + r.Run(":8000") +} diff --git a/cookie/cookie_test.go b/cookie/cookie_test.go index 9f2da68a..78be9e95 100644 --- a/cookie/cookie_test.go +++ b/cookie/cookie_test.go @@ -35,3 +35,7 @@ func TestCookie_SessionOptions(t *testing.T) { func TestCookie_SessionMany(t *testing.T) { tester.Many(t, newStore) } + +func TestCookie_SessionManyStores(t *testing.T) { + tester.ManyStores(t, newStore) +} diff --git a/filesystem/filesystem.go b/filesystem/filesystem.go new file mode 100644 index 00000000..7aa19913 --- /dev/null +++ b/filesystem/filesystem.go @@ -0,0 +1,31 @@ +package filesystem + +import ( + "github.com/gin-contrib/sessions" + gsessions "github.com/gorilla/sessions" +) + +type Store interface { + sessions.Store +} + +// Keys are defined in pairs to allow key rotation, but the common case is to set a single +// authentication key and optionally an encryption key. +// +// The first key in a pair is used for authentication and the second for encryption. The +// encryption key can be set to nil or omitted in the last pair, but the authentication key +// is required in all pairs. +// +// It is recommended to use an authentication key with 32 or 64 bytes. The encryption key, +// if set, must be either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256 modes. +func NewStore(path string, keyPairs ...[]byte) Store { + return &store{gsessions.NewFilesystemStore(path, keyPairs...)} +} + +type store struct { + *gsessions.FilesystemStore +} + +func (c *store) Options(options sessions.Options) { + c.FilesystemStore.Options = options.ToGorillaOptions() +} diff --git a/filesystem/filesystem_test.go b/filesystem/filesystem_test.go new file mode 100644 index 00000000..0418c369 --- /dev/null +++ b/filesystem/filesystem_test.go @@ -0,0 +1,40 @@ +package filesystem + +import ( + "os" + "testing" + + "github.com/gin-contrib/sessions" + "github.com/gin-contrib/sessions/tester" +) + +var sessionPath = os.TempDir() + +var newStore = func(_ *testing.T) sessions.Store { + store := NewStore(sessionPath, []byte("secret")) + return store +} + +func TestFilesystem_SessionGetSet(t *testing.T) { + tester.GetSet(t, newStore) +} + +func TestFilesystem_SessionDeleteKey(t *testing.T) { + tester.DeleteKey(t, newStore) +} + +func TestFilesystem_SessionFlashes(t *testing.T) { + tester.Flashes(t, newStore) +} + +func TestFilesystem_SessionClear(t *testing.T) { + tester.Clear(t, newStore) +} + +func TestFilesystem_SessionOptions(t *testing.T) { + tester.Options(t, newStore) +} + +func TestFilesystem_SessionMany(t *testing.T) { + tester.Many(t, newStore) +} diff --git a/go.mod b/go.mod index 486a9045..c6cd5068 100644 --- a/go.mod +++ b/go.mod @@ -1,58 +1,69 @@ module github.com/gin-contrib/sessions -go 1.18 +go 1.25.0 require ( github.com/antonlindstrom/pgstore v0.0.0-20220421113606-e3a6e3fed12a - github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff - github.com/bos-hieu/mongostore v0.0.3 - github.com/bradfitz/gomemcache v0.0.0-20230124162541-5f7a7d875746 - github.com/bradleypeabody/gorilla-sessions-memcache v0.0.0-20181103040241-659414f458e1 - github.com/gin-gonic/gin v1.8.2 + github.com/boj/redistore v1.4.1 + github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf + github.com/bradleypeabody/gorilla-sessions-memcache v0.0.0-20240916143655-c0e34fd2f304 + github.com/gin-gonic/gin v1.12.0 github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 - github.com/gomodule/redigo v2.0.0+incompatible - github.com/gorilla/context v1.1.1 - github.com/gorilla/sessions v1.2.1 + github.com/gomodule/redigo v1.9.2 + github.com/gorilla/context v1.1.2 + github.com/gorilla/sessions v1.4.0 github.com/kidstuff/mongostore v0.0.0-20181113001930-e650cd85ee4b + github.com/laziness-coders/mongostore v0.0.14 github.com/memcachier/mc v2.0.1+incompatible github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b github.com/wader/gormstore/v2 v2.0.3 - go.mongodb.org/mongo-driver v1.11.1 - gorm.io/driver/sqlite v1.4.4 - gorm.io/gorm v1.24.5 + go.mongodb.org/mongo-driver v1.17.3 + gorm.io/driver/sqlite v1.5.7 + gorm.io/gorm v1.25.12 ) require ( - github.com/gin-contrib/sse v0.1.0 // indirect + github.com/bytedance/gopkg v0.1.3 // indirect + github.com/bytedance/sonic v1.15.0 // indirect + github.com/bytedance/sonic/loader v0.5.0 // indirect + github.com/cloudwego/base64x v0.1.6 // indirect + github.com/gabriel-vasile/mimetype v1.4.12 // indirect + github.com/gin-contrib/sse v1.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.11.2 // indirect - github.com/goccy/go-json v0.10.0 // indirect - github.com/golang/snappy v0.0.4 // indirect - github.com/gorilla/securecookie v1.1.1 // indirect + github.com/go-playground/validator/v10 v10.30.1 // indirect + github.com/goccy/go-json v0.10.5 // indirect + github.com/goccy/go-yaml v1.19.2 // indirect + github.com/golang/snappy v1.0.0 // indirect + github.com/gorilla/securecookie v1.1.2 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/compress v1.15.15 // indirect - github.com/leodido/go-urn v1.2.1 // indirect - github.com/lib/pq v1.10.7 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect - github.com/mattn/go-sqlite3 v1.14.16 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/klauspost/cpuid/v2 v2.3.0 // indirect + github.com/leodido/go-urn v1.4.0 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-sqlite3 v1.14.22 // indirect + github.com/memcachier/mc/v3 v3.0.3 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/montanaflynn/stats v0.7.0 // indirect - github.com/pelletier/go-toml/v2 v2.0.6 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/ugorji/go/codec v1.2.9 // indirect + github.com/montanaflynn/stats v0.7.1 // indirect + github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/quic-go/qpack v0.6.0 // indirect + github.com/quic-go/quic-go v0.59.0 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.3.1 // indirect github.com/xdg-go/pbkdf2 v1.0.0 // indirect - github.com/xdg-go/scram v1.1.2 // indirect + github.com/xdg-go/scram v1.2.0 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect - github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect - golang.org/x/crypto v0.5.0 // indirect - golang.org/x/net v0.5.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/text v0.6.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect + go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect + golang.org/x/arch v0.22.0 // indirect + golang.org/x/crypto v0.48.0 // indirect + golang.org/x/net v0.51.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/sys v0.41.0 // indirect + golang.org/x/text v0.35.0 // indirect + google.golang.org/protobuf v1.36.10 // indirect ) diff --git a/go.sum b/go.sum index 4c461be0..bac5848e 100644 --- a/go.sum +++ b/go.sum @@ -2,14 +2,20 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/antonlindstrom/pgstore v0.0.0-20220421113606-e3a6e3fed12a h1:dIdcLbck6W67B5JFMewU5Dba1yKZA3MsT67i4No/zh0= github.com/antonlindstrom/pgstore v0.0.0-20220421113606-e3a6e3fed12a/go.mod h1:Sdr/tmSOLEnncCuXS5TwZRxuk7deH1WXVY8cve3eVBM= -github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff h1:RmdPFa+slIr4SCBg4st/l/vZWVe9QJKMXGO60Bxbe04= -github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff/go.mod h1:+RTT1BOk5P97fT2CiHkbFQwkK3mjsFAP6zCYV2aXtjw= -github.com/bos-hieu/mongostore v0.0.3 h1:wla8pz4VQU8JOcbo+sBbuvFVBBHt3yRelVSi6YInC48= -github.com/bos-hieu/mongostore v0.0.3/go.mod h1:8AbbVmDEb0yqJsBrWxZIAZOxIfv/tsP8CDtdHduZHGg= -github.com/bradfitz/gomemcache v0.0.0-20230124162541-5f7a7d875746 h1:wAIE/kN63Oig1DdOzN7O+k4AbFh2cCJoKMFXrwRJtzk= -github.com/bradfitz/gomemcache v0.0.0-20230124162541-5f7a7d875746/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= -github.com/bradleypeabody/gorilla-sessions-memcache v0.0.0-20181103040241-659414f458e1 h1:4QHxgr7hM4gVD8uOwrk8T1fjkKRLwaLjmTkU0ibhZKU= -github.com/bradleypeabody/gorilla-sessions-memcache v0.0.0-20181103040241-659414f458e1/go.mod h1:dkChI7Tbtx7H1Tj7TqGSZMOeGpMP5gLHtjroHd4agiI= +github.com/boj/redistore v1.4.1 h1:lP9ZZWqKMq2RIqexlZX1w1ODSnegL+puxGIujkU5tIw= +github.com/boj/redistore v1.4.1/go.mod h1:c0Tvw6aMjslog4jHIAcNv6EtJM849YoOAhMY7JBbWpI= +github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf h1:TqhNAT4zKbTdLa62d2HDBFdvgSbIGB3eJE8HqhgiL9I= +github.com/bradfitz/gomemcache v0.0.0-20250403215159-8d39553ac7cf/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c= +github.com/bradleypeabody/gorilla-sessions-memcache v0.0.0-20240916143655-c0e34fd2f304 h1:f/AUyZ4PoqHhBJnhMrrNtSNYH5RvLxr5UQ0qrOZ9jkE= +github.com/bradleypeabody/gorilla-sessions-memcache v0.0.0-20240916143655-c0e34fd2f304/go.mod h1:dkChI7Tbtx7H1Tj7TqGSZMOeGpMP5gLHtjroHd4agiI= +github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= +github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= +github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= +github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= +github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE= +github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= +github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= +github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= @@ -17,45 +23,50 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do 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/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY= -github.com/gin-gonic/gin v1.8.2/go.mod h1:qw5AYuDrzRTnhvusDsrov+fDIxp9Dleuu12h8nfB398= +github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw= +github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= +github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= +github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= +github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8= +github.com/gin-gonic/gin v1.12.0/go.mod h1:VxccKfsSllpKshkBWgVgRniFFAzFb9csfngsqANjnLc= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 h1:DujepqpGd1hyOd7aW59XpK7Qymp8iy83xq74fLr21is= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU= -github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s= +github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w= +github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= -github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= +github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= +github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= -github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= -github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs= +github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v1.9.2 h1:HrutZBLhSIU8abiSfW8pj8mPhOyMYjZT/wcA4/L9L9s= +github.com/gomodule/redigo v1.9.2/go.mod h1:KsU3hiK/Ay8U42qpaJk+kuNa3C+spxapWpM+ywhcgtw= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= +github.com/gorilla/context v1.1.2 h1:WRkNAv2uoa03QNIc1A6u4O7DAGMUVoopZhkiXWA2V1o= +github.com/gorilla/context v1.1.2/go.mod h1:KDPwT9i/MeWHiLl90fuTgrt4/wPcv75vFAZLaOOcbxM= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= -github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= -github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= +github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= +github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ= +github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= @@ -114,56 +125,66 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/kidstuff/mongostore v0.0.0-20181113001930-e650cd85ee4b h1:TLCm7HR+P9HM2NXaAJaIiHerOUMedtFJeAfaYwZ8YhY= github.com/kidstuff/mongostore v0.0.0-20181113001930-e650cd85ee4b/go.mod h1:g2nVr8KZVXJSS97Jo8pJ0jgq29P6H7dG0oplUA86MQw= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= -github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw= -github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= +github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -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/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/laziness-coders/mongostore v0.0.14 h1:4RrtOeTsGr3pBbImtpCZT7L4LB/kXfAzpCPXds69RgA= +github.com/laziness-coders/mongostore v0.0.14/go.mod h1:Rh+yJax2Vxc2QY62clIM/kRnLk+TxivgSLHOXENXPtk= +github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= +github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= -github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= -github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/memcachier/mc v2.0.1+incompatible h1:s8EDz0xrJLP8goitwZOoq1vA/sm0fPS4X3KAF0nyhWQ= github.com/memcachier/mc v2.0.1+incompatible/go.mod h1:7bkvFE61leUBvXz+yxsOnGBQSZpBSPIMUQSmmSHvuXc= +github.com/memcachier/mc/v3 v3.0.3 h1:qii+lDiPKi36O4Xg+HVKwHu6Oq+Gt17b+uEiA0Drwv4= +github.com/memcachier/mc/v3 v3.0.3/go.mod h1:GzjocBahcXPxt2cmqzknrgqCOmMxiSzhVKPOe90Tpug= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= -github.com/montanaflynn/stats v0.7.0 h1:r3y12KyNxj/Sb/iOE46ws+3mS1+MZca1wlHQFPsY/JU= -github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= -github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= -github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= +github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= +github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= 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= 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/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b h1:aUNXCGgukb4gtY99imuIeoh8Vr0GSwAlYxPAhqZrpFc= github.com/quasoft/memstore v0.0.0-20191010062613-2bce066d2b0b/go.mod h1:wTPjTepVu7uJBYgZ0SdWHQlIas582j6cn2jgk4DDdlg= +github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= +github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= +github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= +github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= @@ -177,41 +198,44 @@ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= -github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU= -github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY= +github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= github.com/wader/gormstore/v2 v2.0.3 h1:/29GWPauY8xZkpLnB8hsp+dZfP3ivA9fiDw1YVNTp6U= github.com/wader/gormstore/v2 v2.0.3/go.mod h1:sr3N3a8F1+PBc3fHoKaphFqDXLRJ9Oe6Yow0HxKFbbg= github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= -github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= -github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= -github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= -github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/xdg-go/scram v1.2.0 h1:bYKF2AEwG5rqd1BumT4gAnvwU/M9nBp2pTSxeZw7Wvs= +github.com/xdg-go/scram v1.2.0/go.mod h1:3dlrS0iBaWKYVt2ZfA4cj48umJZ+cAEbR6/SjLA88I8= github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= -github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= -github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a h1:fZHgsYlfvtyqToslyjUt3VOPF4J7aK/3MPcK7xp3PDk= -github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a/go.mod h1:ul22v+Nro/R083muKhosV54bj5niojjWZvU8xrevuH4= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM= +github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= -go.mongodb.org/mongo-driver v1.11.1 h1:QP0znIRTuL0jf1oBQoAoM0C6ZJfBK4kx0Uumtv1A7w8= -go.mongodb.org/mongo-driver v1.11.1/go.mod h1:s7p5vEtfbeR1gYi6pnj3c3/urpbLv2T5Sfd6Rp2HBB8= +go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ= +go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= +go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE= +go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0= 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.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= 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.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= @@ -219,21 +243,21 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +golang.org/x/arch v0.22.0 h1:c/Zle32i5ttqRXjdLyyHZESLD/bB90DCU1g9l/0YBDI= +golang.org/x/arch v0.22.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/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-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts= +golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= @@ -245,13 +269,12 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= -golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= +golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -267,9 +290,9 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k= +golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= 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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -280,8 +303,8 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8= +golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -296,20 +319,16 @@ golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= -google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= @@ -318,12 +337,12 @@ gorm.io/driver/mysql v1.4.0/go.mod h1:sSIebwZAVPiT+27jK9HIwvsqOGKx3YMPmrA3mBJR10 gorm.io/driver/postgres v1.4.1 h1:DutsKq2LK2Ag65q/+VygWth0/L4GAVOp+sCtg6WzZjs= gorm.io/driver/postgres v1.4.1/go.mod h1:whNfh5WhhHs96honoLjBAMwJGYEuA3m1hvgUbNXhPCw= gorm.io/driver/sqlite v1.4.1/go.mod h1:AKZZCAoFfOWHF7Nd685Iq8Uywc0i9sWJlzpoE/INzsw= -gorm.io/driver/sqlite v1.4.4 h1:gIufGoR0dQzjkyqDyYSCvsYR6fba1Gw5YKDqKeChxFc= -gorm.io/driver/sqlite v1.4.4/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI= +gorm.io/driver/sqlite v1.5.7 h1:8NvsrhP0ifM7LX9G4zPB97NwovUakUxc+2V2uuf3Z1I= +gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDah4= gorm.io/gorm v1.23.7/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.23.10/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= gorm.io/gorm v1.24.0/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= -gorm.io/gorm v1.24.5 h1:g6OPREKqqlWq4kh/3MCQbZKImeB9e6Xgc4zD+JgNZGE= -gorm.io/gorm v1.24.5/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA= +gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8= +gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= diff --git a/gorm/gorm.go b/gorm/gorm.go index 1f11649a..91d79b6f 100644 --- a/gorm/gorm.go +++ b/gorm/gorm.go @@ -26,5 +26,5 @@ type store struct { } func (s *store) Options(options sessions.Options) { - s.Store.SessionOpts = options.ToGorillaOptions() + s.SessionOpts = options.ToGorillaOptions() } diff --git a/gorm/gorm_test.go b/gorm/gorm_test.go index 4bbd01c9..f92b8e9a 100644 --- a/gorm/gorm_test.go +++ b/gorm/gorm_test.go @@ -1,4 +1,4 @@ -// +build go1.13 +//go:build go1.13 package gorm diff --git a/memcached/memcached_test.go b/memcached/memcached_test.go index cd8ae1ce..56e4b354 100644 --- a/memcached/memcached_test.go +++ b/memcached/memcached_test.go @@ -41,6 +41,10 @@ func TestMemcached_SessionMany(t *testing.T) { tester.Many(t, newStore) } +func TestMemcached_SessionManyStores(t *testing.T) { + tester.ManyStores(t, newStore) +} + var newBinaryStore = func(_ *testing.T) sessions.Store { store := NewMemcacheStore( mc.NewMC(memcachedTestServer, "", ""), "", []byte("secret")) @@ -70,3 +74,7 @@ func TestBinaryMemcached_SessionOptions(t *testing.T) { func TestBinaryMemcached_SessionMany(t *testing.T) { tester.Many(t, newBinaryStore) } + +func TestBinaryMemcached_SessionManyStores(t *testing.T) { + tester.ManyStores(t, newBinaryStore) +} diff --git a/memstore/memstore_test.go b/memstore/memstore_test.go index 045eab93..e824db77 100644 --- a/memstore/memstore_test.go +++ b/memstore/memstore_test.go @@ -35,3 +35,7 @@ func TestCookie_SessionOptions(t *testing.T) { func TestCookie_SessionMany(t *testing.T) { tester.Many(t, newStore) } + +func TestCookie_SessionManyStores(t *testing.T) { + tester.ManyStores(t, newStore) +} diff --git a/mongo/mongodriver/mongodriver.go b/mongo/mongodriver/mongodriver.go index bcac2ce4..357a5c97 100644 --- a/mongo/mongodriver/mongodriver.go +++ b/mongo/mongodriver/mongodriver.go @@ -1,14 +1,13 @@ package mongodriver import ( - "github.com/bos-hieu/mongostore" "github.com/gin-contrib/sessions" + + "github.com/laziness-coders/mongostore" "go.mongodb.org/mongo-driver/mongo" ) -var ( - _ sessions.Store = (*store)(nil) -) +var _ sessions.Store = (*store)(nil) func NewStore(c *mongo.Collection, maxAge int, ensureTTL bool, keyPairs ...[]byte) sessions.Store { return &store{mongostore.NewMongoStore(c, maxAge, ensureTTL, keyPairs...)} diff --git a/mongo/mongodriver/mongodriver_test.go b/mongo/mongodriver/mongodriver_test.go index dd225651..3a3a676e 100644 --- a/mongo/mongodriver/mongodriver_test.go +++ b/mongo/mongodriver/mongodriver_test.go @@ -16,15 +16,11 @@ const mongoTestServer = "mongodb://localhost:27017" var newStore = func(_ *testing.T) sessions.Store { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - client, err := mongo.NewClient(options.Client().ApplyURI(mongoTestServer)) + client, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoTestServer)) if err != nil { panic(err) } - if err := client.Connect(ctx); err != nil { - panic(err) - } - c := client.Database("test").Collection("sessions") return NewStore(c, 3600, true, []byte("secret")) } diff --git a/mongo/mongomgo/mongomgo.go b/mongo/mongomgo/mongomgo.go index b6a3e9f3..bbb777e6 100644 --- a/mongo/mongomgo/mongomgo.go +++ b/mongo/mongomgo/mongomgo.go @@ -6,9 +6,7 @@ import ( "github.com/kidstuff/mongostore" ) -var ( - _ sessions.Store = (*store)(nil) -) +var _ sessions.Store = (*store)(nil) func NewStore(c *mgo.Collection, maxAge int, ensureTTL bool, keyPairs ...[]byte) sessions.Store { return &store{mongostore.NewMongoStore(c, maxAge, ensureTTL, keyPairs...)} diff --git a/mongo/mongomgo/mongomgo_test.go b/mongo/mongomgo/mongomgo_test.go index 8a05a504..183ab44c 100644 --- a/mongo/mongomgo/mongomgo_test.go +++ b/mongo/mongomgo/mongomgo_test.go @@ -43,3 +43,7 @@ func TestMongoMGO_SessionOptions(t *testing.T) { func TestMongoMGO_SessionMany(t *testing.T) { tester.Many(t, newStore) } + +func TestMongo_SessionManyStores(t *testing.T) { + tester.ManyStores(t, newStore) +} diff --git a/postgres/postgres.go b/postgres/postgres.go index e506f893..04b8f9f7 100644 --- a/postgres/postgres.go +++ b/postgres/postgres.go @@ -2,6 +2,7 @@ package postgres import ( "database/sql" + "github.com/antonlindstrom/pgstore" "github.com/gin-contrib/sessions" ) diff --git a/postgres/postgres_test.go b/postgres/postgres_test.go index 4ec60513..12cb6214 100644 --- a/postgres/postgres_test.go +++ b/postgres/postgres_test.go @@ -2,12 +2,14 @@ package postgres import ( "database/sql" + "testing" + "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/tester" - "testing" ) -const postgresTestServer = "postgres://testuser:testpw@localhost:5432/testdb?sslmode=disable" +// test-only credentials for local CI +const postgresTestServer = "postgres://testuser:testpw@localhost:5432/testdb?sslmode=disable" //nolint:gosec var newStore = func(_ *testing.T) sessions.Store { db, err := sql.Open("postgres", postgresTestServer) @@ -46,3 +48,7 @@ func TestPostgres_SessionOptions(t *testing.T) { func TestPostgres_SessionMany(t *testing.T) { tester.Many(t, newStore) } + +func TestPostgres_SessionManyStores(t *testing.T) { + tester.ManyStores(t, newStore) +} diff --git a/redis/redis.go b/redis/redis.go index c70149d2..12a1bc2c 100644 --- a/redis/redis.go +++ b/redis/redis.go @@ -3,8 +3,9 @@ package redis import ( "errors" - "github.com/boj/redistore" "github.com/gin-contrib/sessions" + + "github.com/boj/redistore" "github.com/gomodule/redigo/redis" ) @@ -25,29 +26,47 @@ type Store interface { // // It is recommended to use an authentication key with 32 or 64 bytes. The encryption key, // if set, must be either 16, 24, or 32 bytes to select AES-128, AES-192, or AES-256 modes. -func NewStore(size int, network, address, password string, keyPairs ...[]byte) (Store, error) { - s, err := redistore.NewRediStore(size, network, address, password, keyPairs...) +func NewStore(size int, network, address, username, password string, keyPairs ...[]byte) (Store, error) { + s, err := redistore.NewRediStore(size, network, address, username, password, keyPairs...) if err != nil { return nil, err } return &store{s}, nil } -// NewStoreWithDB - like NewStore but accepts `DB` parameter to select -// redis DB instead of using the default one ("0") +// NewStoreWithDB creates a new Redis-based session store with the specified parameters. // -// Ref: https://godoc.org/github.com/boj/redistore#NewRediStoreWithDB -func NewStoreWithDB(size int, network, address, password, DB string, keyPairs ...[]byte) (Store, error) { - s, err := redistore.NewRediStoreWithDB(size, network, address, password, DB, keyPairs...) +// Parameters: +// - size: The maximum number of idle connections in the pool. +// - network: The network type (e.g., "tcp"). +// - address: The address of the Redis server (e.g., "localhost:6379"). +// - password: The password for the Redis server (if any). +// - DB: The Redis database to be selected after connecting. +// - keyPairs: A variadic list of byte slices used for authentication and encryption. +// +// Returns: +// - Store: The created session store. +// - error: An error if the store could not be created. +func NewStoreWithDB(size int, network, address, username, password, db string, keyPairs ...[]byte) (Store, error) { + s, err := redistore.NewRediStoreWithDB(size, network, address, username, password, db, keyPairs...) if err != nil { return nil, err } return &store{s}, nil } -// NewStoreWithPool instantiates a RediStore with a *redis.Pool passed in. +// NewStoreWithPool creates a new session store using a Redis connection pool. +// It takes a redis.Pool and an optional variadic list of key pairs for +// authentication and encryption of session data. +// +// Parameters: +// - pool: A redis.Pool object that manages a pool of Redis connections. +// - keyPairs: Optional variadic list of byte slices used for authentication +// and encryption of session data. // -// Ref: https://godoc.org/github.com/boj/redistore#NewRediStoreWithPool +// Returns: +// - Store: A new session store backed by Redis. +// - error: An error if the store could not be created. func NewStoreWithPool(pool *redis.Pool, keyPairs ...[]byte) (Store, error) { s, err := redistore.NewRediStoreWithPool(pool, keyPairs...) if err != nil { @@ -60,22 +79,38 @@ type store struct { *redistore.RediStore } -// GetRedisStore get the actual woking store. -// Ref: https://godoc.org/github.com/boj/redistore#RediStore -func GetRedisStore(s Store) (err error, rediStore *redistore.RediStore) { +// GetRedisStore retrieves the Redis store from the provided Store interface. +// It returns an error if the provided Store is not of the expected type. +// +// Parameters: +// - s: The Store interface from which to retrieve the Redis store. +// +// Returns: +// - err: An error if the provided Store is not of the expected type. +// - rediStore: The retrieved Redis store, or nil if there was an error. +func GetRedisStore(s Store) (rediStore *redistore.RediStore, err error) { realStore, ok := s.(*store) if !ok { err = errors.New("unable to get the redis store: Store isn't *store") - return + return nil, err } rediStore = realStore.RediStore - return + return rediStore, nil } -// SetKeyPrefix sets the key prefix in the redis database. +// SetKeyPrefix sets a key prefix for the given Redis store. +// It retrieves the Redis store from the provided Store interface and sets the key prefix. +// If there is an error retrieving the Redis store, it returns the error. +// +// Parameters: +// - s: The Store interface from which the Redis store will be retrieved. +// - prefix: The key prefix to be set for the Redis store. +// +// Returns: +// - error: An error if there is an issue retrieving the Redis store, otherwise nil. func SetKeyPrefix(s Store, prefix string) error { - err, rediStore := GetRedisStore(s) + rediStore, err := GetRedisStore(s) if err != nil { return err } diff --git a/redis/redis_test.go b/redis/redis_test.go index f0c01276..453026e2 100644 --- a/redis/redis_test.go +++ b/redis/redis_test.go @@ -10,7 +10,7 @@ import ( const redisTestServer = "localhost:6379" var newRedisStore = func(_ *testing.T) sessions.Store { - store, err := NewStore(10, "tcp", redisTestServer, "", []byte("secret")) + store, err := NewStore(10, "tcp", redisTestServer, "", "", []byte("secret")) if err != nil { panic(err) } @@ -41,10 +41,14 @@ func TestRedis_SessionMany(t *testing.T) { tester.Many(t, newRedisStore) } +func TestRedis_SessionManyStores(t *testing.T) { + tester.ManyStores(t, newRedisStore) +} + func TestGetRedisStore(t *testing.T) { t.Run("unmatched type", func(t *testing.T) { type store struct{ Store } - err, rediStore := GetRedisStore(store{}) + rediStore, err := GetRedisStore(store{}) if err == nil || rediStore != nil { t.Fail() } diff --git a/session_options_go1.10.go b/session_options_go1.10.go index 623473e8..dc4821ad 100644 --- a/session_options_go1.10.go +++ b/session_options_go1.10.go @@ -1,4 +1,4 @@ -// +build !go1.11 +//go:build !go1.11 package sessions diff --git a/session_options_go1.11.go b/session_options_go1.11.go index 02b2e5e7..324890c2 100644 --- a/session_options_go1.11.go +++ b/session_options_go1.11.go @@ -1,10 +1,11 @@ -// +build go1.11 +//go:build go1.11 package sessions import ( - gsessions "github.com/gorilla/sessions" "net/http" + + gsessions "github.com/gorilla/sessions" ) // Options stores configuration for a session or session store. diff --git a/sessions.go b/sessions.go index 0ef8ec41..d7914741 100644 --- a/sessions.go +++ b/sessions.go @@ -1,7 +1,7 @@ package sessions import ( - "log" + "log/slog" "net/http" "github.com/gin-gonic/gin" @@ -11,7 +11,7 @@ import ( const ( DefaultKey = "github.com/gin-contrib/sessions" - errorFormat = "[sessions] ERROR! %s\n" + errorFormat = "[sessions] ERROR!" ) type Store interface { @@ -46,6 +46,12 @@ type Session interface { Save() error } +// SessionStore named session stores allow multiple sessions with different store types +type SessionStore struct { + Name string + Store Store +} + func Sessions(name string, store Store) gin.HandlerFunc { return func(c *gin.Context) { s := &session{name, c.Request, store, nil, false, c.Writer} @@ -67,6 +73,18 @@ func SessionsMany(names []string, store Store) gin.HandlerFunc { } } +func SessionsManyStores(sessionStores []SessionStore) gin.HandlerFunc { + return func(c *gin.Context) { + sessions := make(map[string]Session, len(sessionStores)) + for _, sessionStore := range sessionStores { + sessions[sessionStore.Name] = &session{sessionStore.Name, c.Request, sessionStore.Store, nil, false, c.Writer} + } + c.Set(DefaultKey, sessions) + defer context.Clear(c.Request) + c.Next() + } +} + type session struct { name string request *http.Request @@ -131,7 +149,9 @@ func (s *session) Session() *sessions.Session { var err error s.session, err = s.store.Get(s.request, s.name) if err != nil { - log.Printf(errorFormat, err) + slog.Error(errorFormat, + "err", err, + ) } } return s.session diff --git a/tester/tester.go b/tester/tester.go index cecc913a..4bd1797e 100644 --- a/tester/tester.go +++ b/tester/tester.go @@ -4,6 +4,7 @@ package tester import ( + "context" "net/http" "net/http/httptest" "strings" @@ -15,13 +16,11 @@ import ( type storeFactory func(*testing.T) sessions.Store -const sessionName = "mysession" - -const ok = "ok" - -func init() { - gin.SetMode(gin.TestMode) -} +const ( + sessionName = "mysession" + ok = "ok" + testBarVal = "bar" +) func GetSet(t *testing.T, newStore storeFactory) { r := gin.Default() @@ -44,11 +43,11 @@ func GetSet(t *testing.T, newStore storeFactory) { }) res1 := httptest.NewRecorder() - req1, _ := http.NewRequest("GET", "/set", nil) + req1, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/set", nil) r.ServeHTTP(res1, req1) res2 := httptest.NewRecorder() - req2, _ := http.NewRequest("GET", "/get", nil) + req2, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/get", nil) copyCookies(req2, res1) r.ServeHTTP(res2, req2) } @@ -81,16 +80,16 @@ func DeleteKey(t *testing.T, newStore storeFactory) { }) res1 := httptest.NewRecorder() - req1, _ := http.NewRequest("GET", "/set", nil) + req1, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/set", nil) r.ServeHTTP(res1, req1) res2 := httptest.NewRecorder() - req2, _ := http.NewRequest("GET", "/delete", nil) + req2, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/delete", nil) copyCookies(req2, res1) r.ServeHTTP(res2, req2) res3 := httptest.NewRecorder() - req3, _ := http.NewRequest("GET", "/get", nil) + req3, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/get", nil) copyCookies(req3, res2) r.ServeHTTP(res3, req3) } @@ -128,16 +127,16 @@ func Flashes(t *testing.T, newStore storeFactory) { }) res1 := httptest.NewRecorder() - req1, _ := http.NewRequest("GET", "/set", nil) + req1, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/set", nil) r.ServeHTTP(res1, req1) res2 := httptest.NewRecorder() - req2, _ := http.NewRequest("GET", "/flash", nil) + req2, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/flash", nil) copyCookies(req2, res1) r.ServeHTTP(res2, req2) res3 := httptest.NewRecorder() - req3, _ := http.NewRequest("GET", "/check", nil) + req3, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/check", nil) copyCookies(req3, res2) r.ServeHTTP(res3, req3) } @@ -145,7 +144,7 @@ func Flashes(t *testing.T, newStore storeFactory) { func Clear(t *testing.T, newStore storeFactory) { data := map[string]string{ "key": "val", - "foo": "bar", + "foo": testBarVal, } r := gin.Default() store := newStore(t) @@ -173,11 +172,11 @@ func Clear(t *testing.T, newStore storeFactory) { }) res1 := httptest.NewRecorder() - req1, _ := http.NewRequest("GET", "/set", nil) + req1, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/set", nil) r.ServeHTTP(res1, req1) res2 := httptest.NewRecorder() - req2, _ := http.NewRequest("GET", "/check", nil) + req2, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/check", nil) copyCookies(req2, res1) r.ServeHTTP(res2, req2) } @@ -231,36 +230,43 @@ func Options(t *testing.T, newStore storeFactory) { testOptionSameSitego(t, r) res1 := httptest.NewRecorder() - req1, _ := http.NewRequest("GET", "/domain", nil) + req1, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/domain", nil) r.ServeHTTP(res1, req1) res2 := httptest.NewRecorder() - req2, _ := http.NewRequest("GET", "/path", nil) + req2, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/path", nil) r.ServeHTTP(res2, req2) res3 := httptest.NewRecorder() - req3, _ := http.NewRequest("GET", "/set", nil) + req3, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/set", nil) r.ServeHTTP(res3, req3) res4 := httptest.NewRecorder() - req4, _ := http.NewRequest("GET", "/expire", nil) + req4, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/expire", nil) r.ServeHTTP(res4, req4) res5 := httptest.NewRecorder() - req5, _ := http.NewRequest("GET", "/check", nil) + req5, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/check", nil) r.ServeHTTP(res5, req5) for _, c := range res1.Header().Values("Set-Cookie") { - s := strings.Split(c, ";") - if s[1] != " Path=/foo/bar/bat" { - t.Error("Error writing path with options:", s[1]) + s := strings.Split(c, "; ") + if len(s) < 2 { + t.Fatal("No Path=/foo/bar/batt found in options") + } + if s[1] != "Path=/foo/bar/bat" { + t.Fatal("Error writing path with options:", s[1]) } } for _, c := range res2.Header().Values("Set-Cookie") { - s := strings.Split(c, ";") - if s[1] != " Domain=localhost" { - t.Error("Error writing domain with options:", s[1]) + s := strings.Split(c, "; ") + if len(s) < 2 { + t.Fatal("No Domain=localhost found in options") + } + + if s[1] != "Domain=localhost" { + t.Fatal("Error writing domain with options:", s[1]) } } } @@ -277,7 +283,58 @@ func Many(t *testing.T, newStore storeFactory) { _ = sessionA.Save() sessionB := sessions.DefaultMany(c, "b") - sessionB.Set("foo", "bar") + sessionB.Set("foo", testBarVal) + _ = sessionB.Save() + c.String(http.StatusOK, ok) + }) + + r.GET("/get", func(c *gin.Context) { + sessionA := sessions.DefaultMany(c, "a") + if sessionA.Get("hello") != "world" { + t.Error("Session writing failed") + } + _ = sessionA.Save() + + sessionB := sessions.DefaultMany(c, "b") + if sessionB.Get("foo") != testBarVal { + t.Error("Session writing failed") + } + _ = sessionB.Save() + c.String(http.StatusOK, ok) + }) + + res1 := httptest.NewRecorder() + req1, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/set", nil) + r.ServeHTTP(res1, req1) + + res2 := httptest.NewRecorder() + req2, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/get", nil) + header := "" + for _, x := range res1.Header()["Set-Cookie"] { + header += strings.Split(x, ";")[0] + "; \n" + } + req2.Header.Set("Cookie", header) + r.ServeHTTP(res2, req2) +} + +func ManyStores(t *testing.T, newStore storeFactory) { + r := gin.Default() + + store := newStore(t) + sessionStores := []sessions.SessionStore{ + {Name: "a", Store: store}, + {Name: "b", Store: store}, + } + + r.Use(sessions.SessionsManyStores(sessionStores)) + + r.GET("/set", func(c *gin.Context) { + sessionA := sessions.DefaultMany(c, "a") + sessionA.Set("hello", "world") + _ = sessionA.Save() + + sessionB := sessions.DefaultMany(c, "b") + sessionB.Set("foo", testBarVal) _ = sessionB.Save() c.String(http.StatusOK, ok) }) @@ -290,7 +347,7 @@ func Many(t *testing.T, newStore storeFactory) { _ = sessionA.Save() sessionB := sessions.DefaultMany(c, "b") - if sessionB.Get("foo") != "bar" { + if sessionB.Get("foo") != testBarVal { t.Error("Session writing failed") } _ = sessionB.Save() @@ -298,11 +355,11 @@ func Many(t *testing.T, newStore storeFactory) { }) res1 := httptest.NewRecorder() - req1, _ := http.NewRequest("GET", "/set", nil) + req1, _ := http.NewRequestWithContext(context.Background(), "GET", "/set", nil) r.ServeHTTP(res1, req1) res2 := httptest.NewRecorder() - req2, _ := http.NewRequest("GET", "/get", nil) + req2, _ := http.NewRequestWithContext(context.Background(), "GET", "/get", nil) header := "" for _, x := range res1.Header()["Set-Cookie"] { header += strings.Split(x, ";")[0] + "; \n" diff --git a/tester/tester_options_samesite_go1.10.go b/tester/tester_options_samesite_go1.10.go index 2aa00d88..928ea57c 100644 --- a/tester/tester_options_samesite_go1.10.go +++ b/tester/tester_options_samesite_go1.10.go @@ -1,4 +1,4 @@ -// +build !go1.11 +//go:build !go1.11 package tester diff --git a/tester/tester_options_samesite_go1.11.go b/tester/tester_options_samesite_go1.11.go index 5e7aff8e..9527823e 100644 --- a/tester/tester_options_samesite_go1.11.go +++ b/tester/tester_options_samesite_go1.11.go @@ -1,8 +1,9 @@ -// +build go1.11 +//go:build go1.11 package tester import ( + "context" "net/http" "net/http/httptest" "strings" @@ -24,11 +25,14 @@ func testOptionSameSitego(t *testing.T, r *gin.Engine) { }) res3 := httptest.NewRecorder() - req3, _ := http.NewRequest("GET", "/sameSite", nil) + req3, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "/sameSite", nil) r.ServeHTTP(res3, req3) - s := strings.Split(res3.Header().Get("Set-Cookie"), ";") - if s[1] != " SameSite=Strict" { - t.Error("Error writing samesite with options:", s[1]) + s := strings.Split(res3.Header().Get("Set-Cookie"), "; ") + if len(s) < 2 { + t.Fatal("No SameSite=Strict found in options") + } + if s[1] != "SameSite=Strict" { + t.Fatal("Error writing samesite with options:", s[1]) } }