package bots import ( "context" "crypto/rand" "encoding/hex" "errors" "time" "atlas9.dev/c/core" "atlas9.dev/c/core/iam" ) type Key struct { ID core.ID Tenant core.ID Bot core.ID Secret string CreatedAt time.Time ExpiresAt time.Time } func NewKey(tenant, bot core.ID) (*Key, string, error) { // Generate a random secret. Encode as a hex string. data := make([]byte, 32) rand.Read(data) sec := hex.EncodeToString(data) // TODO encrypt keys. key := &Key{ ID: core.NewID("key"), Tenant: tenant, Bot: bot, Secret: sec, CreatedAt: time.Now(), ExpiresAt: time.Now().Add(time.Hour * 24), } return key, sec, nil } var Cap_BotKeys_Read = iam.NewCap("BotKeys_Read") var Cap_BotKeys_Write = iam.NewCap("BotKeys_Write") // KeyStore defines the interface for persisting bot keys. type KeyStore interface { Create(ctx context.Context, key *Key) error SetExpiration(ctx context.Context, tenant, keyID core.ID, expiration time.Time) error Get(ctx context.Context, tenant, keyID core.ID, out *Key) error List(ctx context.Context, tenant core.ID, out *core.Page[Key]) error } var ErrKeyNotFound = errors.New("api key not found") var ErrInvalidSignature = errors.New("invalid signature")