slack5-1770603014/pkg/auth/apikey.go
jordan e66ecd00bf
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
ci/woodpecker/manual/woodpecker Pipeline was successful
Initialize project from skeleton template
2026-02-09 02:10:15 +00:00

91 lines
2.3 KiB
Go

package auth
import (
"context"
"errors"
)
var (
// ErrInvalidAPIKey is returned when the API key is invalid.
ErrInvalidAPIKey = errors.New("invalid API key")
)
// APIKeyLookup is a function that looks up a user by API key.
// Returns nil user and no error if the key is not found.
type APIKeyLookup func(ctx context.Context, key string) (*User, error)
// APIKeyValidator validates API keys using a lookup function.
type APIKeyValidator struct {
lookup APIKeyLookup
}
// NewAPIKeyValidator creates a new API key validator.
//
// Example with database lookup:
//
// validator := auth.NewAPIKeyValidator(func(ctx context.Context, key string) (*auth.User, error) {
// apiKey, err := db.GetAPIKeyByHash(ctx, hashKey(key))
// if err != nil {
// return nil, err
// }
// if apiKey == nil {
// return nil, nil // Key not found
// }
// return &auth.User{
// ID: apiKey.UserID,
// Scopes: apiKey.Scopes,
// }, nil
// })
func NewAPIKeyValidator(lookup APIKeyLookup) *APIKeyValidator {
return &APIKeyValidator{lookup: lookup}
}
// Validate validates an API key and returns the associated user.
func (v *APIKeyValidator) Validate(ctx context.Context, key string) (*User, error) {
if key == "" {
return nil, ErrInvalidAPIKey
}
user, err := v.lookup(ctx, key)
if err != nil {
return nil, err
}
if user == nil {
return nil, ErrInvalidAPIKey
}
return user, nil
}
// StaticAPIKeyValidator validates against a static set of API keys.
// Useful for simple use cases or testing.
type StaticAPIKeyValidator struct {
keys map[string]*User
}
// NewStaticAPIKeyValidator creates a validator with static API keys.
//
// Example:
//
// validator := auth.NewStaticAPIKeyValidator(map[string]*auth.User{
// "sk-test-123": {ID: "user-1", Scopes: []string{"read", "write"}},
// "sk-test-456": {ID: "user-2", Scopes: []string{"read"}},
// })
func NewStaticAPIKeyValidator(keys map[string]*User) *StaticAPIKeyValidator {
return &StaticAPIKeyValidator{keys: keys}
}
// Validate validates an API key against the static key map.
func (v *StaticAPIKeyValidator) Validate(ctx context.Context, key string) (*User, error) {
if key == "" {
return nil, ErrInvalidAPIKey
}
user, ok := v.keys[key]
if !ok {
return nil, ErrInvalidAPIKey
}
return user, nil
}