summaryrefslogtreecommitdiff
path: root/app/controllers
diff options
context:
space:
mode:
authormo khan <mo@mokhan.ca>2025-07-23 12:40:12 -0600
committermo khan <mo@mokhan.ca>2025-07-23 12:40:12 -0600
commitd2ebd0a9afed57ba11f053266e6ae1edb84a0f36 (patch)
treeeb547006085f2549f2cea5773c1ec75dba47bfd0 /app/controllers
parent9674cfaedfdb8d583cfe75e1c1738a1c1d66c7f9 (diff)
feat: authorize requests to create sparkles
Diffstat (limited to 'app/controllers')
-rw-r--r--app/controllers/sparkles/controller.go12
-rw-r--r--app/controllers/sparkles/controller_test.go58
2 files changed, 46 insertions, 24 deletions
diff --git a/app/controllers/sparkles/controller.go b/app/controllers/sparkles/controller.go
index 80e95cb..ef2ecd5 100644
--- a/app/controllers/sparkles/controller.go
+++ b/app/controllers/sparkles/controller.go
@@ -14,11 +14,15 @@ import (
)
type Controller struct {
- db domain.Repository[*domain.Sparkle]
+ db domain.Repository[*domain.Sparkle]
+ check authz.CheckPermissionService
}
-func New(db domain.Repository[*domain.Sparkle], check authz.PermissionService) *Controller {
- return &Controller{db: db}
+func New(db domain.Repository[*domain.Sparkle], check authz.CheckPermissionService) *Controller {
+ return &Controller{
+ check: check,
+ db: db,
+ }
}
func (c *Controller) MountTo(mux *http.ServeMux) {
@@ -26,7 +30,7 @@ func (c *Controller) MountTo(mux *http.ServeMux) {
mux.Handle("POST /sparkles", x.Middleware[http.Handler](
http.HandlerFunc(c.Create),
middleware.RequireUser(),
- // middleware.RequirePermission("create", x.Try(ioc.Resolve[authz.CheckPermission](ioc.Default))),
+ middleware.RequirePermission("create", c.check),
))
// This is a temporary endpoint to restore a backup
diff --git a/app/controllers/sparkles/controller_test.go b/app/controllers/sparkles/controller_test.go
index 006c3fa..64b4dc5 100644
--- a/app/controllers/sparkles/controller_test.go
+++ b/app/controllers/sparkles/controller_test.go
@@ -62,16 +62,16 @@ func TestSparkles(t *testing.T) {
})
t.Run("POST /sparkles", func(t *testing.T) {
- t.Run("when a user is logged in", func(t *testing.T) {
+ t.Run("when a user is authenticated", func(t *testing.T) {
currentUser := domain.NewUser(domain.WithID[*domain.User](domain.ID("1")))
+ repository := db.NewRepository[*domain.Sparkle]()
- t.Run("when the user is authorized to create sparkles", func(t *testing.T) {
- t.Run("saves a new sparkle", func(t *testing.T) {
- repository := db.NewRepository[*domain.Sparkle]()
- mux := http.NewServeMux()
- controller := New(repository, stub.AllowWith(t, "user:1", "create", "sparkle:*"))
- controller.MountTo(mux)
+ t.Run("when the user is authorized", func(t *testing.T) {
+ mux := http.NewServeMux()
+ controller := New(repository, stub.AllowWith(t, "user:1", "create", "sparkle:*"))
+ controller.MountTo(mux)
+ t.Run("saves a new sparkle", func(t *testing.T) {
sparkle, _ := domain.NewSparkle("@tanuki for reviewing my code!")
request, response := test.RequestResponse(
"POST",
@@ -103,24 +103,42 @@ func TestSparkles(t *testing.T) {
assert.Equal(t, currentUser, item.Author)
})
})
+
+ t.Run("prevents double WriteHeader when serialization fails", func(t *testing.T) {
+ currentUser := domain.NewUser(domain.WithID[*domain.User](domain.ID("1")))
+ sparkle, _ := domain.NewSparkle("@user for testing")
+
+ request, response := test.RequestResponse(
+ "POST",
+ "/sparkles",
+ test.WithAcceptHeader(serde.JSON),
+ test.WithContentType(sparkle, serde.JSON),
+ test.WithContextKeyValue(t.Context(), cfg.CurrentUser, currentUser),
+ )
+
+ mux.ServeHTTP(&FailingResponseWriter{T: t, ResponseRecorder: response}, request)
+ })
})
- t.Run("prevents double WriteHeader when serialization fails", func(t *testing.T) {
- repository := db.NewRepository[*domain.Sparkle]()
- controller := New(repository, stub.Allow())
+ t.Run("when the user is not authorized", func(t *testing.T) {
+ mux := http.NewServeMux()
+ controller := New(repository, stub.Deny())
+ controller.MountTo(mux)
- currentUser := domain.NewUser(domain.WithID[*domain.User](domain.ID("1")))
- sparkle, _ := domain.NewSparkle("@user for testing")
+ t.Run("returns an error", func(t *testing.T) {
+ sparkle, _ := domain.NewSparkle("@tanuki for reviewing my code!")
+ request, response := test.RequestResponse(
+ "POST",
+ "/sparkles",
+ test.WithAcceptHeader(serde.JSON),
+ test.WithContentType(sparkle, serde.JSON),
+ test.WithContextKeyValue(t.Context(), cfg.CurrentUser, currentUser),
+ )
- request, response := test.RequestResponse(
- "POST",
- "/sparkles",
- test.WithAcceptHeader(serde.JSON),
- test.WithContentType(sparkle, serde.JSON),
- test.WithContextKeyValue(t.Context(), cfg.CurrentUser, currentUser),
- )
+ mux.ServeHTTP(response, request)
- controller.Create(&FailingResponseWriter{T: t, ResponseRecorder: response}, request)
+ require.Equal(t, http.StatusForbidden, response.Code)
+ })
})
})
})