Refactor database interface to use *sql.DB directly
Simplified the database layer by removing custom interface wrappers and using standard library *sql.DB and *sql.Tx types directly. Changes: - Removed DBConnection and DBTransaction interfaces from database.go - Removed NewDBConnection() wrapper function - Updated TokenGenerator to use *sql.DB instead of DBConnection - Updated all validation and revocation methods to accept *sql.Tx - Updated TableManager to work with *sql.DB directly - Updated all tests to use db.Begin() instead of custom wrappers - Fixed GeneratorConfig.DB field (was DBConn) - Updated documentation in doc.go with correct API usage Benefits: - Simpler API with fewer abstractions - Works directly with database/sql standard library - Compatible with GORM (via gormDB.DB()) and Bun (share same *sql.DB) - Easier to understand and maintain - No unnecessary wrapper layers Breaking changes: - GeneratorConfig.DBConn renamed to GeneratorConfig.DB - Removed NewDBConnection() function - pass *sql.DB directly - ValidateAccess/ValidateRefresh now accept *sql.Tx instead of DBTransaction - Token.Revoke/CheckNotRevoked now accept *sql.Tx instead of DBTransaction 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,38 +1,56 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Revoke a token by adding it to the database
|
||||
// revoke is an internal method that adds a token to the blacklist database.
|
||||
// Once revoked, the token will fail validation checks even if it hasn't expired.
|
||||
// This operation must be performed within a database transaction.
|
||||
func (gen *TokenGenerator) revoke(tx *sql.Tx, t Token) error {
|
||||
if gen.dbConn == nil {
|
||||
if gen.db == nil {
|
||||
return errors.New("No DB provided, unable to use this function")
|
||||
}
|
||||
|
||||
tableName := gen.tableConfig.TableName
|
||||
jti := t.GetJTI()
|
||||
exp := t.GetEXP()
|
||||
query := `INSERT INTO jwtblacklist (jti, exp) VALUES (?, ?)`
|
||||
_, err := tx.Exec(query, jti, exp)
|
||||
sub := t.GetSUB()
|
||||
|
||||
query := fmt.Sprintf("INSERT INTO %s (jti, exp, sub) VALUES (?, ?, ?)", tableName)
|
||||
_, err := tx.ExecContext(context.Background(), query, jti.String(), exp, sub)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "tx.Exec")
|
||||
return errors.Wrap(err, "tx.ExecContext")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if a token has been revoked. Returns true if not revoked.
|
||||
// checkNotRevoked is an internal method that queries the blacklist to verify
|
||||
// a token hasn't been revoked. Returns true if the token is valid (not blacklisted),
|
||||
// false if it has been revoked. This operation must be performed within a database transaction.
|
||||
func (gen *TokenGenerator) checkNotRevoked(tx *sql.Tx, t Token) (bool, error) {
|
||||
if gen.dbConn == nil {
|
||||
if gen.db == nil {
|
||||
return false, errors.New("No DB provided, unable to use this function")
|
||||
}
|
||||
|
||||
tableName := gen.tableConfig.TableName
|
||||
jti := t.GetJTI()
|
||||
query := `SELECT 1 FROM jwtblacklist WHERE jti = ? LIMIT 1`
|
||||
rows, err := tx.Query(query, jti)
|
||||
|
||||
query := fmt.Sprintf("SELECT 1 FROM %s WHERE jti = ? LIMIT 1", tableName)
|
||||
rows, err := tx.QueryContext(context.Background(), query, jti.String())
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "tx.Query")
|
||||
return false, errors.Wrap(err, "tx.QueryContext")
|
||||
}
|
||||
defer rows.Close()
|
||||
revoked := rows.Next()
|
||||
return !revoked, nil
|
||||
|
||||
exists := rows.Next()
|
||||
if err := rows.Err(); err != nil {
|
||||
return false, errors.Wrap(err, "rows iteration")
|
||||
}
|
||||
|
||||
return !exists, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user