feat: more role backend and admin/writer roles additions and adjustments

This commit is contained in:
Florian Sylvain committed 2026-10-26 18:15:26 +01:00
1 parent 8c6c6456da
commit de142f6c5f
131 files changed
+2663 -435

No files matched your search

+61 -66
View File
@@ -58,6 +58,14 @@ func (c *UseCases) apiKeyAuth() func(http.Handler) http.Handler {
return c.apiKeyAuthMiddleware
}
func (c *UseCases) require(key string) func(http.Handler) http.Handler {
return middleware.RequirePermission(c.GetUserUseCase, c.CheckPermissionUseCase, key)
}
func (c *UseCases) requireAll(key string) func(http.Handler) http.Handler {
return middleware.RequireFullScope(c.GetUserUseCase, c.CheckPermissionUseCase, key)
}
func NewArticleRouter(container *UseCases, trustedProxies []string) http.Handler {
r := chi.NewRouter()
r.Use(container.apiKeyAuth())
@@ -149,10 +157,10 @@ func NewUserRouter(container *UseCases, rateLimit config.AuthRateLimitSettings,
r.Use(middleware.RequireCurrentToken(container.GetUserUseCase))
r.Use(middleware.RequireVerifiedUser(container.GetUserUseCase))
r.Patch("/me", userHandler.UpdateMe)
r.Get("/", inviteHandler.ListUsers)
r.With(container.require("users.view")).Get("/", inviteHandler.ListUsers)
r.Get("/lookup", lookupHandler.Lookup)
r.Group(func(r chi.Router) {
r.Use(middleware.RequireOwner(container.GetUserUseCase))
r.Use(container.require("users.invite"))
r.Use(middleware.TrustedProxyRealIP(trustedProxies))
r.Use(middleware.NewRateLimiter(rateLimit.MaxAttempts, rateLimit.Window))
r.Post("/invite", inviteHandler.CreateInvite)
@@ -173,6 +181,7 @@ func NewSettingsRouter(container *UseCases, trustedProxies []string) http.Handle
r.Use(authtoken.Authenticator)
r.Use(middleware.RequireCurrentToken(container.GetUserUseCase))
r.Use(middleware.RequireVerifiedUser(container.GetUserUseCase))
r.Use(container.require("settings.view"))
r.Get("/", settingsHandler.GetSettings)
})
r.Group(func(r chi.Router) {
@@ -183,7 +192,7 @@ func NewSettingsRouter(container *UseCases, trustedProxies []string) http.Handle
r.Use(authtoken.Authenticator)
r.Use(middleware.RequireCurrentToken(container.GetUserUseCase))
r.Use(middleware.RequireVerifiedUser(container.GetUserUseCase))
r.Use(middleware.RequireOwner(container.GetUserUseCase))
r.Use(container.require("system.edit_retention"))
r.Patch("/", settingsHandler.UpdateSettings)
})
return r
@@ -213,11 +222,10 @@ func NewSiteRouter(container *UseCases, trustedProxies []string) http.Handler {
r.Use(authtoken.Authenticator)
r.Use(middleware.RequireCurrentToken(container.GetUserUseCase))
r.Use(middleware.RequireVerifiedUser(container.GetUserUseCase))
r.Use(middleware.RequireOwner(container.GetUserUseCase))
r.Post("/", siteHandler.Create)
r.Patch("/{id}", siteHandler.Update)
r.Patch("/{id}/default", siteHandler.SetDefault)
r.Delete("/{id}", siteHandler.Delete)
r.With(container.require("settings.manage_sites")).Post("/", siteHandler.Create)
r.With(container.require("settings.manage_sites")).Patch("/{id}", siteHandler.Update)
r.With(container.require("settings.manage_sites")).Patch("/{id}/default", siteHandler.SetDefault)
r.With(container.require("settings.delete_site")).Delete("/{id}", siteHandler.Delete)
})
return r
}
@@ -225,7 +233,7 @@ func NewSiteRouter(container *UseCases, trustedProxies []string) http.Handler {
func NewAuthorRouter(container *UseCases, trustedProxies []string) http.Handler {
r := chi.NewRouter()
authorHandler := author.NewHandler(container.ListAuthorsUseCase, container.CreateAuthorUseCase, container.CreateMyAuthorUseCase, container.UpdateAuthorUseCase, container.DeleteAuthorUseCase, container.GetUserUseCase)
authorHandler := author.NewHandler(container.ListAuthorsUseCase, container.CreateAuthorUseCase, container.CreateMyAuthorUseCase, container.UpdateAuthorUseCase, container.DeleteAuthorUseCase)
r.Group(func(r chi.Router) {
r.Use(authtoken.Verifier(container.Token))
@@ -233,6 +241,7 @@ func NewAuthorRouter(container *UseCases, trustedProxies []string) http.Handler
r.Use(authtoken.Authenticator)
r.Use(middleware.RequireCurrentToken(container.GetUserUseCase))
r.Use(middleware.RequireVerifiedUser(container.GetUserUseCase))
r.Use(container.require("authors.view"))
r.Get("/", authorHandler.List)
})
r.Group(func(r chi.Router) {
@@ -244,12 +253,9 @@ func NewAuthorRouter(container *UseCases, trustedProxies []string) http.Handler
r.Use(middleware.RequireCurrentToken(container.GetUserUseCase))
r.Use(middleware.RequireVerifiedUser(container.GetUserUseCase))
r.Post("/me", authorHandler.CreateMine)
r.Patch("/{id}", authorHandler.Update)
r.Group(func(r chi.Router) {
r.Use(middleware.RequireOwnerOrAdmin(container.GetUserUseCase))
r.Post("/", authorHandler.Create)
r.Delete("/{id}", authorHandler.Delete)
})
r.With(container.require("authors.edit")).Patch("/{id}", authorHandler.Update)
r.With(container.require("authors.create")).Post("/", authorHandler.Create)
r.With(container.require("authors.delete")).Delete("/{id}", authorHandler.Delete)
})
return r
}
@@ -268,14 +274,11 @@ func NewContentTypeRouter(container *UseCases, trustedProxies []string) http.Han
r.Use(authtoken.Authenticator)
r.Use(middleware.RequireCurrentToken(container.GetUserUseCase))
r.Use(middleware.RequireVerifiedUser(container.GetUserUseCase))
r.Get("/", contentTypeHandler.List)
r.Get("/{key}", contentTypeHandler.Get)
r.Group(func(r chi.Router) {
r.Use(middleware.RequireOwnerOrAdmin(container.GetUserUseCase))
r.Post("/", contentTypeHandler.Create)
r.Put("/{key}", contentTypeHandler.Update)
r.Delete("/{key}", contentTypeHandler.Delete)
})
r.With(container.require("schema.view")).Get("/", contentTypeHandler.List)
r.With(container.require("schema.view")).Get("/{key}", contentTypeHandler.Get)
r.With(container.require("schema.edit")).Post("/", contentTypeHandler.Create)
r.With(container.require("schema.edit")).Put("/{key}", contentTypeHandler.Update)
r.With(container.require("schema.delete")).Delete("/{key}", contentTypeHandler.Delete)
r.Get("/{key}/entry", entryHandler.List)
r.Post("/{key}/entry", entryHandler.Create)
r.Get("/{key}/entry/{id}", entryHandler.Get)
@@ -296,7 +299,7 @@ func NewBuiltinTypeRouter(container *UseCases, trustedProxies []string) http.Han
r.Use(authtoken.Authenticator)
r.Use(middleware.RequireCurrentToken(container.GetUserUseCase))
r.Use(middleware.RequireVerifiedUser(container.GetUserUseCase))
r.Use(middleware.RequireOwnerOrAdmin(container.GetUserUseCase))
r.Use(container.require("schema.view"))
r.Get("/", builtinTypeHandler.List)
r.Get("/{key}", builtinTypeHandler.Get)
return r
@@ -314,12 +317,9 @@ func NewActivityRouter(container *UseCases, trustedProxies []string) http.Handle
r.Use(authtoken.Authenticator)
r.Use(middleware.RequireCurrentToken(container.GetUserUseCase))
r.Use(middleware.RequireVerifiedUser(container.GetUserUseCase))
r.Get("/", activityHandler.List)
r.Group(func(r chi.Router) {
r.Use(middleware.RequireOwnerOrAdmin(container.GetUserUseCase))
r.Get("/summary", activityHandler.Summary)
r.Get("/export", activityHandler.Export)
})
r.With(container.require("activity.view")).Get("/", activityHandler.List)
r.With(container.requireAll("activity.view")).Get("/summary", activityHandler.Summary)
r.With(container.require("activity.export"), container.require("activity.view")).Get("/export", activityHandler.Export)
return r
}
@@ -333,7 +333,7 @@ const (
func NewSystemRouter(container *UseCases, trustedProxies []string) http.Handler {
r := chi.NewRouter()
updateHandler := update.NewHandler(container.GetUpdateStatusUseCase, container.CheckForUpdateUseCase, container.StartUpdateDownloadUseCase, container.RequestRestartUseCase, container.GetUserUseCase)
updateHandler := update.NewHandler(container.GetUpdateStatusUseCase, container.CheckForUpdateUseCase, container.StartUpdateDownloadUseCase, container.RequestRestartUseCase)
r.Use(middleware.RequireSession)
r.Use(authtoken.Verifier(container.Token))
@@ -341,19 +341,19 @@ func NewSystemRouter(container *UseCases, trustedProxies []string) http.Handler
r.Use(authtoken.Authenticator)
r.Use(middleware.RequireCurrentToken(container.GetUserUseCase))
r.Use(middleware.RequireVerifiedUser(container.GetUserUseCase))
r.Get("/update", updateHandler.GetStatus)
r.With(container.require("settings.view")).Get("/update", updateHandler.GetStatus)
r.Group(func(r chi.Router) {
r.Use(middleware.RequireOwner(container.GetUserUseCase))
r.Use(container.require("system.apply_updates"))
r.Use(middleware.NewUserRateLimiter(updateCheckMaxAttempts, updateCheckWindow))
r.Post("/update/check", updateHandler.Check)
})
r.Group(func(r chi.Router) {
r.Use(middleware.RequireOwner(container.GetUserUseCase))
r.Use(container.require("system.apply_updates"))
r.Use(middleware.NewUserRateLimiter(updateDownloadMaxAttempts, updateDownloadWindow))
r.Post("/update/download", updateHandler.Download)
})
r.Group(func(r chi.Router) {
r.Use(middleware.RequireOwner(container.GetUserUseCase))
r.Use(container.require("system.apply_updates"))
r.Post("/update/restart", updateHandler.Restart)
})
return r
@@ -370,9 +370,9 @@ func NewAPIKeyRouter(container *UseCases, trustedProxies []string) http.Handler
r.Use(authtoken.Authenticator)
r.Use(middleware.RequireCurrentToken(container.GetUserUseCase))
r.Use(middleware.RequireVerifiedUser(container.GetUserUseCase))
r.Post("/", apiKeyHandler.Create)
r.Get("/", apiKeyHandler.List)
r.Delete("/{id}", apiKeyHandler.Revoke)
r.With(container.require("apikeys.create")).Post("/", apiKeyHandler.Create)
r.With(container.require("apikeys.view")).Get("/", apiKeyHandler.List)
r.With(container.require("apikeys.revoke")).Delete("/{id}", apiKeyHandler.Revoke)
return r
}
@@ -402,28 +402,24 @@ func NewMediaRouter(container *UseCases, trustedProxies []string) http.Handler {
r.Use(authtoken.Authenticator)
r.Use(middleware.RequireCurrentToken(container.GetUserUseCase))
r.Use(middleware.RequireVerifiedUser(container.GetUserUseCase))
r.Group(func(r chi.Router) {
r.Use(middleware.RequireOwnerOrAdmin(container.GetUserUseCase))
r.Get("/purge-settings", mediaHandler.GetPurgeSettings)
r.Patch("/purge-settings", mediaHandler.UpdatePurgeSettings)
r.Get("/purge-preview", mediaHandler.PreviewPurge)
r.Post("/purge", mediaHandler.RunPurge)
})
r.With(container.require("settings.view")).Get("/purge-settings", mediaHandler.GetPurgeSettings)
r.With(container.require("settings.edit_general")).Patch("/purge-settings", mediaHandler.UpdatePurgeSettings)
r.With(container.requireAll("media.delete")).Get("/purge-preview", mediaHandler.PreviewPurge)
r.With(container.requireAll("media.delete")).Post("/purge", mediaHandler.RunPurge)
r.Group(func(r chi.Router) {
r.Use(middleware.RejectAPIKey)
r.Use(middleware.RequireOwnerOrAdmin(container.GetUserUseCase))
r.Get("/{id}/variants", mediaHandler.ListVariants)
r.Post("/{id}/variants", mediaHandler.GenerateAllVariants)
r.Post("/{id}/variants/{name}", mediaHandler.GenerateVariant)
r.Delete("/{id}/variants/{name}", mediaHandler.PurgeVariant)
r.With(container.require("media.view")).Get("/{id}/variants", mediaHandler.ListVariants)
r.With(container.require("settings.edit_general")).Post("/{id}/variants", mediaHandler.GenerateAllVariants)
r.With(container.require("settings.edit_general")).Post("/{id}/variants/{name}", mediaHandler.GenerateVariant)
r.With(container.require("settings.edit_general")).Delete("/{id}/variants/{name}", mediaHandler.PurgeVariant)
})
r.Get("/", mediaHandler.List)
r.Post("/", mediaHandler.Upload)
r.Post("/merge", mediaHandler.Merge)
r.Patch("/{id}", mediaHandler.Rename)
r.Delete("/{id}", mediaHandler.Delete)
r.Get("/{id}", mediaHandler.Get)
r.Get("/{id}/usage", mediaHandler.Usage)
r.With(container.require("media.view")).Get("/", mediaHandler.List)
r.With(container.require("media.upload")).Post("/", mediaHandler.Upload)
r.With(container.requireAll("media.delete")).Post("/merge", mediaHandler.Merge)
r.With(container.require("media.upload")).Patch("/{id}", mediaHandler.Rename)
r.With(container.requireAll("media.delete")).Delete("/{id}", mediaHandler.Delete)
r.With(container.require("media.view")).Get("/{id}", mediaHandler.Get)
r.With(container.require("media.view")).Get("/{id}/usage", mediaHandler.Usage)
return r
}
@@ -438,15 +434,14 @@ func NewImageVariantRouter(container *UseCases, trustedProxies []string) http.Ha
r.Use(authtoken.Authenticator)
r.Use(middleware.RequireCurrentToken(container.GetUserUseCase))
r.Use(middleware.RequireVerifiedUser(container.GetUserUseCase))
r.Use(middleware.RequireOwnerOrAdmin(container.GetUserUseCase))
r.Get("/", variantHandler.List)
r.Post("/", variantHandler.Create)
r.Get("/cache", variantHandler.CacheStats)
r.Post("/cache/purge", variantHandler.PurgeCache)
r.Put("/{name}", variantHandler.Update)
r.Patch("/{name}", variantHandler.SetEnabled)
r.Delete("/{name}", variantHandler.Delete)
r.Post("/{name}/purge", variantHandler.Purge)
r.With(container.require("media.view")).Get("/", variantHandler.List)
r.With(container.require("settings.edit_general")).Post("/", variantHandler.Create)
r.With(container.require("settings.view")).Get("/cache", variantHandler.CacheStats)
r.With(container.require("settings.edit_general")).Post("/cache/purge", variantHandler.PurgeCache)
r.With(container.require("settings.edit_general")).Put("/{name}", variantHandler.Update)
r.With(container.require("settings.edit_general")).Patch("/{name}", variantHandler.SetEnabled)
r.With(container.require("settings.edit_general")).Delete("/{name}", variantHandler.Delete)
r.With(container.require("settings.edit_general")).Post("/{name}/purge", variantHandler.Purge)
return r
}