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>
118 lines
3.1 KiB
Go
118 lines
3.1 KiB
Go
package hwsauth
|
|
|
|
import (
|
|
"database/sql"
|
|
|
|
"git.haelnorr.com/h/golib/hws"
|
|
"git.haelnorr.com/h/golib/jwt"
|
|
"github.com/pkg/errors"
|
|
"github.com/rs/zerolog"
|
|
)
|
|
|
|
type Authenticator[T Model] struct {
|
|
tokenGenerator *jwt.TokenGenerator
|
|
load LoadFunc[T]
|
|
conn DBConnection
|
|
ignoredPaths []string
|
|
logger *zerolog.Logger
|
|
server *hws.Server
|
|
errorPage hws.ErrorPageFunc
|
|
SSL bool // Use SSL for JWT tokens. Default true
|
|
LandingPage string // Path of the desired landing page for logged in users
|
|
}
|
|
|
|
// NewAuthenticator creates and returns a new Authenticator using the provided configuration.
|
|
// If cfg is nil or any required fields are not set, default values will be used or an error returned.
|
|
// Required fields: SecretKey (no default)
|
|
// If SSL is true, TrustedHost is also required.
|
|
func NewAuthenticator[T Model](
|
|
cfg *Config,
|
|
load LoadFunc[T],
|
|
server *hws.Server,
|
|
conn DBConnection,
|
|
logger *zerolog.Logger,
|
|
errorPage hws.ErrorPageFunc,
|
|
) (*Authenticator[T], error) {
|
|
if load == nil {
|
|
return nil, errors.New("No function to load model supplied")
|
|
}
|
|
if server == nil {
|
|
return nil, errors.New("No hws.Server provided")
|
|
}
|
|
if conn == nil {
|
|
return nil, errors.New("No database connection supplied")
|
|
}
|
|
if logger == nil {
|
|
return nil, errors.New("No logger provided")
|
|
}
|
|
if errorPage == nil {
|
|
return nil, errors.New("No ErrorPage provided")
|
|
}
|
|
|
|
// Validate config
|
|
if cfg == nil {
|
|
return nil, errors.New("Config is required")
|
|
}
|
|
if cfg.SecretKey == "" {
|
|
return nil, errors.New("SecretKey is required")
|
|
}
|
|
if cfg.SSL && cfg.TrustedHost == "" {
|
|
return nil, errors.New("TrustedHost is required when SSL is enabled")
|
|
}
|
|
if cfg.AccessTokenExpiry == 0 {
|
|
cfg.AccessTokenExpiry = 5
|
|
}
|
|
if cfg.RefreshTokenExpiry == 0 {
|
|
cfg.RefreshTokenExpiry = 1440
|
|
}
|
|
if cfg.TokenFreshTime == 0 {
|
|
cfg.TokenFreshTime = 5
|
|
}
|
|
if cfg.LandingPage == "" {
|
|
cfg.LandingPage = "/profile"
|
|
}
|
|
|
|
// Cast DBConnection to *sql.DB
|
|
// DBConnection is satisfied by *sql.DB, so this cast should be safe for standard usage
|
|
sqlDB, ok := conn.(*sql.DB)
|
|
if !ok {
|
|
return nil, errors.New("DBConnection must be *sql.DB for JWT token generation")
|
|
}
|
|
|
|
// Configure JWT table
|
|
tableConfig := jwt.DefaultTableConfig()
|
|
if cfg.JWTTableName != "" {
|
|
tableConfig.TableName = cfg.JWTTableName
|
|
}
|
|
|
|
// Create token generator
|
|
tokenGen, err := jwt.CreateGenerator(jwt.GeneratorConfig{
|
|
AccessExpireAfter: cfg.AccessTokenExpiry,
|
|
RefreshExpireAfter: cfg.RefreshTokenExpiry,
|
|
FreshExpireAfter: cfg.TokenFreshTime,
|
|
TrustedHost: cfg.TrustedHost,
|
|
SecretKey: cfg.SecretKey,
|
|
DBConn: sqlDB,
|
|
DBType: jwt.DatabaseType{
|
|
Type: cfg.DatabaseType,
|
|
Version: cfg.DatabaseVersion,
|
|
},
|
|
TableConfig: tableConfig,
|
|
})
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "jwt.CreateGenerator")
|
|
}
|
|
|
|
auth := Authenticator[T]{
|
|
tokenGenerator: tokenGen,
|
|
load: load,
|
|
server: server,
|
|
conn: conn,
|
|
logger: logger,
|
|
errorPage: errorPage,
|
|
SSL: cfg.SSL,
|
|
LandingPage: cfg.LandingPage,
|
|
}
|
|
return &auth, nil
|
|
}
|