Fix bug with provisioned token removal

This commit is contained in:
binwiederhier
2026-02-22 20:28:37 -05:00
parent 43280fbc0a
commit 850a9d4cc4
3 changed files with 60 additions and 1 deletions

View File

@@ -763,7 +763,7 @@ func (a *Manager) maybeProvisionTokens(provisionUsernames []string) error {
}
for _, existingToken := range existingTokens {
if !slices.Contains(provisionTokens, existingToken.Value) {
if err := a.store.RemoveToken("", existingToken.Value); err != nil {
if err := a.store.RemoveProvisionedToken(existingToken.Value); err != nil {
return fmt.Errorf("failed to remove provisioned token %s: %v", existingToken.Value, err)
}
}

View File

@@ -1313,6 +1313,53 @@ func TestManager_WithProvisionedUsers(t *testing.T) {
})
}
func TestManager_WithProvisionedUsers_RemoveToken(t *testing.T) {
forEachBackend(t, func(t *testing.T, newStore newStoreFunc) {
conf := &Config{
DefaultAccess: PermissionReadWrite,
ProvisionEnabled: true,
Users: []*User{
{Name: "phil", Hash: "$2a$10$YLiO8U21sX1uhZamTLJXHuxgVC0Z/GKISibrKCLohPgtG7yIxSk4C", Role: RoleUser},
},
Tokens: map[string][]*Token{
"phil": {
{Value: "tk_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Label: "Token A"},
{Value: "tk_bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", Label: "Token B"},
},
},
}
a := newTestManagerFromStoreConfig(t, newStore, conf)
users, err := a.Users()
require.Nil(t, err)
philUserID := ""
for _, u := range users {
if u.Name == "phil" {
philUserID = u.ID
}
}
require.NotEmpty(t, philUserID)
tokens, err := a.Tokens(philUserID)
require.Nil(t, err)
require.Equal(t, 2, len(tokens))
// Re-open the DB: user stays, but Token B is removed from config
require.Nil(t, a.Close())
conf.Tokens = map[string][]*Token{
"phil": {
{Value: "tk_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", Label: "Token A"},
},
}
a = newTestManagerFromStoreConfig(t, newStore, conf)
tokens, err = a.Tokens(philUserID)
require.Nil(t, err)
require.Equal(t, 1, len(tokens))
require.Equal(t, "tk_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", tokens[0].Value)
})
}
func TestManager_UpdateNonProvisionedUsersToProvisionedUsers(t *testing.T) {
forEachBackend(t, func(t *testing.T, newStore newStoreFunc) {
conf := &Config{

View File

@@ -44,6 +44,7 @@ type Store interface {
ChangeTokenExpiry(userID, token string, expires time.Time) error
UpdateTokenLastAccess(token string, lastAccess time.Time, lastOrigin netip.Addr) error
RemoveToken(userID, token string) error
RemoveProvisionedToken(token string) error
RemoveExpiredTokens() error
TokenCount(userID string) (int, error)
RemoveExcessTokens(userID string, maxCount int) error
@@ -538,6 +539,17 @@ func (s *commonStore) RemoveToken(userID, token string) error {
return nil
}
// RemoveProvisionedToken deletes a provisioned token by value, regardless of user
func (s *commonStore) RemoveProvisionedToken(token string) error {
if token == "" {
return errNoTokenProvided
}
if _, err := s.db.Exec(s.queries.deleteProvisionedToken, token); err != nil {
return err
}
return nil
}
// RemoveExpiredTokens deletes all expired tokens from the database
func (s *commonStore) RemoveExpiredTokens() error {
if _, err := s.db.Exec(s.queries.deleteExpiredTokens, time.Now().Unix()); err != nil {