Documentation
¶
Overview ¶
Package apikey issues machine credentials sent via the X-API-KEY header, with expiry and last-used tracking. Keys are the user's own API keys; resource-server scopes live in the apiaccess module.
Index ¶
- Variables
- func HashToken(token string) string
- func NewToken() (string, error)
- type APIKey
- type APIKeyID
- type CreateParams
- type ListParams
- type Page
- type PostgresStore
- func (s *PostgresStore) Create(ctx context.Context, userID string, keyHash string, params CreateParams) (APIKey, error)
- func (s *PostgresStore) ListForUser(ctx context.Context, userID string, params ListParams) ([]APIKey, int, error)
- func (s *PostgresStore) Renew(ctx context.Context, userID string, id APIKeyID, keyHash string, ...) (APIKey, error)
- func (s *PostgresStore) Revoke(ctx context.Context, userID string, id APIKeyID) error
- func (s *PostgresStore) ValidByHash(ctx context.Context, keyHash string) (APIKey, user.User, error)
- type RenewParams
- type Service
- func (s *Service) Create(ctx context.Context, userID string, params CreateParams) (APIKey, string, error)
- func (s *Service) List(ctx context.Context, userID string, params ListParams) ([]APIKey, int, error)
- func (s *Service) Name() string
- func (s *Service) RPCService() (string, http.Handler)
- func (s *Service) Renew(ctx context.Context, userID string, id APIKeyID, params RenewParams) (APIKey, string, error)
- func (s *Service) Revoke(ctx context.Context, userID string, id APIKeyID) error
- func (s *Service) Verify(ctx context.Context, rawKey string) (kernel.Principal, error)
- type ServiceOption
- type Store
Constants ¶
This section is empty.
Variables ¶
var ( ErrNotFound = errors.New("apikey: key not found") ErrDuplicate = errors.New("apikey: key name already exists") ErrNotExpired = errors.New("apikey: key is not expired yet") ErrInvalidCreds = errors.New("apikey: key is invalid or expired") )
Errors surfaced by the store and service; the handler maps them to statuses.
Functions ¶
Types ¶
type APIKey ¶
type APIKey struct {
ID APIKeyID `json:"id"`
Name string `json:"name"`
Description *string `json:"description,omitzero"`
ExpiresAt time.Time `json:"expires_at"`
CreatedAt time.Time `json:"created_at"`
LastUsedAt *time.Time `json:"last_used_at,omitzero"`
ExpirationEmailSentAt *time.Time `json:"-"`
}
APIKey is one machine credential row.
type APIKeyID ¶
Typed IDs for the api key tables: UUIDv7 suffix, snake_case prefix matching the singular table name.
type CreateParams ¶
CreateParams carries the POST /api-keys fields.
func (*CreateParams) Validate ¶
func (p *CreateParams) Validate() error
Validate checks the name and expiry.
type ListParams ¶
type ListParams struct {
Page
}
ListParams narrows and pages the listing; keys are scoped to the authenticated user.
type Page ¶
Page is the store-level paging window: plain ints with no HTTP dependency. The handler converts the request query into it.
type PostgresStore ¶
type PostgresStore struct {
// contains filtered or unexported fields
}
PostgresStore persists keys in public.api_keys.
func NewPostgresStore ¶
func NewPostgresStore(exec datastore.Executor) *PostgresStore
NewPostgresStore builds the production key store.
func (*PostgresStore) Create ¶
func (s *PostgresStore) Create(ctx context.Context, userID string, keyHash string, params CreateParams) (APIKey, error)
Create inserts a key; uuidv7() fills the ID.
func (*PostgresStore) ListForUser ¶
func (s *PostgresStore) ListForUser(ctx context.Context, userID string, params ListParams) ([]APIKey, int, error)
ListForUser pages the keys owned by one user, newest first.
func (*PostgresStore) Renew ¶
func (s *PostgresStore) Renew(ctx context.Context, userID string, id APIKeyID, keyHash string, expiresAt time.Time) (APIKey, error)
Renew rotates the token hash and expiry of an expired key.
func (*PostgresStore) ValidByHash ¶
ValidByHash resolves an unexpired key by hash, atomically bumping last_used_at in the same statement.
type RenewParams ¶
RenewParams carries the POST /api-keys/{id}/renew fields.
func (*RenewParams) Validate ¶
func (p *RenewParams) Validate() error
Validate enforces the future-expiry constraint.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service holds the API key business rules and HTTP surface. Guards are not stored: the mount call receives the route groups, and the self surface reads the principal from the request context.
func NewService ¶
func NewService(store Store, recorder identity.Recorder, opts ...ServiceOption) *Service
NewService builds the feature on the given store.
func (*Service) Create ¶
func (s *Service) Create(ctx context.Context, userID string, params CreateParams) (APIKey, string, error)
Create mints a key for the current user and returns it with the one-time token.
func (*Service) List ¶
func (s *Service) List(ctx context.Context, userID string, params ListParams) ([]APIKey, int, error)
List returns the caller's keys with pagination.
func (*Service) RPCService ¶ added in v0.0.12
RPCService returns the Connect registration for the API key surface: the procedure prefix and the handler. The surface is scoped to the caller — the same contract as the REST routes — so the composition root wraps it with the RPC authentication middleware. Minting and renewing demand a session principal: a machine credential must not extend itself.
func (*Service) Renew ¶
func (s *Service) Renew(ctx context.Context, userID string, id APIKeyID, params RenewParams) (APIKey, string, error)
Renew rotates an expired key and returns the new one-time token.
type ServiceOption ¶
type ServiceOption func(*Service)
ServiceOption configures the API key feature.
type Store ¶
type Store interface {
Create(ctx context.Context, userID string, keyHash string, params CreateParams) (APIKey, error)
ListForUser(ctx context.Context, userID string, params ListParams) ([]APIKey, int, error)
Revoke(ctx context.Context, userID string, id APIKeyID) error
// Renew rotates the token hash and expiry; allowed only when
// the key is already expired.
Renew(ctx context.Context, userID string, id APIKeyID, keyHash string, expiresAt time.Time) (APIKey, error)
// ValidByHash resolves a hash to the owning user, atomically
// bumping last_used_at (UPDATE ... RETURNING).
ValidByHash(ctx context.Context, keyHash string) (APIKey, user.User, error)
}
Store abstracts API key persistence.