Skip to content

Commit b0f5f4e

Browse files
committed
Add garbage collector for expired api tokens
1 parent e5afae2 commit b0f5f4e

3 files changed

Lines changed: 25 additions & 7 deletions

File tree

config/config.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,14 @@ var (
4141
DisableRateLimiter bool = getBool("DISABLE_RATE_LIMITER", false)
4242

4343
// Domain specific config
44-
AdminRoleName string = getString("ADMIN_ROLENAME", "admin")
45-
DeployRoleName string = getString("DEPLOY_ROLENAME", "deploy")
46-
RegistrationKeyLength int = getInt("REGISTRATION_KEY_LENGTH", 20)
47-
ApiTokenExpirationTime time.Duration = getDuration("API_TOKEN_EXPIRATION_TIME", 3*24*time.Hour)
48-
MinPasswordLength int = getInt("MIN_PASSWORD_LENGTH", 12)
49-
InternalIPs []net.IP = parseIPs(getString("INTERNAL_IPS", ""))
50-
RestrictLoginToAdmins bool = getBool("RESTRICT_LOGIN_TO_ADMINS", false)
44+
AdminRoleName string = getString("ADMIN_ROLENAME", "admin")
45+
DeployRoleName string = getString("DEPLOY_ROLENAME", "deploy")
46+
RegistrationKeyLength int = getInt("REGISTRATION_KEY_LENGTH", 20)
47+
ApiTokenExpirationTime time.Duration = getDuration("API_TOKEN_EXPIRATION_TIME", 3*24*time.Hour)
48+
ApiTokenGarbageCollectorInterval time.Duration = getDuration("API_TOKEN_GARBAGE_COLLECTOR_INTERVAL", 1*time.Hour)
49+
MinPasswordLength int = getInt("MIN_PASSWORD_LENGTH", 12)
50+
InternalIPs []net.IP = parseIPs(getString("INTERNAL_IPS", ""))
51+
RestrictLoginToAdmins bool = getBool("RESTRICT_LOGIN_TO_ADMINS", false)
5152

5253
UseTestDatabase bool = getBool("USE_TEST_DATABASE", false) // TODO: remove in prod - this function deletes the whole database
5354
)

repository/token.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ func (r *TokenRepository) DeleteByID(id uint) error {
5454
return wrapError(r.DB.Unscoped().Select(clause.Associations).Delete(&model.Token{UserID: id}).Error)
5555
}
5656

57+
func (r *TokenRepository) DeleteAllExpiredNonPermanent() (int, error) {
58+
res := r.DB.Unscoped().Where("not permanent AND expires_at < NOW()").Delete(model.Token{})
59+
return (int)(res.RowsAffected), res.Error
60+
}
61+
5762
func (r *TokenRepository) Migrate() error {
5863
err := r.DB.AutoMigrate(&model.Token{})
5964
if err != nil {

service/token.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type TokenService struct {
2525
}
2626

2727
func NewTokenService(tokenRepository repository.TokenRepository, userRepository repository.UserRepository) TokenService {
28+
go tokenGarbageCollector(tokenRepository)
2829
return TokenService{tokenRepository,
2930
userRepository,
3031
make(map[string][]chan *model.AuthUpdateMessage),
@@ -34,6 +35,17 @@ func NewTokenService(tokenRepository repository.TokenRepository, userRepository
3435
}
3536
}
3637

38+
func tokenGarbageCollector(tokenRepository repository.TokenRepository) {
39+
for range time.NewTicker(config.ApiTokenGarbageCollectorInterval).C {
40+
rowsAffected, err := tokenRepository.DeleteAllExpiredNonPermanent()
41+
if err != nil {
42+
log.Println(err)
43+
continue
44+
}
45+
log.Printf("Successfully deleted %d expired tokens\n", rowsAffected)
46+
}
47+
}
48+
3749
func newRandomToken() (string, error) {
3850
s, err := crypto.NewRandomAlphaNumString(20)
3951
if err != nil {

0 commit comments

Comments
 (0)