feat: add DB queries for ai_gateway_coderd_keys (#25564)

Adds Insert, List and Delete queries for `ai_gateway_coderd_keys `
table.
This commit is contained in:
Paweł Banaszewski
2026-06-02 13:25:44 +02:00
committed by GitHub
parent 7195be87b1
commit 32aee9ea4c
8 changed files with 415 additions and 0 deletions
+21
View File
@@ -1907,6 +1907,13 @@ func (q *querier) CustomRoles(ctx context.Context, arg database.CustomRolesParam
return q.db.CustomRoles(ctx, arg)
}
func (q *querier) DeleteAIGatewayKey(ctx context.Context, id uuid.UUID) (database.DeleteAIGatewayKeyRow, error) {
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceAIGatewayKey); err != nil {
return database.DeleteAIGatewayKeyRow{}, err
}
return q.db.DeleteAIGatewayKey(ctx, id)
}
func (q *querier) DeleteAIProviderByID(ctx context.Context, id uuid.UUID) error {
if err := q.authorizeContext(ctx, policy.ActionDelete, rbac.ResourceAIProvider); err != nil {
return err
@@ -5463,6 +5470,13 @@ func (q *querier) InsertAIBridgeUserPrompt(ctx context.Context, arg database.Ins
return q.db.InsertAIBridgeUserPrompt(ctx, arg)
}
func (q *querier) InsertAIGatewayKey(ctx context.Context, arg database.InsertAIGatewayKeyParams) (database.InsertAIGatewayKeyRow, error) {
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceAIGatewayKey); err != nil {
return database.InsertAIGatewayKeyRow{}, err
}
return q.db.InsertAIGatewayKey(ctx, arg)
}
func (q *querier) InsertAIProvider(ctx context.Context, arg database.InsertAIProviderParams) (database.AIProvider, error) {
if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceAIProvider); err != nil {
return database.AIProvider{}, err
@@ -6238,6 +6252,13 @@ func (q *querier) ListAIBridgeUserPromptsByInterceptionIDs(ctx context.Context,
return q.db.ListAIBridgeUserPromptsByInterceptionIDs(ctx, interceptionIDs)
}
func (q *querier) ListAIGatewayKeys(ctx context.Context) ([]database.ListAIGatewayKeysRow, error) {
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceAIGatewayKey); err != nil {
return nil, err
}
return q.db.ListAIGatewayKeys(ctx)
}
func (q *querier) ListBoundaryLogsBySessionID(ctx context.Context, arg database.ListBoundaryLogsBySessionIDParams) ([]database.BoundaryLog, error) {
if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceBoundaryLog); err != nil {
return nil, err
+17
View File
@@ -6638,6 +6638,23 @@ func (s *MethodTestSuite) TestAIBridge() {
dbm.EXPECT().UpdateEncryptedUserAIProviderKey(gomock.Any(), arg).Return(key, nil).AnyTimes()
check.Args(arg).Asserts(rbac.ResourceAIProvider, policy.ActionUpdate).Returns(key)
}))
s.Run("InsertAIGatewayKey", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
params := database.InsertAIGatewayKeyParams{}
row := database.InsertAIGatewayKeyRow{}
dbm.EXPECT().InsertAIGatewayKey(gomock.Any(), params).Return(row, nil).AnyTimes()
check.Args(params).Asserts(rbac.ResourceAIGatewayKey, policy.ActionCreate).Returns(row)
}))
s.Run("ListAIGatewayKeys", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
rows := []database.ListAIGatewayKeysRow{}
dbm.EXPECT().ListAIGatewayKeys(gomock.Any()).Return(rows, nil).AnyTimes()
check.Args().Asserts(rbac.ResourceAIGatewayKey, policy.ActionRead).Returns(rows)
}))
s.Run("DeleteAIGatewayKey", s.Mocked(func(dbm *dbmock.MockStore, _ *gofakeit.Faker, check *expects) {
id := uuid.New()
dbm.EXPECT().DeleteAIGatewayKey(gomock.Any(), id).Return(database.DeleteAIGatewayKeyRow{}, nil).AnyTimes()
check.Args(id).Asserts(rbac.ResourceAIGatewayKey, policy.ActionDelete).Returns(database.DeleteAIGatewayKeyRow{})
}))
}
func (s *MethodTestSuite) TestTelemetry() {
+24
View File
@@ -377,6 +377,14 @@ func (m queryMetricsStore) CustomRoles(ctx context.Context, arg database.CustomR
return r0, r1
}
func (m queryMetricsStore) DeleteAIGatewayKey(ctx context.Context, id uuid.UUID) (database.DeleteAIGatewayKeyRow, error) {
start := time.Now()
r0, r1 := m.s.DeleteAIGatewayKey(ctx, id)
m.queryLatencies.WithLabelValues("DeleteAIGatewayKey").Observe(time.Since(start).Seconds())
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "DeleteAIGatewayKey").Inc()
return r0, r1
}
func (m queryMetricsStore) DeleteAIProviderByID(ctx context.Context, id uuid.UUID) error {
start := time.Now()
r0 := m.s.DeleteAIProviderByID(ctx, id)
@@ -3721,6 +3729,14 @@ func (m queryMetricsStore) InsertAIBridgeUserPrompt(ctx context.Context, arg dat
return r0, r1
}
func (m queryMetricsStore) InsertAIGatewayKey(ctx context.Context, arg database.InsertAIGatewayKeyParams) (database.InsertAIGatewayKeyRow, error) {
start := time.Now()
r0, r1 := m.s.InsertAIGatewayKey(ctx, arg)
m.queryLatencies.WithLabelValues("InsertAIGatewayKey").Observe(time.Since(start).Seconds())
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "InsertAIGatewayKey").Inc()
return r0, r1
}
func (m queryMetricsStore) InsertAIProvider(ctx context.Context, arg database.InsertAIProviderParams) (database.AIProvider, error) {
start := time.Now()
r0, r1 := m.s.InsertAIProvider(ctx, arg)
@@ -4417,6 +4433,14 @@ func (m queryMetricsStore) ListAIBridgeUserPromptsByInterceptionIDs(ctx context.
return r0, r1
}
func (m queryMetricsStore) ListAIGatewayKeys(ctx context.Context) ([]database.ListAIGatewayKeysRow, error) {
start := time.Now()
r0, r1 := m.s.ListAIGatewayKeys(ctx)
m.queryLatencies.WithLabelValues("ListAIGatewayKeys").Observe(time.Since(start).Seconds())
m.queryCounts.WithLabelValues(httpmw.ExtractHTTPRoute(ctx), httpmw.ExtractHTTPMethod(ctx), "ListAIGatewayKeys").Inc()
return r0, r1
}
func (m queryMetricsStore) ListBoundaryLogsBySessionID(ctx context.Context, arg database.ListBoundaryLogsBySessionIDParams) ([]database.BoundaryLog, error) {
start := time.Now()
r0, r1 := m.s.ListBoundaryLogsBySessionID(ctx, arg)
+45
View File
@@ -603,6 +603,21 @@ func (mr *MockStoreMockRecorder) CustomRoles(ctx, arg any) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CustomRoles", reflect.TypeOf((*MockStore)(nil).CustomRoles), ctx, arg)
}
// DeleteAIGatewayKey mocks base method.
func (m *MockStore) DeleteAIGatewayKey(ctx context.Context, id uuid.UUID) (database.DeleteAIGatewayKeyRow, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DeleteAIGatewayKey", ctx, id)
ret0, _ := ret[0].(database.DeleteAIGatewayKeyRow)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// DeleteAIGatewayKey indicates an expected call of DeleteAIGatewayKey.
func (mr *MockStoreMockRecorder) DeleteAIGatewayKey(ctx, id any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteAIGatewayKey", reflect.TypeOf((*MockStore)(nil).DeleteAIGatewayKey), ctx, id)
}
// DeleteAIProviderByID mocks base method.
func (m *MockStore) DeleteAIProviderByID(ctx context.Context, id uuid.UUID) error {
m.ctrl.T.Helper()
@@ -6989,6 +7004,21 @@ func (mr *MockStoreMockRecorder) InsertAIBridgeUserPrompt(ctx, arg any) *gomock.
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InsertAIBridgeUserPrompt", reflect.TypeOf((*MockStore)(nil).InsertAIBridgeUserPrompt), ctx, arg)
}
// InsertAIGatewayKey mocks base method.
func (m *MockStore) InsertAIGatewayKey(ctx context.Context, arg database.InsertAIGatewayKeyParams) (database.InsertAIGatewayKeyRow, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "InsertAIGatewayKey", ctx, arg)
ret0, _ := ret[0].(database.InsertAIGatewayKeyRow)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// InsertAIGatewayKey indicates an expected call of InsertAIGatewayKey.
func (mr *MockStoreMockRecorder) InsertAIGatewayKey(ctx, arg any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InsertAIGatewayKey", reflect.TypeOf((*MockStore)(nil).InsertAIGatewayKey), ctx, arg)
}
// InsertAIProvider mocks base method.
func (m *MockStore) InsertAIProvider(ctx context.Context, arg database.InsertAIProviderParams) (database.AIProvider, error) {
m.ctrl.T.Helper()
@@ -8279,6 +8309,21 @@ func (mr *MockStoreMockRecorder) ListAIBridgeUserPromptsByInterceptionIDs(ctx, i
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListAIBridgeUserPromptsByInterceptionIDs", reflect.TypeOf((*MockStore)(nil).ListAIBridgeUserPromptsByInterceptionIDs), ctx, interceptionIds)
}
// ListAIGatewayKeys mocks base method.
func (m *MockStore) ListAIGatewayKeys(ctx context.Context) ([]database.ListAIGatewayKeysRow, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "ListAIGatewayKeys", ctx)
ret0, _ := ret[0].([]database.ListAIGatewayKeysRow)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// ListAIGatewayKeys indicates an expected call of ListAIGatewayKeys.
func (mr *MockStoreMockRecorder) ListAIGatewayKeys(ctx any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListAIGatewayKeys", reflect.TypeOf((*MockStore)(nil).ListAIGatewayKeys), ctx)
}
// ListAuthorizedAIBridgeClients mocks base method.
func (m *MockStore) ListAuthorizedAIBridgeClients(ctx context.Context, arg database.ListAIBridgeClientsParams, prepared rbac.PreparedAuthorized) ([]string, error) {
m.ctrl.T.Helper()
+3
View File
@@ -101,6 +101,7 @@ type sqlcQuerier interface {
CountUnreadInboxNotificationsByUserID(ctx context.Context, userID uuid.UUID) (int64, error)
CreateUserSecret(ctx context.Context, arg CreateUserSecretParams) (UserSecret, error)
CustomRoles(ctx context.Context, arg CustomRolesParams) ([]CustomRole, error)
DeleteAIGatewayKey(ctx context.Context, id uuid.UUID) (DeleteAIGatewayKeyRow, error)
DeleteAIProviderByID(ctx context.Context, id uuid.UUID) error
DeleteAIProviderKey(ctx context.Context, id uuid.UUID) error
DeleteAPIKeyByID(ctx context.Context, id string) error
@@ -914,6 +915,7 @@ type sqlcQuerier interface {
InsertAIBridgeTokenUsage(ctx context.Context, arg InsertAIBridgeTokenUsageParams) (AIBridgeTokenUsage, error)
InsertAIBridgeToolUsage(ctx context.Context, arg InsertAIBridgeToolUsageParams) (AIBridgeToolUsage, error)
InsertAIBridgeUserPrompt(ctx context.Context, arg InsertAIBridgeUserPromptParams) (AIBridgeUserPrompt, error)
InsertAIGatewayKey(ctx context.Context, arg InsertAIGatewayKeyParams) (InsertAIGatewayKeyRow, error)
InsertAIProvider(ctx context.Context, arg InsertAIProviderParams) (AIProvider, error)
InsertAIProviderKey(ctx context.Context, arg InsertAIProviderKeyParams) (AIProviderKey, error)
InsertAPIKey(ctx context.Context, arg InsertAPIKeyParams) (APIKey, error)
@@ -1048,6 +1050,7 @@ type sqlcQuerier interface {
ListAIBridgeTokenUsagesByInterceptionIDs(ctx context.Context, interceptionIds []uuid.UUID) ([]AIBridgeTokenUsage, error)
ListAIBridgeToolUsagesByInterceptionIDs(ctx context.Context, interceptionIds []uuid.UUID) ([]AIBridgeToolUsage, error)
ListAIBridgeUserPromptsByInterceptionIDs(ctx context.Context, interceptionIds []uuid.UUID) ([]AIBridgeUserPrompt, error)
ListAIGatewayKeys(ctx context.Context) ([]ListAIGatewayKeysRow, error)
// Lists boundary logs for a session, sorted by sequence number ascending.
// Supports optional exclusive sequence number bounds (seq_after, seq_before)
// for fetching events between two known interceptions.
+186
View File
@@ -14733,3 +14733,189 @@ func TestSoftDeleteWorkspaceAgentsByWorkspaceID(t *testing.T) {
err = db.SoftDeleteWorkspaceAgentsByWorkspaceID(ctx, wsEmpty)
require.NoError(t, err)
}
func TestAIGatewayKeysTableConstraints(t *testing.T) {
t.Parallel()
db, _ := dbtestutil.NewDB(t)
ctx := testutil.Context(t, testutil.WaitMedium)
preExsiting := database.InsertAIGatewayKeyParams{
ID: uuid.New(),
Name: "name",
SecretPrefix: "cgw_test__1",
HashedSecret: []byte("first-secret"),
}
_, err := db.InsertAIGatewayKey(ctx, preExsiting)
require.NoError(t, err)
tests := []struct {
name string
params database.InsertAIGatewayKeyParams
expectUniqueErr database.UniqueConstraint
expectCheckErr database.CheckConstraint
}{
{
name: "duplicate name",
params: aiGatewayKeyParams(preExsiting.Name, "cgw_test002"),
expectUniqueErr: database.UniqueAiGatewayKeysNameIndex,
},
{
name: "duplicate secret prefix",
params: aiGatewayKeyParams("different-key", preExsiting.SecretPrefix),
expectUniqueErr: database.UniqueAiGatewayKeysSecretPrefixIndex,
},
{
name: "duplicate hashed secret",
params: database.InsertAIGatewayKeyParams{ID: uuid.New(), Name: "other-name", SecretPrefix: "cgw_1234567", HashedSecret: preExsiting.HashedSecret},
expectUniqueErr: database.UniqueAiGatewayKeysHashedSecretIndex,
},
{
name: "empty name",
params: aiGatewayKeyParams("", "cgw_1234567"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
},
{
name: "name with trailing dash",
params: aiGatewayKeyParams("other-name-", "cgw_1234567"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
},
{
name: "name with consecutive dashes",
params: aiGatewayKeyParams("other--name", "cgw_1234567"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
},
{
name: "name with underscore",
params: aiGatewayKeyParams("other_name", "cgw_1234567"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
},
{
name: "name with space",
params: aiGatewayKeyParams("other name", "cgw_1234567"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
},
{
name: "name with leading dash",
params: aiGatewayKeyParams("-other-name", "cgw_1234567"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
},
{
name: "name longer than 64 characters",
params: aiGatewayKeyParams(strings.Repeat("a", 65), "cgw_1234567"),
expectCheckErr: database.CheckAiGatewayKeysNameCheck,
},
{
name: "empty secret prefix",
params: aiGatewayKeyParams("other-name", ""),
expectCheckErr: database.CheckAiGatewayKeysSecretPrefixCheck,
},
{
name: "invalid secret prefix length",
params: aiGatewayKeyParams("other-name", "cgw_short"),
expectCheckErr: database.CheckAiGatewayKeysSecretPrefixCheck,
},
{
name: "empty hashed secret",
params: database.InsertAIGatewayKeyParams{ID: uuid.New(), Name: "other-name", SecretPrefix: "cgw_1234567"},
expectCheckErr: database.CheckAiGatewayKeysHashedSecretCheck,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
ctx := testutil.Context(t, testutil.WaitShort)
_, err = db.InsertAIGatewayKey(ctx, tc.params)
require.Error(t, err)
requireAIGatewayKeysViolation(t, err, tc.expectUniqueErr, tc.expectCheckErr)
})
}
}
func TestAIGatewayKeysQueries(t *testing.T) {
t.Parallel()
db, _ := dbtestutil.NewDB(t)
ctx := testutil.Context(t, testutil.WaitLong)
first := aiGatewayKeyParams("first-key", "cgw_first__")
second := aiGatewayKeyParams("second-key", "cgw_second_")
second.HashedSecret = []byte("second-secret")
firstRow, err := db.InsertAIGatewayKey(ctx, first)
require.NoError(t, err)
require.Equal(t, first.ID, firstRow.ID)
require.Equal(t, "first-key", firstRow.Name)
require.Equal(t, first.SecretPrefix, firstRow.SecretPrefix)
secondRow, err := db.InsertAIGatewayKey(ctx, second)
require.NoError(t, err)
require.Equal(t, second.ID, secondRow.ID)
require.Equal(t, "second-key", secondRow.Name)
require.Equal(t, second.SecretPrefix, secondRow.SecretPrefix)
keys, err := db.ListAIGatewayKeys(ctx)
require.NoError(t, err)
require.Len(t, keys, 2)
requireAIGatewayKeysRow(t, keys[0], first, firstRow.CreatedAt)
require.False(t, keys[0].LastUsedAt.Valid)
requireAIGatewayKeysRow(t, keys[1], second, secondRow.CreatedAt)
require.False(t, keys[1].LastUsedAt.Valid)
deleted, err := db.DeleteAIGatewayKey(ctx, first.ID)
require.NoError(t, err)
require.Equal(t, first.ID, deleted.ID)
require.Equal(t, first.Name, deleted.Name)
require.Equal(t, first.SecretPrefix, deleted.SecretPrefix)
require.Equal(t, firstRow.CreatedAt, deleted.CreatedAt)
_, err = db.DeleteAIGatewayKey(ctx, first.ID)
require.ErrorIs(t, err, sql.ErrNoRows)
keys, err = db.ListAIGatewayKeys(ctx)
require.NoError(t, err)
require.Len(t, keys, 1)
requireAIGatewayKeysRow(t, keys[0], second, secondRow.CreatedAt)
}
func aiGatewayKeyParams(name string, secretPrefix string) database.InsertAIGatewayKeyParams {
return database.InsertAIGatewayKeyParams{
ID: uuid.New(),
Name: name,
SecretPrefix: secretPrefix,
HashedSecret: []byte("secret"),
}
}
func requireAIGatewayKeysRow(t *testing.T, listRow database.ListAIGatewayKeysRow, insertParams database.InsertAIGatewayKeyParams, insertCreatedAt time.Time) {
t.Helper()
require.Equal(t, insertParams.ID, listRow.ID)
require.Equal(t, insertParams.Name, listRow.Name)
require.Equal(t, insertParams.SecretPrefix, listRow.SecretPrefix)
require.Equal(t, insertCreatedAt, listRow.CreatedAt)
}
func requireAIGatewayKeysViolation(
t *testing.T,
err error,
uniqueConstraint database.UniqueConstraint,
checkConstraint database.CheckConstraint,
) {
t.Helper()
switch {
case uniqueConstraint != "":
require.True(t, database.IsUniqueViolation(err, uniqueConstraint), "expected %q unique violation, got %v", uniqueConstraint, err)
case checkConstraint != "":
require.True(t, database.IsCheckViolation(err, checkConstraint), "expected %q check violation, got %v", checkConstraint, err)
default:
require.FailNow(t, "test case must expect a constraint error")
}
}
+106
View File
@@ -111,6 +111,112 @@ func (q *sqlQuerier) ActivityBumpWorkspace(ctx context.Context, arg ActivityBump
return err
}
const deleteAIGatewayKey = `-- name: DeleteAIGatewayKey :one
DELETE FROM ai_gateway_keys WHERE id = $1
RETURNING id, name, secret_prefix, created_at, last_used_at
`
type DeleteAIGatewayKeyRow struct {
ID uuid.UUID `db:"id" json:"id"`
Name string `db:"name" json:"name"`
SecretPrefix string `db:"secret_prefix" json:"secret_prefix"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
LastUsedAt sql.NullTime `db:"last_used_at" json:"last_used_at"`
}
func (q *sqlQuerier) DeleteAIGatewayKey(ctx context.Context, id uuid.UUID) (DeleteAIGatewayKeyRow, error) {
row := q.db.QueryRowContext(ctx, deleteAIGatewayKey, id)
var i DeleteAIGatewayKeyRow
err := row.Scan(
&i.ID,
&i.Name,
&i.SecretPrefix,
&i.CreatedAt,
&i.LastUsedAt,
)
return i, err
}
const insertAIGatewayKey = `-- name: InsertAIGatewayKey :one
INSERT INTO ai_gateway_keys (id, name, secret_prefix, hashed_secret, created_at)
VALUES ($1, $4, $2, $3, NOW())
RETURNING id, name, secret_prefix, created_at
`
type InsertAIGatewayKeyParams struct {
ID uuid.UUID `db:"id" json:"id"`
SecretPrefix string `db:"secret_prefix" json:"secret_prefix"`
HashedSecret []byte `db:"hashed_secret" json:"hashed_secret"`
Name string `db:"name" json:"name"`
}
type InsertAIGatewayKeyRow struct {
ID uuid.UUID `db:"id" json:"id"`
Name string `db:"name" json:"name"`
SecretPrefix string `db:"secret_prefix" json:"secret_prefix"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
}
func (q *sqlQuerier) InsertAIGatewayKey(ctx context.Context, arg InsertAIGatewayKeyParams) (InsertAIGatewayKeyRow, error) {
row := q.db.QueryRowContext(ctx, insertAIGatewayKey,
arg.ID,
arg.SecretPrefix,
arg.HashedSecret,
arg.Name,
)
var i InsertAIGatewayKeyRow
err := row.Scan(
&i.ID,
&i.Name,
&i.SecretPrefix,
&i.CreatedAt,
)
return i, err
}
const listAIGatewayKeys = `-- name: ListAIGatewayKeys :many
SELECT id, name, secret_prefix, created_at, last_used_at
FROM ai_gateway_keys
ORDER BY created_at ASC
`
type ListAIGatewayKeysRow struct {
ID uuid.UUID `db:"id" json:"id"`
Name string `db:"name" json:"name"`
SecretPrefix string `db:"secret_prefix" json:"secret_prefix"`
CreatedAt time.Time `db:"created_at" json:"created_at"`
LastUsedAt sql.NullTime `db:"last_used_at" json:"last_used_at"`
}
func (q *sqlQuerier) ListAIGatewayKeys(ctx context.Context) ([]ListAIGatewayKeysRow, error) {
rows, err := q.db.QueryContext(ctx, listAIGatewayKeys)
if err != nil {
return nil, err
}
defer rows.Close()
var items []ListAIGatewayKeysRow
for rows.Next() {
var i ListAIGatewayKeysRow
if err := rows.Scan(
&i.ID,
&i.Name,
&i.SecretPrefix,
&i.CreatedAt,
&i.LastUsedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Close(); err != nil {
return nil, err
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const deleteAIProviderKey = `-- name: DeleteAIProviderKey :exec
DELETE FROM
ai_provider_keys
@@ -0,0 +1,13 @@
-- name: InsertAIGatewayKey :one
INSERT INTO ai_gateway_keys (id, name, secret_prefix, hashed_secret, created_at)
VALUES ($1, @name, $2, $3, NOW())
RETURNING id, name, secret_prefix, created_at;
-- name: ListAIGatewayKeys :many
SELECT id, name, secret_prefix, created_at, last_used_at
FROM ai_gateway_keys
ORDER BY created_at ASC;
-- name: DeleteAIGatewayKey :one
DELETE FROM ai_gateway_keys WHERE id = $1
RETURNING id, name, secret_prefix, created_at, last_used_at;