mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
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:
committed by
GitHub
parent
7195be87b1
commit
32aee9ea4c
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
Generated
+45
@@ -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()
|
||||
|
||||
Generated
+3
@@ -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.
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
|
||||
Generated
+106
@@ -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;
|
||||
Reference in New Issue
Block a user