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,6 +1,7 @@
|
||||
package jwt
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/DATA-DOG/go-sqlmock"
|
||||
@@ -8,14 +9,16 @@ import (
|
||||
)
|
||||
|
||||
func TestCreateGenerator_Success_NoDB(t *testing.T) {
|
||||
gen, err := CreateGenerator(
|
||||
15,
|
||||
60,
|
||||
5,
|
||||
"example.com",
|
||||
"secret",
|
||||
nil,
|
||||
)
|
||||
gen, err := CreateGenerator(GeneratorConfig{
|
||||
AccessExpireAfter: 15,
|
||||
RefreshExpireAfter: 60,
|
||||
FreshExpireAfter: 5,
|
||||
TrustedHost: "example.com",
|
||||
SecretKey: "secret",
|
||||
DB: nil,
|
||||
DBType: DatabaseType{Type: DatabasePostgreSQL, Version: "15"},
|
||||
TableConfig: DefaultTableConfig(),
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, gen)
|
||||
@@ -26,14 +29,54 @@ func TestCreateGenerator_Success_WithDB(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
gen, err := CreateGenerator(
|
||||
15,
|
||||
60,
|
||||
5,
|
||||
"example.com",
|
||||
"secret",
|
||||
db,
|
||||
)
|
||||
config := DefaultTableConfig()
|
||||
config.AutoCreate = false
|
||||
config.EnableAutoCleanup = false
|
||||
|
||||
gen, err := CreateGenerator(GeneratorConfig{
|
||||
AccessExpireAfter: 15,
|
||||
RefreshExpireAfter: 60,
|
||||
FreshExpireAfter: 5,
|
||||
TrustedHost: "example.com",
|
||||
SecretKey: "secret",
|
||||
DB: db,
|
||||
DBType: DatabaseType{Type: DatabasePostgreSQL, Version: "15"},
|
||||
TableConfig: config,
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, gen)
|
||||
require.NoError(t, mock.ExpectationsWereMet())
|
||||
}
|
||||
|
||||
func TestCreateGenerator_WithDB_AutoCreate(t *testing.T) {
|
||||
db, mock, err := sqlmock.New()
|
||||
require.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
// Mock table doesn't exist
|
||||
mock.ExpectQuery("SELECT 1 FROM information_schema.tables").
|
||||
WithArgs("jwtblacklist").
|
||||
WillReturnRows(sqlmock.NewRows([]string{"1"}))
|
||||
|
||||
// Mock CREATE TABLE
|
||||
mock.ExpectExec("CREATE TABLE IF NOT EXISTS jwtblacklist").
|
||||
WillReturnResult(sqlmock.NewResult(0, 0))
|
||||
|
||||
// Mock cleanup function creation
|
||||
mock.ExpectExec("CREATE OR REPLACE FUNCTION cleanup_jwtblacklist").
|
||||
WillReturnResult(sqlmock.NewResult(0, 0))
|
||||
|
||||
gen, err := CreateGenerator(GeneratorConfig{
|
||||
AccessExpireAfter: 15,
|
||||
RefreshExpireAfter: 60,
|
||||
FreshExpireAfter: 5,
|
||||
TrustedHost: "example.com",
|
||||
SecretKey: "secret",
|
||||
DB: db,
|
||||
DBType: DatabaseType{Type: DatabasePostgreSQL, Version: "15"},
|
||||
TableConfig: DefaultTableConfig(),
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, gen)
|
||||
@@ -42,49 +85,113 @@ func TestCreateGenerator_Success_WithDB(t *testing.T) {
|
||||
|
||||
func TestCreateGenerator_InvalidInputs(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fn func() error
|
||||
name string
|
||||
config GeneratorConfig
|
||||
}{
|
||||
{
|
||||
"access expiry <= 0",
|
||||
func() error {
|
||||
_, err := CreateGenerator(0, 1, 1, "h", "s", nil)
|
||||
return err
|
||||
GeneratorConfig{
|
||||
AccessExpireAfter: 0,
|
||||
RefreshExpireAfter: 1,
|
||||
FreshExpireAfter: 1,
|
||||
TrustedHost: "h",
|
||||
SecretKey: "s",
|
||||
},
|
||||
},
|
||||
{
|
||||
"refresh expiry <= 0",
|
||||
func() error {
|
||||
_, err := CreateGenerator(1, 0, 1, "h", "s", nil)
|
||||
return err
|
||||
GeneratorConfig{
|
||||
AccessExpireAfter: 1,
|
||||
RefreshExpireAfter: 0,
|
||||
FreshExpireAfter: 1,
|
||||
TrustedHost: "h",
|
||||
SecretKey: "s",
|
||||
},
|
||||
},
|
||||
{
|
||||
"fresh expiry <= 0",
|
||||
func() error {
|
||||
_, err := CreateGenerator(1, 1, 0, "h", "s", nil)
|
||||
return err
|
||||
GeneratorConfig{
|
||||
AccessExpireAfter: 1,
|
||||
RefreshExpireAfter: 1,
|
||||
FreshExpireAfter: 0,
|
||||
TrustedHost: "h",
|
||||
SecretKey: "s",
|
||||
},
|
||||
},
|
||||
{
|
||||
"empty trustedHost",
|
||||
func() error {
|
||||
_, err := CreateGenerator(1, 1, 1, "", "s", nil)
|
||||
return err
|
||||
GeneratorConfig{
|
||||
AccessExpireAfter: 1,
|
||||
RefreshExpireAfter: 1,
|
||||
FreshExpireAfter: 1,
|
||||
TrustedHost: "",
|
||||
SecretKey: "s",
|
||||
},
|
||||
},
|
||||
{
|
||||
"empty secretKey",
|
||||
func() error {
|
||||
_, err := CreateGenerator(1, 1, 1, "h", "", nil)
|
||||
return err
|
||||
GeneratorConfig{
|
||||
AccessExpireAfter: 1,
|
||||
RefreshExpireAfter: 1,
|
||||
FreshExpireAfter: 1,
|
||||
TrustedHost: "h",
|
||||
SecretKey: "",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
require.Error(t, tt.fn())
|
||||
_, err := CreateGenerator(tt.config)
|
||||
require.Error(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCleanup_NoDB(t *testing.T) {
|
||||
gen, err := CreateGenerator(GeneratorConfig{
|
||||
AccessExpireAfter: 15,
|
||||
RefreshExpireAfter: 60,
|
||||
FreshExpireAfter: 5,
|
||||
TrustedHost: "example.com",
|
||||
SecretKey: "secret",
|
||||
DB: nil,
|
||||
DBType: DatabaseType{Type: DatabasePostgreSQL, Version: "15"},
|
||||
TableConfig: DefaultTableConfig(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
err = gen.Cleanup(context.Background())
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "No DB provided")
|
||||
}
|
||||
|
||||
func TestCleanup_Success(t *testing.T) {
|
||||
db, mock, err := sqlmock.New()
|
||||
require.NoError(t, err)
|
||||
defer db.Close()
|
||||
|
||||
config := DefaultTableConfig()
|
||||
config.AutoCreate = false
|
||||
config.EnableAutoCleanup = false
|
||||
|
||||
gen, err := CreateGenerator(GeneratorConfig{
|
||||
AccessExpireAfter: 15,
|
||||
RefreshExpireAfter: 60,
|
||||
FreshExpireAfter: 5,
|
||||
TrustedHost: "example.com",
|
||||
SecretKey: "secret",
|
||||
DB: db,
|
||||
DBType: DatabaseType{Type: DatabasePostgreSQL, Version: "15"},
|
||||
TableConfig: config,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Mock DELETE query
|
||||
mock.ExpectExec("DELETE FROM jwtblacklist WHERE exp").
|
||||
WillReturnResult(sqlmock.NewResult(0, 5))
|
||||
|
||||
err = gen.Cleanup(context.Background())
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, mock.ExpectationsWereMet())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user