[bugfix] new token API issues (#4022)

* fix incorrect endpoint being registered for /token/{id}

* update the maximum page value for tokens endpoint to 100

* update the available tokens page options

* set a default limit of 25 to match the first available settings panel option

* ensure OnInvalidateToken() hook is called during token delete
This commit is contained in:
kim
2025-04-18 15:37:50 +00:00
committed by GitHub
parent 2fce027808
commit 14899733c8
4 changed files with 43 additions and 26 deletions

View File

@ -43,6 +43,6 @@ func New(processor *processing.Processor) *Module {
func (m *Module) Route(attachHandler func(method string, path string, f ...gin.HandlerFunc) gin.IRoutes) { func (m *Module) Route(attachHandler func(method string, path string, f ...gin.HandlerFunc) gin.IRoutes) {
attachHandler(http.MethodGet, BasePath, m.TokensInfoGETHandler) attachHandler(http.MethodGet, BasePath, m.TokensInfoGETHandler)
attachHandler(http.MethodGet, BasePathWithID, m.TokensInfoGETHandler) attachHandler(http.MethodGet, BasePathWithID, m.TokenInfoGETHandler)
attachHandler(http.MethodPost, InvalidateTokenPath, m.TokenInvalidatePOSTHandler) attachHandler(http.MethodPost, InvalidateTokenPath, m.TokenInvalidatePOSTHandler)
} }

View File

@ -118,8 +118,8 @@ func (m *Module) TokensInfoGETHandler(c *gin.Context) {
page, errWithCode := paging.ParseIDPage(c, page, errWithCode := paging.ParseIDPage(c,
0, // min limit 0, // min limit
80, // max limit 100, // max limit
20, // default limit 25, // default limit
) )
if errWithCode != nil { if errWithCode != nil {
apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1) apiutil.ErrorHandler(c, errWithCode, m.processor.InstanceGetV1)

View File

@ -19,8 +19,10 @@ package bundb
import ( import (
"context" "context"
"errors"
"slices" "slices"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/gtserror" "github.com/superseriousbusiness/gotosocial/internal/gtserror"
"github.com/superseriousbusiness/gotosocial/internal/gtsmodel" "github.com/superseriousbusiness/gotosocial/internal/gtsmodel"
"github.com/superseriousbusiness/gotosocial/internal/paging" "github.com/superseriousbusiness/gotosocial/internal/paging"
@ -409,8 +411,11 @@ func (a *applicationDB) UpdateToken(ctx context.Context, token *gtsmodel.Token,
} }
func (a *applicationDB) DeleteTokenByID(ctx context.Context, id string) error { func (a *applicationDB) DeleteTokenByID(ctx context.Context, id string) error {
var token gtsmodel.Token
token.ID = id
_, err := a.db.NewDelete(). _, err := a.db.NewDelete().
Table("tokens"). Model(&token).
Where("? = ?", bun.Ident("id"), id). Where("? = ?", bun.Ident("id"), id).
Exec(ctx) Exec(ctx)
if err != nil { if err != nil {
@ -418,68 +423,79 @@ func (a *applicationDB) DeleteTokenByID(ctx context.Context, id string) error {
} }
a.state.Caches.DB.Token.Invalidate("ID", id) a.state.Caches.DB.Token.Invalidate("ID", id)
a.state.Caches.OnInvalidateToken(&token)
return nil return nil
} }
func (a *applicationDB) DeleteTokenByCode(ctx context.Context, code string) error { func (a *applicationDB) DeleteTokenByCode(ctx context.Context, code string) error {
var token gtsmodel.Token
_, err := a.db.NewDelete(). _, err := a.db.NewDelete().
Table("tokens"). Model(&token).
Where("? = ?", bun.Ident("code"), code). Where("? = ?", bun.Ident("code"), code).
Returning("?", bun.Ident("id")).
Exec(ctx) Exec(ctx)
if err != nil { if err != nil && !errors.Is(err, db.ErrNoEntries) {
return err return err
} }
a.state.Caches.DB.Token.Invalidate("Code", code) a.state.Caches.DB.Token.Invalidate("Code", code)
a.state.Caches.OnInvalidateToken(&token)
return nil return nil
} }
func (a *applicationDB) DeleteTokenByAccess(ctx context.Context, access string) error { func (a *applicationDB) DeleteTokenByAccess(ctx context.Context, access string) error {
var token gtsmodel.Token
_, err := a.db.NewDelete(). _, err := a.db.NewDelete().
Table("tokens"). Model(&token).
Where("? = ?", bun.Ident("access"), access). Where("? = ?", bun.Ident("access"), access).
Returning("?", bun.Ident("id")).
Exec(ctx) Exec(ctx)
if err != nil { if err != nil && !errors.Is(err, db.ErrNoEntries) {
return err return err
} }
a.state.Caches.DB.Token.Invalidate("Access", access) a.state.Caches.DB.Token.Invalidate("Access", access)
a.state.Caches.OnInvalidateToken(&token)
return nil return nil
} }
func (a *applicationDB) DeleteTokenByRefresh(ctx context.Context, refresh string) error { func (a *applicationDB) DeleteTokenByRefresh(ctx context.Context, refresh string) error {
var token gtsmodel.Token
_, err := a.db.NewDelete(). _, err := a.db.NewDelete().
Table("tokens"). Model(&token).
Where("? = ?", bun.Ident("refresh"), refresh). Where("? = ?", bun.Ident("refresh"), refresh).
Returning("?", bun.Ident("id")).
Exec(ctx) Exec(ctx)
if err != nil { if err != nil && !errors.Is(err, db.ErrNoEntries) {
return err return err
} }
a.state.Caches.DB.Token.Invalidate("Refresh", refresh) a.state.Caches.DB.Token.Invalidate("Refresh", refresh)
a.state.Caches.OnInvalidateToken(&token)
return nil return nil
} }
func (a *applicationDB) DeleteTokensByClientID(ctx context.Context, clientID string) error { func (a *applicationDB) DeleteTokensByClientID(ctx context.Context, clientID string) error {
var tokens []*gtsmodel.Token
// Delete tokens owned by // Delete tokens owned by
// clientID and gather token IDs. // clientID and gather token IDs.
var tokenIDs []string if _, err := a.db.NewDelete().
if _, err := a.db. Model(&tokens).
NewDelete().
Table("tokens").
Where("? = ?", bun.Ident("client_id"), clientID). Where("? = ?", bun.Ident("client_id"), clientID).
Returning("id"). Returning("?", bun.Ident("id")).
Exec(ctx, &tokenIDs); err != nil { Exec(ctx); err != nil && !errors.Is(err, db.ErrNoEntries) {
return err return err
} }
if len(tokenIDs) == 0 { // Invalidate all deleted tokens.
// Nothing was deleted, for _, token := range tokens {
// nothing to invalidate. a.state.Caches.DB.Token.Invalidate("ID", token.ID)
return nil a.state.Caches.OnInvalidateToken(token)
} }
// Invalidate all deleted tokens.
a.state.Caches.DB.Token.InvalidateIDs("ID", tokenIDs)
return nil return nil
} }

View File

@ -36,7 +36,7 @@ export default function TokensSearchForm() {
// Populate search form using values from // Populate search form using values from
// urlQueryParams, to allow paging. // urlQueryParams, to allow paging.
const form = { const form = {
limit: useTextInput("limit", { defaultValue: urlQueryParams.get("limit") ?? "20" }) limit: useTextInput("limit", { defaultValue: urlQueryParams.get("limit") ?? "25" })
}; };
// On mount, trigger search. // On mount, trigger search.
@ -93,9 +93,10 @@ export default function TokensSearchForm() {
label="Items per page" label="Items per page"
options={ options={
<> <>
<option value="20">20</option> <option value="25">25</option>
<option value="50">50</option> <option value="50">50</option>
<option value="0">No limit / show all</option> <option value="75">75</option>
<option value="100">100</option>
</> </>
} }
></Select> ></Select>