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.
67 lines
1.4 KiB
Go
67 lines
1.4 KiB
Go
package httpapi
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"sync"
|
|
|
|
"evobgp/internal/store"
|
|
)
|
|
|
|
type apiKeyResolver struct {
|
|
mu sync.RWMutex
|
|
|
|
envByToken map[string]apiKeyRecord
|
|
byHash map[string]apiKeyRecord
|
|
}
|
|
|
|
func newAPIKeyResolver(envSpec string, st store.Backend) (*apiKeyResolver, error) {
|
|
r := &apiKeyResolver{
|
|
envByToken: make(map[string]apiKeyRecord),
|
|
byHash: make(map[string]apiKeyRecord),
|
|
}
|
|
for _, rec := range parseAPIKeysSpec(envSpec) {
|
|
r.envByToken[rec.token] = rec
|
|
}
|
|
return r, r.reloadFromStore(st)
|
|
}
|
|
|
|
func (r *apiKeyResolver) reloadFromStore(st store.Backend) error {
|
|
rows, err := st.ListActiveAPIKeyHashes()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
byHash := make(map[string]apiKeyRecord, len(rows))
|
|
for _, row := range rows {
|
|
if len(row.TokenHash) != 32 {
|
|
continue
|
|
}
|
|
byHash[hex.EncodeToString(row.TokenHash)] = apiKeyRecord{
|
|
token: "",
|
|
tenantID: row.TenantID,
|
|
role: row.Role,
|
|
keyID: row.ID,
|
|
}
|
|
}
|
|
r.mu.Lock()
|
|
r.byHash = byHash
|
|
r.mu.Unlock()
|
|
return nil
|
|
}
|
|
|
|
func (r *apiKeyResolver) Reload(st store.Backend) error {
|
|
return r.reloadFromStore(st)
|
|
}
|
|
|
|
func (r *apiKeyResolver) Lookup(raw string) (apiKeyRecord, bool) {
|
|
r.mu.RLock()
|
|
defer r.mu.RUnlock()
|
|
if rec, ok := r.envByToken[raw]; ok {
|
|
return rec, true
|
|
}
|
|
sum := sha256.Sum256([]byte(raw))
|
|
key := hex.EncodeToString(sum[:])
|
|
rec, ok := r.byHash[key]
|
|
return rec, ok
|
|
}
|