summaryrefslogtreecommitdiff
path: root/pkg/web
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-04-25 11:08:58 -0600
committermo khan <mo@mokhan.ca>2025-04-25 11:08:58 -0600
commit2b1e14690ea6426a67c0faaaddcfb8aa7360dce7 (patch)
tree7f764225e3e3a26bbd7532e72ab99a54e465be92 /pkg/web
parent0053db0d265af313dd281db5cf1e73236cde30c6 (diff)
refactor: move db and mountable to app
Diffstat (limited to 'pkg/web')
-rw-r--r--pkg/web/middleware/id_token.go56
-rw-r--r--pkg/web/middleware/id_token_test.go101
-rw-r--r--pkg/web/middleware/init.go24
-rw-r--r--pkg/web/middleware/require_user.go22
-rw-r--r--pkg/web/middleware/require_user_test.go43
-rw-r--r--pkg/web/middleware/user.go36
-rw-r--r--pkg/web/middleware/user_test.go76
-rw-r--r--pkg/web/mountable.go7
8 files changed, 0 insertions, 365 deletions
diff --git a/pkg/web/middleware/id_token.go b/pkg/web/middleware/id_token.go
deleted file mode 100644
index a32c77b..0000000
--- a/pkg/web/middleware/id_token.go
+++ /dev/null
@@ -1,56 +0,0 @@
-package middleware
-
-import (
- "net/http"
-
- "github.com/xlgmokha/x/pkg/log"
- "github.com/xlgmokha/x/pkg/x"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/key"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/oidc"
-)
-
-type TokenParser func(*http.Request) oidc.RawToken
-
-func IDTokenFromSessionCookie(r *http.Request) oidc.RawToken {
- cookies := r.CookiesNamed("session")
-
- if len(cookies) != 1 {
- return ""
- }
-
- tokens, err := oidc.TokensFromBase64String(cookies[0].Value)
- if err != nil {
- log.WithFields(r.Context(), log.Fields{"error": err})
- return ""
- }
-
- return tokens.IDToken
-}
-
-func IDToken(cfg *oidc.OpenID) func(http.Handler) http.Handler {
- parsers := []TokenParser{IDTokenFromSessionCookie}
-
- return func(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- for _, parser := range parsers {
- rawIDToken := parser(r)
- if !x.IsZero(rawIDToken) {
- verifier := cfg.Provider.VerifierContext(r.Context(), cfg.OIDCConfig)
- idToken, err := verifier.Verify(r.Context(), rawIDToken.String())
- if err != nil {
- log.WithFields(r.Context(), log.Fields{"error": err})
- } else {
- log.WithFields(r.Context(), log.Fields{"id_token": idToken})
- next.ServeHTTP(
- w,
- r.WithContext(key.IDToken.With(r.Context(), idToken)),
- )
- return
- }
- }
- }
-
- next.ServeHTTP(w, r)
- })
- }
-}
diff --git a/pkg/web/middleware/id_token_test.go b/pkg/web/middleware/id_token_test.go
deleted file mode 100644
index 4f26cdf..0000000
--- a/pkg/web/middleware/id_token_test.go
+++ /dev/null
@@ -1,101 +0,0 @@
-package middleware
-
-import (
- "context"
- "net/http"
- "os"
- "testing"
- "time"
-
- "github.com/oauth2-proxy/mockoidc"
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- "github.com/xlgmokha/x/pkg/log"
- "github.com/xlgmokha/x/pkg/x"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/key"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/oidc"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/test"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/web"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/web/cookie"
- "golang.org/x/oauth2"
-)
-
-func TestIDToken(t *testing.T) {
- srv := test.NewOIDCServer(t)
- defer srv.Close()
-
- client := &http.Client{Transport: &web.Transport{Logger: log.New(os.Stdout, log.Fields{})}}
- cfg := srv.MockOIDC.Config()
- ctx := context.WithValue(t.Context(), oauth2.HTTPClient, client)
- openID, err := oidc.New(
- ctx,
- srv.Issuer(),
- cfg.ClientID,
- cfg.ClientSecret,
- "https://example.com/oauth/callback",
- )
- require.NoError(t, err)
-
- middleware := IDToken(openID)
-
- t.Run("when an active session cookie is provided", func(t *testing.T) {
- t.Run("attaches the token to the request context", func(t *testing.T) {
- user := mockoidc.DefaultUser()
-
- token, rawIDToken := srv.CreateTokensFor(user)
- tokens := &oidc.Tokens{Token: token, IDToken: oidc.RawToken(rawIDToken)}
- encoded := x.Must(tokens.ToBase64String())
-
- server := middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- token := key.IDToken.From(r.Context())
- require.NotNil(t, token)
- assert.Equal(t, user.Subject, token.Subject)
-
- w.WriteHeader(http.StatusTeapot)
- }))
-
- r, w := test.RequestResponse(
- "GET",
- "/example",
- test.WithCookie(cookie.New("session", encoded, time.Now().Add(1*time.Hour))),
- )
- server.ServeHTTP(w, r)
-
- assert.Equal(t, http.StatusTeapot, w.Code)
- })
- })
-
- t.Run("when an invalid session cookie is provided", func(t *testing.T) {
- t.Run("forwards the request", func(t *testing.T) {
- server := middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- require.Nil(t, key.IDToken.From(r.Context()))
-
- w.WriteHeader(http.StatusTeapot)
- }))
-
- r, w := test.RequestResponse(
- "GET",
- "/example",
- test.WithCookie(cookie.New("session", "invalid", time.Now().Add(1*time.Hour))),
- )
- server.ServeHTTP(w, r)
-
- assert.Equal(t, http.StatusTeapot, w.Code)
- })
- })
-
- t.Run("when no cookies are provided", func(t *testing.T) {
- t.Run("forwards the request", func(t *testing.T) {
- server := middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- require.Nil(t, key.IDToken.From(r.Context()))
-
- w.WriteHeader(http.StatusTeapot)
- }))
-
- r, w := test.RequestResponse("GET", "/example")
- server.ServeHTTP(w, r)
-
- assert.Equal(t, http.StatusTeapot, w.Code)
- })
- })
-}
diff --git a/pkg/web/middleware/init.go b/pkg/web/middleware/init.go
deleted file mode 100644
index f1a693d..0000000
--- a/pkg/web/middleware/init.go
+++ /dev/null
@@ -1,24 +0,0 @@
-package middleware
-
-import (
- "github.com/xlgmokha/x/pkg/mapper"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/domain"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/oidc"
-)
-
-func init() {
- mapper.Register(func(idToken *oidc.IDToken) *domain.User {
- customClaims := &oidc.CustomClaims{}
- if err := idToken.Claims(customClaims); err != nil {
- return &domain.User{ID: domain.ID(idToken.Subject)}
- }
-
- return &domain.User{
- ID: domain.ID(idToken.Subject),
- Username: customClaims.Nickname,
- Email: customClaims.Email,
- ProfileURL: customClaims.ProfileURL,
- Picture: customClaims.Picture,
- }
- })
-}
diff --git a/pkg/web/middleware/require_user.go b/pkg/web/middleware/require_user.go
deleted file mode 100644
index e81d5b5..0000000
--- a/pkg/web/middleware/require_user.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package middleware
-
-import (
- "net/http"
-
- "github.com/xlgmokha/x/pkg/x"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/key"
-)
-
-func RequireUser(code int, url string) func(http.Handler) http.Handler {
- return func(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- user := key.CurrentUser.From(r.Context())
- if x.IsZero(user) {
- http.Redirect(w, r, url, code)
- return
- }
-
- next.ServeHTTP(w, r)
- })
- }
-}
diff --git a/pkg/web/middleware/require_user_test.go b/pkg/web/middleware/require_user_test.go
deleted file mode 100644
index 68b9911..0000000
--- a/pkg/web/middleware/require_user_test.go
+++ /dev/null
@@ -1,43 +0,0 @@
-package middleware
-
-import (
- "net/http"
- "testing"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/domain"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/key"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/test"
-)
-
-func TestRequireUser(t *testing.T) {
- middleware := RequireUser(http.StatusFound, "/login")
-
- t.Run("when a user is not logged in", func(t *testing.T) {
- t.Run("redirects to the homepage", func(t *testing.T) {
- r, w := test.RequestResponse("GET", "/example")
-
- server := middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- require.Fail(t, "unexpected call to handler")
- }))
- server.ServeHTTP(w, r)
-
- require.Equal(t, http.StatusFound, w.Code)
- assert.Equal(t, "/login", w.Header().Get("Location"))
- })
- })
-
- t.Run("when a user is logged in", func(t *testing.T) {
- t.Run("forwards the request", func(t *testing.T) {
- r, w := test.RequestResponse("GET", "/example", test.WithContextKeyValue(t.Context(), key.CurrentUser, &domain.User{}))
-
- server := middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- w.WriteHeader(http.StatusTeapot)
- }))
- server.ServeHTTP(w, r)
-
- require.Equal(t, http.StatusTeapot, w.Code)
- })
- })
-}
diff --git a/pkg/web/middleware/user.go b/pkg/web/middleware/user.go
deleted file mode 100644
index 194ded6..0000000
--- a/pkg/web/middleware/user.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package middleware
-
-import (
- "net/http"
-
- "github.com/xlgmokha/x/pkg/log"
- "github.com/xlgmokha/x/pkg/mapper"
- "github.com/xlgmokha/x/pkg/x"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/domain"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/key"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/oidc"
-)
-
-func User(db domain.Repository[*domain.User]) func(http.Handler) http.Handler {
- return func(next http.Handler) http.Handler {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- idToken := key.IDToken.From(r.Context())
- if x.IsZero(idToken) {
- next.ServeHTTP(w, r)
- return
- }
-
- user := db.Find(domain.ID(idToken.Subject))
- if x.IsZero(user) {
- user = mapper.MapFrom[*oidc.IDToken, *domain.User](idToken)
- if err := db.Save(user); err != nil {
- log.WithFields(r.Context(), log.Fields{"error": err})
- next.ServeHTTP(w, r)
- return
- }
- }
-
- next.ServeHTTP(w, r.WithContext(key.CurrentUser.With(r.Context(), user)))
- })
- }
-}
diff --git a/pkg/web/middleware/user_test.go b/pkg/web/middleware/user_test.go
deleted file mode 100644
index b09fa7b..0000000
--- a/pkg/web/middleware/user_test.go
+++ /dev/null
@@ -1,76 +0,0 @@
-package middleware
-
-import (
- "net/http"
- "testing"
-
- "github.com/stretchr/testify/assert"
- "github.com/stretchr/testify/require"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/app/domain"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/db"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/key"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/oidc"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/pls"
- "gitlab.com/gitlab-org/software-supply-chain-security/authorization/sparkled/pkg/test"
-)
-
-func TestUser(t *testing.T) {
- repository := db.NewRepository[*domain.User]()
- middleware := User(repository)
-
- knownUser := &domain.User{ID: domain.ID(pls.GenerateULID())}
- require.NoError(t, repository.Save(knownUser))
-
- t.Run("when ID Token is provided", func(t *testing.T) {
- t.Run("when user is known", func(t *testing.T) {
- server := middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- user := key.CurrentUser.From(r.Context())
- require.NotNil(t, user)
- assert.Equal(t, knownUser.ID, user.ID)
-
- w.WriteHeader(http.StatusTeapot)
- }))
-
- ctx := key.IDToken.With(t.Context(), &oidc.IDToken{Subject: knownUser.ID.String()})
-
- r, w := test.RequestResponse("GET", "/example", test.WithContext(ctx))
- server.ServeHTTP(w, r)
-
- assert.Equal(t, http.StatusTeapot, w.Code)
- })
-
- t.Run("when user is unknown", func(t *testing.T) {
- unknownID := pls.GenerateULID()
-
- server := middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- user := key.CurrentUser.From(r.Context())
- require.NotNil(t, user)
- assert.Equal(t, domain.ID(unknownID), user.ID)
-
- w.WriteHeader(http.StatusTeapot)
- }))
-
- ctx := key.IDToken.With(t.Context(), &oidc.IDToken{Subject: unknownID})
-
- r, w := test.RequestResponse("GET", "/example", test.WithContext(ctx))
- server.ServeHTTP(w, r)
-
- assert.Equal(t, http.StatusTeapot, w.Code)
- require.NotNil(t, repository.Find(domain.ID(unknownID)))
- })
- })
-
- t.Run("when ID Token is not provided", func(t *testing.T) {
- server := middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- user := key.CurrentUser.From(r.Context())
- require.Nil(t, user)
-
- w.WriteHeader(http.StatusTeapot)
- }))
-
- r, w := test.RequestResponse("GET", "/example")
- server.ServeHTTP(w, r)
-
- assert.Equal(t, http.StatusTeapot, w.Code)
- })
-}
diff --git a/pkg/web/mountable.go b/pkg/web/mountable.go
deleted file mode 100644
index 6e04b86..0000000
--- a/pkg/web/mountable.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package web
-
-import "net/http"
-
-type Mountable interface {
- MountTo(*http.ServeMux)
-}