mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-30 23:42:25 -05:00 
			
		
		
		
	[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:
		
					parent
					
						
							
								2fce027808
							
						
					
				
			
			
				commit
				
					
						14899733c8
					
				
			
		
					 4 changed files with 43 additions and 26 deletions
				
			
		|  | @ -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) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -117,9 +117,9 @@ 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) | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -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> | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue