feat(api): implement API key management and authentication enhancements
CI / changes (push) Successful in 7s
CI / commitlint (push) Has been skipped
CI / openapi (push) Successful in 25s
CI / web (push) Successful in 28s
CI / go (push) Failing after 24s
CI / bird2 (push) Has been skipped
CI / release (push) Has been skipped

- Added endpoints for managing API keys, including creation, retrieval, updating, and revocation.
- Introduced a new Auth session endpoint to retrieve current tenant and role information.
- Updated the authentication middleware to support API key-based authentication and track last used timestamps.
- Enhanced documentation to reflect new API key functionalities and usage guidelines.
- Improved logging for demo authentication scenarios.
This commit is contained in:
Denozordec
2026-05-21 11:26:17 +07:00
parent 880d77810a
commit 6329a4df27
28 changed files with 1682 additions and 39 deletions
+63
View File
@@ -2,6 +2,7 @@ package store
import (
"context"
"strings"
"time"
)
@@ -88,6 +89,15 @@ type Backend interface {
ListGlobalSettings(tenantID string) (map[string]any, error)
PatchGlobalSettings(tenantID string, patch map[string]any) error
ListAPIKeys(tenantID string) ([]*APIKey, error)
GetAPIKey(tenantID, id string) (*APIKey, error)
CreateAPIKey(tenantID string, in *APIKeyCreate) (*APIKeyWithSecret, error)
UpdateAPIKey(tenantID, id string, patch *APIKeyPatch) (*APIKey, error)
RevokeAPIKey(tenantID, id string) error
RotateAPIKey(tenantID, id string) (*APIKeyWithSecret, error)
ListActiveAPIKeyHashes() ([]APIKeyAuthRow, error)
TouchAPIKeyLastUsed(id string) error
// Module prefix snapshots cache last successful collect per module (pipeline ingest/render).
GetModulePrefixSnapshot(tenantID, moduleID string) (*ModulePrefixSnapshot, bool, error)
SetModulePrefixSnapshot(tenantID, moduleID, inputHash string, prefixes []PrefixRow) error
@@ -227,6 +237,59 @@ type CommunityPatch struct {
ValueJSON *string `json:"value_json,omitempty"`
}
// APIKey is tenant-scoped API key metadata (secret never stored in plaintext).
type APIKey struct {
ID string `json:"id"`
TenantID string `json:"tenant_id,omitempty"`
Name string `json:"name"`
Role string `json:"role"`
Prefix string `json:"prefix"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
RevokedAt *time.Time `json:"revoked_at,omitempty"`
LastUsedAt *time.Time `json:"last_used_at,omitempty"`
}
// APIKeyCreate is input for issuing a new key.
type APIKeyCreate struct {
Name string `json:"name"`
Role string `json:"role"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
}
// APIKeyPatch is a partial update (role change affects auth after resolver reload).
type APIKeyPatch struct {
Name *string `json:"name,omitempty"`
Role *string `json:"role,omitempty"`
ExpiresAt *time.Time `json:"expires_at,omitempty"`
ClearExpiresAt bool `json:"-"`
}
// APIKeyWithSecret is returned only on create/rotate.
type APIKeyWithSecret struct {
APIKey
Token string `json:"token"`
}
// APIKeyAuthRow is used to build the in-process auth index.
type APIKeyAuthRow struct {
ID string
TenantID string
Role string
TokenHash []byte
}
// ValidAPIKeyRole reports whether role is allowed for API keys.
func ValidAPIKeyRole(role string) bool {
switch strings.ToLower(strings.TrimSpace(role)) {
case "viewer", "editor", "operator", "node":
return true
default:
return false
}
}
type PeerPatch struct {
Neighbor *string `json:"neighbor,omitempty"`
RemoteASN *int64 `json:"remote_asn,omitempty"`