Files
codit/backend/internal/db/principal_api_keys.go

122 lines
3.7 KiB
Go

package db
import "database/sql"
import "time"
import "codit/internal/models"
import "codit/internal/util"
func (s *Store) CreatePrincipalAPIKey(principalID string, name string, tokenHash string, prefix string, expiresAt int64) (models.PrincipalAPIKey, error) {
var key models.PrincipalAPIKey
var err error
var now time.Time
var nowUnix int64
var id string
id, err = util.NewID()
if err != nil {
return key, err
}
now = time.Now().UTC()
nowUnix = now.Unix()
key = models.PrincipalAPIKey{
ID: id,
PrincipalID: principalID,
Name: name,
Prefix: prefix,
CreatedAt: nowUnix,
LastUsedAt: 0,
ExpiresAt: expiresAt,
Disabled: false,
}
_, err = s.Exec(`INSERT INTO principal_api_keys (public_id, principal_id, name, token_hash, token_prefix, created_at, last_used_at, expires_at, disabled)
VALUES (?, (SELECT id FROM service_principals WHERE public_id = ?), ?, ?, ?, ?, ?, ?, ?)`,
key.ID, key.PrincipalID, key.Name, tokenHash, key.Prefix, key.CreatedAt, key.LastUsedAt, key.ExpiresAt, key.Disabled)
return key, err
}
func (s *Store) ListPrincipalAPIKeys(principalID string) ([]models.PrincipalAPIKey, error) {
var rows *sql.Rows
var err error
var keys []models.PrincipalAPIKey
var key models.PrincipalAPIKey
rows, err = s.Query(`SELECT k.public_id, p.public_id, k.name, k.token_prefix, k.created_at, k.last_used_at, k.expires_at, k.disabled
FROM principal_api_keys k
JOIN service_principals p ON p.id = k.principal_id
WHERE p.public_id = ?
ORDER BY k.created_at DESC`, principalID)
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
err = rows.Scan(&key.ID, &key.PrincipalID, &key.Name, &key.Prefix, &key.CreatedAt, &key.LastUsedAt, &key.ExpiresAt, &key.Disabled)
if err != nil {
return nil, err
}
keys = append(keys, key)
}
return keys, rows.Err()
}
func (s *Store) DeletePrincipalAPIKey(principalID string, id string) error {
var err error
_, err = s.Exec(`DELETE FROM principal_api_keys WHERE public_id = ? AND principal_id = (SELECT id FROM service_principals WHERE public_id = ?)`, id, principalID)
return err
}
func (s *Store) SetPrincipalAPIKeyDisabled(principalID string, id string, disabled bool) error {
var err error
_, err = s.Exec(`UPDATE principal_api_keys SET disabled = ? WHERE public_id = ? AND principal_id = (SELECT id FROM service_principals WHERE public_id = ?)`, disabled, id, principalID)
return err
}
func (s *Store) GetPrincipalByAPIKeyHash(tokenHash string) (models.ServicePrincipal, error) {
var principal models.ServicePrincipal
var tx *sql.Tx
var owned bool
var row *sql.Row
var keyID int64
var now time.Time
var nowUnix int64
var currentUnix int64
var err error
tx, owned, err = s.begin()
if err != nil {
return principal, err
}
now = time.Now().UTC()
currentUnix = now.Unix()
row = tx.QueryRow(`
SELECT p.public_id, p.name, p.description, p.is_admin, p.disabled, p.created_at, p.updated_at, k.id
FROM principal_api_keys k
JOIN service_principals p ON p.id = k.principal_id
WHERE k.token_hash = ?
AND p.disabled = 0
AND k.disabled = 0
AND (k.expires_at = 0 OR k.expires_at > ?)
LIMIT 1
`, tokenHash, currentUnix)
err = row.Scan(&principal.ID, &principal.Name, &principal.Description, &principal.IsAdmin, &principal.Disabled, &principal.CreatedAt, &principal.UpdatedAt, &keyID)
if err != nil {
rollbackIfOwned(tx, owned)
return principal, err
}
now = time.Now().UTC()
nowUnix = now.Unix()
_, err = tx.Exec(`UPDATE principal_api_keys SET last_used_at = ? WHERE id = ?`, nowUnix, keyID)
if err != nil {
rollbackIfOwned(tx, owned)
return principal, err
}
err = commitIfOwned(tx, owned)
if err != nil {
return principal, err
}
return principal, nil
}