mirror of
1
Fork 0

[feature] Debug admin endpoint to clear caches (#2940)

* [feature] Debug admin endpoint to clear caches

* go fmt
This commit is contained in:
tobi 2024-05-29 12:56:17 +02:00 committed by GitHub
parent fa9a3075a5
commit f9a4a6120d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 94 additions and 7 deletions

View File

@ -316,7 +316,7 @@ var Start action.GTSAction = func(ctx context.Context) error {
var ( var (
authModule = api.NewAuth(dbService, processor, idp, routerSession, sessionName) // auth/oauth paths authModule = api.NewAuth(dbService, processor, idp, routerSession, sessionName) // auth/oauth paths
clientModule = api.NewClient(dbService, processor) // api client endpoints clientModule = api.NewClient(&state, processor) // api client endpoints
metricsModule = api.NewMetrics() // Metrics endpoints metricsModule = api.NewMetrics() // Metrics endpoints
healthModule = api.NewHealth(dbService.Ready) // Health check endpoints healthModule = api.NewHealth(dbService.Ready) // Health check endpoints
fileserverModule = api.NewFileserver(processor) // fileserver endpoints fileserverModule = api.NewFileserver(processor) // fileserver endpoints

View File

@ -223,7 +223,7 @@ var Start action.GTSAction = func(ctx context.Context) error {
var ( var (
authModule = api.NewAuth(state.DB, processor, idp, routerSession, sessionName) // auth/oauth paths authModule = api.NewAuth(state.DB, processor, idp, routerSession, sessionName) // auth/oauth paths
clientModule = api.NewClient(state.DB, processor) // api client endpoints clientModule = api.NewClient(&state, processor) // api client endpoints
metricsModule = api.NewMetrics() // Metrics endpoints metricsModule = api.NewMetrics() // Metrics endpoints
healthModule = api.NewHealth(state.DB.Ready) // Health check endpoints healthModule = api.NewHealth(state.DB.Ready) // Health check endpoints
fileserverModule = api.NewFileserver(processor) // fileserver endpoints fileserverModule = api.NewFileserver(processor) // fileserver endpoints

View File

@ -4494,6 +4494,31 @@ paths:
summary: Perform a GET to the specified ActivityPub URL and return detailed debugging information. summary: Perform a GET to the specified ActivityPub URL and return detailed debugging information.
tags: tags:
- debug - debug
/api/v1/admin/debug/caches/clear:
post:
description: Only enabled / exposed if GoToSocial was built and is running with flag DEBUG=1.
operationId: debugClearCaches
produces:
- application/json
responses:
"200":
description: All good baby!
"400":
description: bad request
"401":
description: unauthorized
"404":
description: not found
"406":
description: not acceptable
"500":
description: internal server error
security:
- OAuth2 Bearer:
- admin
summary: Sweep/clear all in-memory caches.
tags:
- debug
/api/v1/admin/domain_allows: /api/v1/admin/domain_allows:
get: get:
operationId: domainAllowsGet operationId: domainAllowsGet

View File

@ -50,6 +50,7 @@ import (
"github.com/superseriousbusiness/gotosocial/internal/middleware" "github.com/superseriousbusiness/gotosocial/internal/middleware"
"github.com/superseriousbusiness/gotosocial/internal/processing" "github.com/superseriousbusiness/gotosocial/internal/processing"
"github.com/superseriousbusiness/gotosocial/internal/router" "github.com/superseriousbusiness/gotosocial/internal/router"
"github.com/superseriousbusiness/gotosocial/internal/state"
) )
type Client struct { type Client struct {
@ -127,13 +128,13 @@ func (c *Client) Route(r *router.Router, m ...gin.HandlerFunc) {
c.user.Route(h) c.user.Route(h)
} }
func NewClient(db db.DB, p *processing.Processor) *Client { func NewClient(state *state.State, p *processing.Processor) *Client {
return &Client{ return &Client{
processor: p, processor: p,
db: db, db: state.DB,
accounts: accounts.New(p), accounts: accounts.New(p),
admin: admin.New(p), admin: admin.New(state, p),
apps: apps.New(p), apps: apps.New(p),
blocks: blocks.New(p), blocks: blocks.New(p),
bookmarks: bookmarks.New(p), bookmarks: bookmarks.New(p),

View File

@ -23,6 +23,7 @@ import (
"codeberg.org/gruf/go-debug" "codeberg.org/gruf/go-debug"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/superseriousbusiness/gotosocial/internal/processing" "github.com/superseriousbusiness/gotosocial/internal/processing"
"github.com/superseriousbusiness/gotosocial/internal/state"
) )
const ( const (
@ -56,6 +57,7 @@ const (
InstanceRulesPathWithID = InstanceRulesPath + "/:" + IDKey InstanceRulesPathWithID = InstanceRulesPath + "/:" + IDKey
DebugPath = BasePath + "/debug" DebugPath = BasePath + "/debug"
DebugAPUrlPath = DebugPath + "/apurl" DebugAPUrlPath = DebugPath + "/apurl"
DebugClearCachesPath = DebugPath + "/caches/clear"
IDKey = "id" IDKey = "id"
FilterQueryKey = "filter" FilterQueryKey = "filter"
@ -73,11 +75,13 @@ const (
type Module struct { type Module struct {
processor *processing.Processor processor *processing.Processor
state *state.State
} }
func New(processor *processing.Processor) *Module { func New(state *state.State, processor *processing.Processor) *Module {
return &Module{ return &Module{
processor: processor, processor: processor,
state: state,
} }
} }
@ -145,5 +149,6 @@ func (m *Module) Route(attachHandler func(method string, path string, f ...gin.H
// debug stuff // debug stuff
if debug.DEBUG { if debug.DEBUG {
attachHandler(http.MethodGet, DebugAPUrlPath, m.DebugAPUrlHandler) attachHandler(http.MethodGet, DebugAPUrlPath, m.DebugAPUrlHandler)
attachHandler(http.MethodPost, DebugClearCachesPath, m.DebugClearCachesHandler)
} }
} }

View File

@ -105,7 +105,7 @@ func (suite *AdminStandardTestSuite) SetupTest() {
suite.sentEmails = make(map[string]string) suite.sentEmails = make(map[string]string)
suite.emailSender = testrig.NewEmailSender("../../../../web/template/", suite.sentEmails) suite.emailSender = testrig.NewEmailSender("../../../../web/template/", suite.sentEmails)
suite.processor = testrig.NewTestProcessor(&suite.state, suite.federator, suite.emailSender, suite.mediaManager) suite.processor = testrig.NewTestProcessor(&suite.state, suite.federator, suite.emailSender, suite.mediaManager)
suite.adminModule = admin.New(suite.processor) suite.adminModule = admin.New(&suite.state, suite.processor)
testrig.StandardDBSetup(suite.db, nil) testrig.StandardDBSetup(suite.db, nil)
testrig.StandardStorageSetup(suite.storage, "../../../../testrig/media") testrig.StandardStorageSetup(suite.storage, "../../../../testrig/media")
} }

View File

@ -73,3 +73,35 @@ import (
// '500': // '500':
// description: internal server error // description: internal server error
func (m *Module) DebugAPUrlHandler(c *gin.Context) {} func (m *Module) DebugAPUrlHandler(c *gin.Context) {}
// DebugClearCachesHandler swagger:operation POST /api/v1/admin/debug/caches/clear debugClearCaches
//
// Sweep/clear all in-memory caches.
//
// Only enabled / exposed if GoToSocial was built and is running with flag DEBUG=1.
//
// ---
// tags:
// - debug
//
// produces:
// - application/json
//
// security:
// - OAuth2 Bearer:
// - admin
//
// responses:
// '200':
// description: All good baby!
// '400':
// description: bad request
// '401':
// description: unauthorized
// '404':
// description: not found
// '406':
// description: not acceptable
// '500':
// description: internal server error
func (m *Module) DebugClearCachesHandler(c *gin.Context) {}

View File

@ -56,3 +56,27 @@ func (m *Module) DebugAPUrlHandler(c *gin.Context) {
c.JSON(http.StatusOK, resp) c.JSON(http.StatusOK, resp)
} }
func (m *Module) DebugClearCachesHandler(c *gin.Context) {
authed, err := oauth.Authed(c, true, true, true, true)
if err != nil {
apiutil.ErrorHandler(c, gtserror.NewErrorUnauthorized(err, err.Error()), m.processor.InstanceGetV1)
return
}
if !*authed.User.Admin {
err := fmt.Errorf("user %s not an admin", authed.User.ID)
apiutil.ErrorHandler(c, gtserror.NewErrorForbidden(err, err.Error()), m.processor.InstanceGetV1)
return
}
if _, err := apiutil.NegotiateAccept(c, apiutil.JSONAcceptHeaders...); err != nil {
apiutil.ErrorHandler(c, gtserror.NewErrorNotAcceptable(err, err.Error()), m.processor.InstanceGetV1)
return
}
// Sweep all caches down to 0 (empty).
m.state.Caches.Sweep(0)
c.JSON(http.StatusOK, gin.H{"status": "OK"})
}