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 { for _, existingToken := range existingTokens {
if !slices.Contains(provisionTokens, existingToken.Value) { 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) 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) { func TestManager_UpdateNonProvisionedUsersToProvisionedUsers(t *testing.T) {
forEachBackend(t, func(t *testing.T, newStore newStoreFunc) { forEachBackend(t, func(t *testing.T, newStore newStoreFunc) {
conf := &Config{ conf := &Config{

View File

@@ -44,6 +44,7 @@ type Store interface {
ChangeTokenExpiry(userID, token string, expires time.Time) error ChangeTokenExpiry(userID, token string, expires time.Time) error
UpdateTokenLastAccess(token string, lastAccess time.Time, lastOrigin netip.Addr) error UpdateTokenLastAccess(token string, lastAccess time.Time, lastOrigin netip.Addr) error
RemoveToken(userID, token string) error RemoveToken(userID, token string) error
RemoveProvisionedToken(token string) error
RemoveExpiredTokens() error RemoveExpiredTokens() error
TokenCount(userID string) (int, error) TokenCount(userID string) (int, error)
RemoveExcessTokens(userID string, maxCount int) error RemoveExcessTokens(userID string, maxCount int) error
@@ -538,6 +539,17 @@ func (s *commonStore) RemoveToken(userID, token string) error {
return nil 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 // RemoveExpiredTokens deletes all expired tokens from the database
func (s *commonStore) RemoveExpiredTokens() error { func (s *commonStore) RemoveExpiredTokens() error {
if _, err := s.db.Exec(s.queries.deleteExpiredTokens, time.Now().Unix()); err != nil { if _, err := s.db.Exec(s.queries.deleteExpiredTokens, time.Now().Unix()); err != nil {