Compare commits
7 Commits
1ae9e0120e
...
472224ba69
Author | SHA1 | Date | |
---|---|---|---|
472224ba69 | |||
26b87f84ea | |||
05a4e3437b | |||
ea2979f06f | |||
ff82ab89a9 | |||
a6cb80ab75 | |||
02f5e24c6f |
10
.drone.yml
10
.drone.yml
|
@ -5,7 +5,7 @@ name: test
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: test
|
- name: test
|
||||||
image: golang:1.19
|
image: golang:1.20
|
||||||
environment:
|
environment:
|
||||||
TESTS_DB_DSN: postgres://postgres:sessions@database:5432/sessions?sslmode=disable
|
TESTS_DB_DSN: postgres://postgres:sessions@database:5432/sessions?sslmode=disable
|
||||||
commands:
|
commands:
|
||||||
|
@ -33,7 +33,7 @@ name: check-go-mod
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: check go.mod
|
- name: check go.mod
|
||||||
image: golang:1.19
|
image: golang:1.20
|
||||||
commands:
|
commands:
|
||||||
- make generate
|
- make generate
|
||||||
- go mod tidy
|
- go mod tidy
|
||||||
|
@ -76,7 +76,7 @@ platform:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: govulncheck
|
- name: govulncheck
|
||||||
image: golang:1.19
|
image: golang:1.20
|
||||||
commands:
|
commands:
|
||||||
- make generate
|
- make generate
|
||||||
- go install golang.org/x/vuln/cmd/govulncheck@latest
|
- go install golang.org/x/vuln/cmd/govulncheck@latest
|
||||||
|
@ -157,7 +157,7 @@ name: deploy
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: deploy-k8s
|
- name: deploy-k8s
|
||||||
image: alpine/k8s:1.25.5
|
image: alpine/k8s:1.25.6
|
||||||
environment:
|
environment:
|
||||||
KUBECONFIG:
|
KUBECONFIG:
|
||||||
from_secret: kubeconfig
|
from_secret: kubeconfig
|
||||||
|
@ -175,6 +175,6 @@ depends_on:
|
||||||
- manifest
|
- manifest
|
||||||
---
|
---
|
||||||
kind: signature
|
kind: signature
|
||||||
hmac: a91c4d377027890d9386c201a161c65f386b942b775c55e0d3c0b6f223bf1a01
|
hmac: e7d25bfdf6996b87a21de714bd52fa5317e192022f254a2813953673af4d5edd
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM golang:1.19 as builder
|
FROM golang:1.20 as builder
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY go.mod go.sum ./
|
COPY go.mod go.sum ./
|
||||||
RUN go mod download
|
RUN go mod download
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM golang:1.19.5-alpine3.17 as builder
|
FROM golang:1.20.0-alpine3.17 as builder
|
||||||
|
|
||||||
WORKDIR /sessions
|
WORKDIR /sessions
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,6 @@ import (
|
||||||
//
|
//
|
||||||
//nolint:tparallel
|
//nolint:tparallel
|
||||||
func TestParse(t *testing.T) {
|
func TestParse(t *testing.T) {
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
input string
|
input string
|
||||||
|
|
|
@ -51,11 +51,7 @@ func New() *cli.Command {
|
||||||
_ = db.Close()
|
_ = db.Close()
|
||||||
}()
|
}()
|
||||||
|
|
||||||
srv, err := newServer(serverConfig{
|
srv, err := newServer(logger, db)
|
||||||
appVersion: c.App.Version,
|
|
||||||
logger: logger,
|
|
||||||
db: db,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("newServer: %w", err)
|
return fmt.Errorf("newServer: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -75,22 +71,16 @@ func New() *cli.Command {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type serverConfig struct {
|
func newServer(logger *zap.Logger, db *bun.DB) (*http.Server, error) {
|
||||||
appVersion string
|
|
||||||
logger *zap.Logger
|
|
||||||
db *bun.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
func newServer(cfg serverConfig) (*http.Server, error) {
|
|
||||||
apiCfg, err := newAPIConfig()
|
apiCfg, err := newAPIConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("newAPIConfig: %w", err)
|
return nil, fmt.Errorf("newAPIConfig: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// repos
|
// repos
|
||||||
userRepo := bundb.NewUser(cfg.db)
|
userRepo := bundb.NewUser(db)
|
||||||
apiKeyRepo := bundb.NewAPIKey(cfg.db)
|
apiKeyRepo := bundb.NewAPIKey(db)
|
||||||
sessionRepo := bundb.NewSession(cfg.db)
|
sessionRepo := bundb.NewSession(db)
|
||||||
|
|
||||||
// services
|
// services
|
||||||
userSvc := service.NewUser(userRepo)
|
userSvc := service.NewUser(userRepo)
|
||||||
|
@ -99,24 +89,24 @@ func newServer(cfg serverConfig) (*http.Server, error) {
|
||||||
|
|
||||||
// router
|
// router
|
||||||
r := chi.NewRouter()
|
r := chi.NewRouter()
|
||||||
r.Use(getChiMiddlewares(cfg.logger)...)
|
r.Use(getMiddlewares(logger)...)
|
||||||
r.Mount(metaEndpointsPrefix, meta.NewRouter([]meta.Checker{bundb.NewChecker(cfg.db)}))
|
r.Mount(metaEndpointsPrefix, meta.New(bundb.NewChecker(db)))
|
||||||
r.Mount("/api", rest.NewRouter(rest.RouterConfig{
|
r.Mount("/api", rest.New(
|
||||||
APIKeyVerifier: apiKeySvc,
|
apiKeySvc,
|
||||||
SessionService: sessionSvc,
|
sessionSvc,
|
||||||
CORS: rest.CORSConfig{
|
rest.WithCORSConfig(rest.CORSConfig{
|
||||||
Enabled: apiCfg.CORSEnabled,
|
Enabled: apiCfg.CORSEnabled,
|
||||||
AllowedOrigins: apiCfg.CORSAllowedOrigins,
|
AllowedOrigins: apiCfg.CORSAllowedOrigins,
|
||||||
AllowedMethods: apiCfg.CORSAllowedMethods,
|
AllowedMethods: apiCfg.CORSAllowedMethods,
|
||||||
AllowCredentials: apiCfg.CORSAllowCredentials,
|
AllowCredentials: apiCfg.CORSAllowCredentials,
|
||||||
MaxAge: int(apiCfg.CORSMaxAge),
|
MaxAge: int(apiCfg.CORSMaxAge),
|
||||||
},
|
}),
|
||||||
Swagger: rest.SwaggerConfig{
|
rest.WithSwaggerConfig(rest.SwaggerConfig{
|
||||||
Enabled: apiCfg.SwaggerEnabled,
|
Enabled: apiCfg.SwaggerEnabled,
|
||||||
Host: apiCfg.SwaggerHost,
|
Host: apiCfg.SwaggerHost,
|
||||||
Schemes: apiCfg.SwaggerSchemes,
|
Schemes: apiCfg.SwaggerSchemes,
|
||||||
},
|
}),
|
||||||
}))
|
))
|
||||||
|
|
||||||
return &http.Server{
|
return &http.Server{
|
||||||
Addr: ":" + defaultPort,
|
Addr: ":" + defaultPort,
|
||||||
|
@ -147,7 +137,7 @@ func newAPIConfig() (apiConfig, error) {
|
||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getChiMiddlewares(logger *zap.Logger) chi.Middlewares {
|
func getMiddlewares(logger *zap.Logger) chi.Middlewares {
|
||||||
return chi.Middlewares{
|
return chi.Middlewares{
|
||||||
middleware.RealIP,
|
middleware.RealIP,
|
||||||
chizap.Logger(logger, chizap.WithFilter(omitMetaEndpoints)),
|
chizap.Logger(logger, chizap.WithFilter(omitMetaEndpoints)),
|
||||||
|
|
14
go.mod
14
go.mod
|
@ -1,9 +1,9 @@
|
||||||
module gitea.dwysokinski.me/twhelp/sessions
|
module gitea.dwysokinski.me/twhelp/sessions
|
||||||
|
|
||||||
go 1.19
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
gitea.dwysokinski.me/Kichiyaki/chizap v0.2.1
|
gitea.dwysokinski.me/Kichiyaki/chizap v0.3.0
|
||||||
github.com/cenkalti/backoff/v4 v4.2.0
|
github.com/cenkalti/backoff/v4 v4.2.0
|
||||||
github.com/go-chi/chi/v5 v5.0.8
|
github.com/go-chi/chi/v5 v5.0.8
|
||||||
github.com/go-chi/cors v1.2.1
|
github.com/go-chi/cors v1.2.1
|
||||||
|
@ -15,11 +15,11 @@ require (
|
||||||
github.com/stretchr/testify v1.8.1
|
github.com/stretchr/testify v1.8.1
|
||||||
github.com/swaggo/http-swagger v1.3.3
|
github.com/swaggo/http-swagger v1.3.3
|
||||||
github.com/swaggo/swag v1.8.10
|
github.com/swaggo/swag v1.8.10
|
||||||
github.com/uptrace/bun v1.1.10
|
github.com/uptrace/bun v1.1.11
|
||||||
github.com/uptrace/bun/dbfixture v1.1.10
|
github.com/uptrace/bun/dbfixture v1.1.11
|
||||||
github.com/uptrace/bun/dialect/pgdialect v1.1.10
|
github.com/uptrace/bun/dialect/pgdialect v1.1.11
|
||||||
github.com/uptrace/bun/driver/pgdriver v1.1.10
|
github.com/uptrace/bun/driver/pgdriver v1.1.11
|
||||||
github.com/urfave/cli/v2 v2.23.7
|
github.com/urfave/cli/v2 v2.24.2
|
||||||
go.uber.org/zap v1.24.0
|
go.uber.org/zap v1.24.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
24
go.sum
24
go.sum
|
@ -1,5 +1,5 @@
|
||||||
gitea.dwysokinski.me/Kichiyaki/chizap v0.2.1 h1:h1p7YvpKvGsFYDwV5L4xbq9VT5czWIBa5x88bl8X0nU=
|
gitea.dwysokinski.me/Kichiyaki/chizap v0.3.0 h1:se+wHeMGRp28dLtSC7XuXZJtxXYqPAEcmJj0gT0tthE=
|
||||||
gitea.dwysokinski.me/Kichiyaki/chizap v0.2.1/go.mod h1:q+HrVxr1rf95wyuSTBt4Sa54UcEysXXLfu3eHRdJpBU=
|
gitea.dwysokinski.me/Kichiyaki/chizap v0.3.0/go.mod h1:VMCCIdwFB8X03qS1eWKaiJgXcU2o8Hs3zn1NwcPL+iE=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
|
@ -142,17 +142,17 @@ github.com/swaggo/swag v1.8.8/go.mod h1:ezQVUUhly8dludpVk+/PuwJWvLLanB13ygV5Pr9e
|
||||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
|
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
|
||||||
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
|
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
|
||||||
github.com/uptrace/bun v1.1.10 h1:wx80lg32mWlOV1gNvmPTbR9znt6A2fYvvURzU5dzSPE=
|
github.com/uptrace/bun v1.1.11 h1:PVT+DHdLX13tIJaBoT0tkjh1TOWOybW/pz3TKiOB9lo=
|
||||||
github.com/uptrace/bun v1.1.10/go.mod h1:pOWJSVU+W0jp3+cbn/TtHdcG/h+QxagECw4EYdKiaSw=
|
github.com/uptrace/bun v1.1.11/go.mod h1:ysoB7l3gioKLBaZH9wKuJAoeBiOthb/hTyKdbXKcaxg=
|
||||||
github.com/uptrace/bun/dbfixture v1.1.10 h1:fjxGQ7CFoIcbfBp3sAg3R6Ee4xaAYGgMTLMY2VergWE=
|
github.com/uptrace/bun/dbfixture v1.1.11 h1:kYiwydXAMwLYKDjTqB7GhguribLfJpWN/VIraoIu1fc=
|
||||||
github.com/uptrace/bun/dbfixture v1.1.10/go.mod h1:cYs6r9hGlgnrh8mW0HYkhso3GMpP2/aY/FFQ45bj3Qw=
|
github.com/uptrace/bun/dbfixture v1.1.11/go.mod h1:tqtA92QYGFpLdhF0fh94Q/tIoocB2q9Zn9mOKSoXMSs=
|
||||||
github.com/uptrace/bun/dialect/pgdialect v1.1.10 h1:H25ieb5OJV5ywvKvswF++wMTnePRaGRiSNkYCRXrQxc=
|
github.com/uptrace/bun/dialect/pgdialect v1.1.11 h1:z1CLRQiYtTX1Usn2OEF7EtOBYeTFJiNdTgLuXE+AZZs=
|
||||||
github.com/uptrace/bun/dialect/pgdialect v1.1.10/go.mod h1:leDSw/IC70/GYPIU3zC8fkOZpJaJ28f51OMT1VnZiY8=
|
github.com/uptrace/bun/dialect/pgdialect v1.1.11/go.mod h1:orzsx6UwNnSaTTELzLqc/XiWrR4k0Smid8Bchdg0mk4=
|
||||||
github.com/uptrace/bun/driver/pgdriver v1.1.10 h1:xmabc3eG5rz8FadFF3GrQiGs5XvXlz6CJUMZhne+1sM=
|
github.com/uptrace/bun/driver/pgdriver v1.1.11 h1:0oKNY3cBuIs6wHCJP2IpUw5wPoeUa8oIDEvIdei+sDI=
|
||||||
github.com/uptrace/bun/driver/pgdriver v1.1.10/go.mod h1:krWrOAzJmroYDySsA6oNsJEVUmKl+ZBWLkGHphXUxqI=
|
github.com/uptrace/bun/driver/pgdriver v1.1.11/go.mod h1:c5x3/2B63Vw876N1GjWJbqQOE3k68+8abMc428PKG18=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli/v2 v2.23.7 h1:YHDQ46s3VghFHFf1DdF+Sh7H4RqhcM+t0TmZRJx4oJY=
|
github.com/urfave/cli/v2 v2.24.2 h1:q1VA+ofZ8SWfEKB9xXHUD4QZaeI9e+ItEqSbfH2JBXk=
|
||||||
github.com/urfave/cli/v2 v2.23.7/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
|
github.com/urfave/cli/v2 v2.24.2/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
|
||||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||||
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
|
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
|
||||||
|
|
|
@ -82,6 +82,7 @@ func TestNewCreateAPIKeyParams(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, tt.keyName, params.Name())
|
||||||
assert.Equal(t, tt.key, params.Key())
|
assert.Equal(t, tt.key, params.Key())
|
||||||
assert.Equal(t, tt.userID, params.UserID())
|
assert.Equal(t, tt.userID, params.UserID())
|
||||||
})
|
})
|
||||||
|
|
|
@ -21,7 +21,7 @@ type Checker interface {
|
||||||
Check(ctx context.Context) error
|
Check(ctx context.Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRouter(checkers []Checker) *chi.Mux {
|
func New(checkers ...Checker) *chi.Mux {
|
||||||
router := chi.NewRouter()
|
router := chi.NewRouter()
|
||||||
|
|
||||||
router.Get("/livez", func(w http.ResponseWriter, r *http.Request) {
|
router.Get("/livez", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
|
@ -20,7 +20,7 @@ func TestLivez(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
meta.NewRouter(nil).ServeHTTP(rr, httptest.NewRequest(http.MethodGet, "/livez", nil))
|
meta.New(nil).ServeHTTP(rr, httptest.NewRequest(http.MethodGet, "/livez", nil))
|
||||||
|
|
||||||
assert.Equal(t, http.StatusNoContent, rr.Code)
|
assert.Equal(t, http.StatusNoContent, rr.Code)
|
||||||
assert.Equal(t, 0, rr.Body.Len())
|
assert.Equal(t, 0, rr.Body.Len())
|
||||||
|
@ -99,7 +99,7 @@ func TestReadyz(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
rr := httptest.NewRecorder()
|
rr := httptest.NewRecorder()
|
||||||
meta.NewRouter(tt.checkers).ServeHTTP(rr, httptest.NewRequest(http.MethodGet, "/readyz", nil))
|
meta.New(tt.checkers...).ServeHTTP(rr, httptest.NewRequest(http.MethodGet, "/readyz", nil))
|
||||||
|
|
||||||
assert.Equal(t, tt.expectedStatus, rr.Code)
|
assert.Equal(t, tt.expectedStatus, rr.Code)
|
||||||
assert.Equal(t, "application/json", rr.Header().Get("Content-Type"))
|
assert.Equal(t, "application/json", rr.Header().Get("Content-Type"))
|
||||||
|
|
42
internal/router/rest/config.go
Normal file
42
internal/router/rest/config.go
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
package rest
|
||||||
|
|
||||||
|
type CORSConfig struct {
|
||||||
|
Enabled bool
|
||||||
|
AllowedOrigins []string
|
||||||
|
AllowedMethods []string
|
||||||
|
AllowCredentials bool
|
||||||
|
MaxAge int
|
||||||
|
}
|
||||||
|
|
||||||
|
type SwaggerConfig struct {
|
||||||
|
Enabled bool
|
||||||
|
Host string
|
||||||
|
Schemes []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Option func(cfg *config)
|
||||||
|
|
||||||
|
func WithCORSConfig(cors CORSConfig) Option {
|
||||||
|
return func(cfg *config) {
|
||||||
|
cfg.cors = cors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func WithSwaggerConfig(swagger SwaggerConfig) Option {
|
||||||
|
return func(cfg *config) {
|
||||||
|
cfg.swagger = swagger
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type config struct {
|
||||||
|
cors CORSConfig
|
||||||
|
swagger SwaggerConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func newConfig(opts ...Option) *config {
|
||||||
|
cfg := &config{}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(cfg)
|
||||||
|
}
|
||||||
|
return cfg
|
||||||
|
}
|
|
@ -15,43 +15,28 @@ import (
|
||||||
|
|
||||||
//go:generate counterfeiter -generate
|
//go:generate counterfeiter -generate
|
||||||
|
|
||||||
type CORSConfig struct {
|
func New(
|
||||||
Enabled bool
|
apiKeyVerifier APIKeyVerifier,
|
||||||
AllowedOrigins []string
|
sessionSvc SessionService,
|
||||||
AllowedMethods []string
|
opts ...Option,
|
||||||
AllowCredentials bool
|
) *chi.Mux {
|
||||||
MaxAge int
|
cfg := newConfig(opts...)
|
||||||
}
|
|
||||||
|
|
||||||
type SwaggerConfig struct {
|
|
||||||
Enabled bool
|
|
||||||
Host string
|
|
||||||
Schemes []string
|
|
||||||
}
|
|
||||||
|
|
||||||
type RouterConfig struct {
|
|
||||||
APIKeyVerifier APIKeyVerifier
|
|
||||||
SessionService SessionService
|
|
||||||
CORS CORSConfig
|
|
||||||
Swagger SwaggerConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRouter(cfg RouterConfig) *chi.Mux {
|
|
||||||
// handlers
|
// handlers
|
||||||
uh := userHandler{}
|
uh := userHandler{}
|
||||||
sh := sessionHandler{
|
sh := sessionHandler{
|
||||||
svc: cfg.SessionService,
|
svc: sessionSvc,
|
||||||
}
|
}
|
||||||
|
|
||||||
router := chi.NewRouter()
|
router := chi.NewRouter()
|
||||||
|
|
||||||
if cfg.CORS.Enabled {
|
if cfg.cors.Enabled {
|
||||||
router.Use(cors.Handler(cors.Options{
|
router.Use(cors.Handler(cors.Options{
|
||||||
AllowedOrigins: cfg.CORS.AllowedOrigins,
|
AllowedOrigins: cfg.cors.AllowedOrigins,
|
||||||
AllowCredentials: cfg.CORS.AllowCredentials,
|
AllowCredentials: cfg.cors.AllowCredentials,
|
||||||
AllowedMethods: cfg.CORS.AllowedMethods,
|
AllowedMethods: cfg.cors.AllowedMethods,
|
||||||
AllowedHeaders: []string{"Origin", "Content-Length", "Content-Type", "X-API-Key"},
|
AllowedHeaders: []string{"Origin", "Content-Length", "Content-Type", "X-API-Key"},
|
||||||
MaxAge: cfg.CORS.MaxAge,
|
MaxAge: cfg.cors.MaxAge,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,17 +44,17 @@ func NewRouter(cfg RouterConfig) *chi.Mux {
|
||||||
router.MethodNotAllowed(methodNotAllowedHandler)
|
router.MethodNotAllowed(methodNotAllowedHandler)
|
||||||
|
|
||||||
router.Route("/v1", func(r chi.Router) {
|
router.Route("/v1", func(r chi.Router) {
|
||||||
if cfg.Swagger.Enabled {
|
if cfg.swagger.Enabled {
|
||||||
if cfg.Swagger.Host != "" {
|
if cfg.swagger.Host != "" {
|
||||||
docs.SwaggerInfo.Host = cfg.Swagger.Host
|
docs.SwaggerInfo.Host = cfg.swagger.Host
|
||||||
}
|
}
|
||||||
if len(cfg.Swagger.Schemes) > 0 {
|
if len(cfg.swagger.Schemes) > 0 {
|
||||||
docs.SwaggerInfo.Schemes = cfg.Swagger.Schemes
|
docs.SwaggerInfo.Schemes = cfg.swagger.Schemes
|
||||||
}
|
}
|
||||||
r.Get("/swagger/*", httpSwagger.Handler())
|
r.Get("/swagger/*", httpSwagger.Handler())
|
||||||
}
|
}
|
||||||
|
|
||||||
authMw := authMiddleware(cfg.APIKeyVerifier)
|
authMw := authMiddleware(apiKeyVerifier)
|
||||||
|
|
||||||
r.With(authMw).Get("/user", uh.getCurrent)
|
r.With(authMw).Get("/user", uh.getCurrent)
|
||||||
r.With(authMw).Put("/user/sessions/{serverKey}", sh.createOrUpdate)
|
r.With(authMw).Put("/user/sessions/{serverKey}", sh.createOrUpdate)
|
||||||
|
|
|
@ -21,7 +21,7 @@ import (
|
||||||
func TestRouteNotFound(t *testing.T) {
|
func TestRouteNotFound(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
resp := doRequest(rest.NewRouter(rest.RouterConfig{}), http.MethodGet, "/v1/"+uuid.NewString(), "", nil)
|
resp := doRequest(newRouter(), http.MethodGet, "/v1/"+uuid.NewString(), "", nil)
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
assertJSONResponse(t, resp, http.StatusNotFound, &model.ErrorResp{
|
assertJSONResponse(t, resp, http.StatusNotFound, &model.ErrorResp{
|
||||||
Error: model.APIError{
|
Error: model.APIError{
|
||||||
|
@ -34,11 +34,10 @@ func TestRouteNotFound(t *testing.T) {
|
||||||
func TestMethodNotAllowed(t *testing.T) {
|
func TestMethodNotAllowed(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
resp := doRequest(rest.NewRouter(rest.RouterConfig{
|
router := newRouter(withOption(rest.WithSwaggerConfig(rest.SwaggerConfig{
|
||||||
Swagger: rest.SwaggerConfig{
|
Enabled: true,
|
||||||
Enabled: true,
|
})))
|
||||||
},
|
resp := doRequest(router, http.MethodPost, "/v1/swagger/index.html", "", nil)
|
||||||
}), http.MethodPost, "/v1/swagger/index.html", "", nil)
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
assertJSONResponse(t, resp, http.StatusMethodNotAllowed, &model.ErrorResp{
|
assertJSONResponse(t, resp, http.StatusMethodNotAllowed, &model.ErrorResp{
|
||||||
Error: model.APIError{
|
Error: model.APIError{
|
||||||
|
@ -127,16 +126,14 @@ func TestCORS(t *testing.T) {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
r := rest.NewRouter(rest.RouterConfig{
|
router := newRouter(withOption(rest.WithCORSConfig(tt.cfg)))
|
||||||
CORS: tt.cfg,
|
|
||||||
})
|
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodOptions, "/url", nil)
|
req := httptest.NewRequest(http.MethodOptions, "/url", nil)
|
||||||
for k, v := range tt.reqHeaders {
|
for k, v := range tt.reqHeaders {
|
||||||
req.Header.Set(k, v)
|
req.Header.Set(k, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := doCustomRequest(r, req)
|
resp := doCustomRequest(router, req)
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
assert.Equal(t, tt.expectedStatus, resp.StatusCode)
|
assert.Equal(t, tt.expectedStatus, resp.StatusCode)
|
||||||
assert.Len(t, resp.Header, len(tt.resHeaders))
|
assert.Len(t, resp.Header, len(tt.resHeaders))
|
||||||
|
@ -166,11 +163,9 @@ func TestSwagger(t *testing.T) {
|
||||||
expectedContentType: "application/json; charset=utf-8",
|
expectedContentType: "application/json; charset=utf-8",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
router := rest.NewRouter(rest.RouterConfig{
|
router := newRouter(withOption(rest.WithSwaggerConfig(rest.SwaggerConfig{
|
||||||
Swagger: rest.SwaggerConfig{
|
Enabled: true,
|
||||||
Enabled: true,
|
})))
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
tt := tt
|
tt := tt
|
||||||
|
@ -186,6 +181,40 @@ func TestSwagger(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type routerConfig struct {
|
||||||
|
apiKeyVerifier rest.APIKeyVerifier
|
||||||
|
sessionSvc rest.SessionService
|
||||||
|
opts []rest.Option
|
||||||
|
}
|
||||||
|
|
||||||
|
type routerOption func(cfg *routerConfig)
|
||||||
|
|
||||||
|
func withSessionService(svc rest.SessionService) routerOption {
|
||||||
|
return func(cfg *routerConfig) {
|
||||||
|
cfg.sessionSvc = svc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func withAPIKeyVerifier(svc rest.APIKeyVerifier) routerOption {
|
||||||
|
return func(cfg *routerConfig) {
|
||||||
|
cfg.apiKeyVerifier = svc
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func withOption(opt rest.Option) routerOption {
|
||||||
|
return func(cfg *routerConfig) {
|
||||||
|
cfg.opts = append(cfg.opts, opt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRouter(opts ...routerOption) chi.Router {
|
||||||
|
cfg := &routerConfig{}
|
||||||
|
for _, opt := range opts {
|
||||||
|
opt(cfg)
|
||||||
|
}
|
||||||
|
return rest.New(cfg.apiKeyVerifier, cfg.sessionSvc, cfg.opts...)
|
||||||
|
}
|
||||||
|
|
||||||
func doRequest(mux chi.Router, method, target, apiKey string, body io.Reader) *http.Response {
|
func doRequest(mux chi.Router, method, target, apiKey string, body io.Reader) *http.Response {
|
||||||
req := httptest.NewRequest(method, target, body)
|
req := httptest.NewRequest(method, target, body)
|
||||||
if apiKey != "" {
|
if apiKey != "" {
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gitea.dwysokinski.me/twhelp/sessions/internal/domain"
|
"gitea.dwysokinski.me/twhelp/sessions/internal/domain"
|
||||||
"gitea.dwysokinski.me/twhelp/sessions/internal/router/rest"
|
|
||||||
"gitea.dwysokinski.me/twhelp/sessions/internal/router/rest/internal/mock"
|
"gitea.dwysokinski.me/twhelp/sessions/internal/router/rest/internal/mock"
|
||||||
"gitea.dwysokinski.me/twhelp/sessions/internal/router/rest/internal/model"
|
"gitea.dwysokinski.me/twhelp/sessions/internal/router/rest/internal/model"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
@ -163,10 +162,7 @@ func TestSession_createOrUpdate(t *testing.T) {
|
||||||
sessionSvc := &mock.FakeSessionService{}
|
sessionSvc := &mock.FakeSessionService{}
|
||||||
tt.setup(apiKeySvc, sessionSvc)
|
tt.setup(apiKeySvc, sessionSvc)
|
||||||
|
|
||||||
router := rest.NewRouter(rest.RouterConfig{
|
router := newRouter(withAPIKeyVerifier(apiKeySvc), withSessionService(sessionSvc))
|
||||||
APIKeyVerifier: apiKeySvc,
|
|
||||||
SessionService: sessionSvc,
|
|
||||||
})
|
|
||||||
|
|
||||||
resp := doRequest(
|
resp := doRequest(
|
||||||
router,
|
router,
|
||||||
|
@ -309,10 +305,7 @@ func TestSession_getCurrentUser(t *testing.T) {
|
||||||
sessionSvc := &mock.FakeSessionService{}
|
sessionSvc := &mock.FakeSessionService{}
|
||||||
tt.setup(apiKeySvc, sessionSvc)
|
tt.setup(apiKeySvc, sessionSvc)
|
||||||
|
|
||||||
router := rest.NewRouter(rest.RouterConfig{
|
router := newRouter(withAPIKeyVerifier(apiKeySvc), withSessionService(sessionSvc))
|
||||||
APIKeyVerifier: apiKeySvc,
|
|
||||||
SessionService: sessionSvc,
|
|
||||||
})
|
|
||||||
|
|
||||||
resp := doRequest(router, http.MethodGet, "/v1/user/sessions/"+tt.serverKey, tt.apiKey, nil)
|
resp := doRequest(router, http.MethodGet, "/v1/user/sessions/"+tt.serverKey, tt.apiKey, nil)
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gitea.dwysokinski.me/twhelp/sessions/internal/domain"
|
"gitea.dwysokinski.me/twhelp/sessions/internal/domain"
|
||||||
"gitea.dwysokinski.me/twhelp/sessions/internal/router/rest"
|
|
||||||
"gitea.dwysokinski.me/twhelp/sessions/internal/router/rest/internal/mock"
|
"gitea.dwysokinski.me/twhelp/sessions/internal/router/rest/internal/mock"
|
||||||
"gitea.dwysokinski.me/twhelp/sessions/internal/router/rest/internal/model"
|
"gitea.dwysokinski.me/twhelp/sessions/internal/router/rest/internal/model"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
@ -105,9 +104,7 @@ func TestUser_getAuthenticated(t *testing.T) {
|
||||||
apiKeySvc := &mock.FakeAPIKeyVerifier{}
|
apiKeySvc := &mock.FakeAPIKeyVerifier{}
|
||||||
tt.setup(apiKeySvc)
|
tt.setup(apiKeySvc)
|
||||||
|
|
||||||
router := rest.NewRouter(rest.RouterConfig{
|
router := newRouter(withAPIKeyVerifier(apiKeySvc))
|
||||||
APIKeyVerifier: apiKeySvc,
|
|
||||||
})
|
|
||||||
|
|
||||||
resp := doRequest(router, http.MethodGet, "/v1/user", tt.apiKey, nil)
|
resp := doRequest(router, http.MethodGet, "/v1/user", tt.apiKey, nil)
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
module gitea.dwysokinski.me/twhelp/sessions/internal/tools
|
module gitea.dwysokinski.me/twhelp/sessions/internal/tools
|
||||||
|
|
||||||
go 1.19
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/golangci/golangci-lint v1.50.1
|
github.com/golangci/golangci-lint v1.50.1
|
||||||
|
|
|
@ -10,5 +10,8 @@
|
||||||
],
|
],
|
||||||
"postUpdateOptions": [
|
"postUpdateOptions": [
|
||||||
"gomodTidy"
|
"gomodTidy"
|
||||||
|
],
|
||||||
|
"ignorePaths": [
|
||||||
|
".drone.yml"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user