Files
Claude 1cc41cb00b feat(server): open-connector service policy and admin operations API
Add connector_service_policy (per-service publish switch, tool allowlist,
user allowlist) and gate the open-connector catalog, connect flows and task
overlays on it. Publish open_connector_apps from whether the integration is
wired instead of a feature flag, and drop OPEN_CONNECTOR_API_KEY_SERVICES.
Expose /api/admin/open-connector/* (health probe, service catalog with
policy and connection counts, connections by user, audited enable/disable
and policy writes through runAdminAction).

Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01G4Tynn8YQnR5koJTSvFC62
2026-10-21 05:59:04 +00:00

726 lines
22 KiB
Go

// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.31.1
// source: connector.sql
package db
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const adminCountConnectorConnectionsByService = `-- name: AdminCountConnectorConnectionsByService :many
SELECT service,
count(*) FILTER (WHERE status = 'active')::bigint AS active_count,
count(*) FILTER (WHERE status = 'reauth_required')::bigint AS reauth_count,
count(*) FILTER (WHERE status = 'revoked')::bigint AS revoked_count,
count(DISTINCT user_id) FILTER (WHERE status <> 'revoked')::bigint AS user_count
FROM user_connector_connection
WHERE provider = $1
GROUP BY service
ORDER BY service ASC
`
type AdminCountConnectorConnectionsByServiceRow struct {
Service string `json:"service"`
ActiveCount int64 `json:"active_count"`
ReauthCount int64 `json:"reauth_count"`
RevokedCount int64 `json:"revoked_count"`
UserCount int64 `json:"user_count"`
}
// =====================
// Connector connection counts (platform admin)
// =====================
func (q *Queries) AdminCountConnectorConnectionsByService(ctx context.Context, provider string) ([]AdminCountConnectorConnectionsByServiceRow, error) {
rows, err := q.db.Query(ctx, adminCountConnectorConnectionsByService, provider)
if err != nil {
return nil, err
}
defer rows.Close()
items := []AdminCountConnectorConnectionsByServiceRow{}
for rows.Next() {
var i AdminCountConnectorConnectionsByServiceRow
if err := rows.Scan(
&i.Service,
&i.ActiveCount,
&i.ReauthCount,
&i.RevokedCount,
&i.UserCount,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const adminCountConnectorUsers = `-- name: AdminCountConnectorUsers :one
SELECT count(DISTINCT c.user_id)
FROM user_connector_connection c
JOIN "user" u ON u.id = c.user_id
WHERE c.provider = $1
AND ($2::text IS NULL OR c.service = $2::text)
AND ($3::text IS NULL
OR u.email ILIKE '%' || $3::text || '%'
OR u.name ILIKE '%' || $3::text || '%')
`
type AdminCountConnectorUsersParams struct {
Provider string `json:"provider"`
Service pgtype.Text `json:"service"`
Q pgtype.Text `json:"q"`
}
func (q *Queries) AdminCountConnectorUsers(ctx context.Context, arg AdminCountConnectorUsersParams) (int64, error) {
row := q.db.QueryRow(ctx, adminCountConnectorUsers, arg.Provider, arg.Service, arg.Q)
var count int64
err := row.Scan(&count)
return count, err
}
const adminListConnectorUsers = `-- name: AdminListConnectorUsers :many
SELECT u.id AS user_id, u.name, u.email, u.disabled_at,
count(*) FILTER (WHERE c.status = 'active')::bigint AS active_count,
count(*) FILTER (WHERE c.status = 'reauth_required')::bigint AS reauth_count,
count(*) FILTER (WHERE c.status = 'revoked')::bigint AS revoked_count,
COALESCE(array_agg(DISTINCT c.service) FILTER (WHERE c.status <> 'revoked'), '{}')::text[] AS services,
max(c.connected_at)::timestamptz AS last_connected_at
FROM user_connector_connection c
JOIN "user" u ON u.id = c.user_id
WHERE c.provider = $1
AND ($2::text IS NULL OR c.service = $2::text)
AND ($3::text IS NULL
OR u.email ILIKE '%' || $3::text || '%'
OR u.name ILIKE '%' || $3::text || '%')
GROUP BY u.id, u.name, u.email, u.disabled_at
ORDER BY active_count DESC, u.email ASC
LIMIT $5 OFFSET $4
`
type AdminListConnectorUsersParams struct {
Provider string `json:"provider"`
Service pgtype.Text `json:"service"`
Q pgtype.Text `json:"q"`
PageOffset int32 `json:"page_offset"`
PageLimit int32 `json:"page_limit"`
}
type AdminListConnectorUsersRow struct {
UserID pgtype.UUID `json:"user_id"`
Name string `json:"name"`
Email string `json:"email"`
DisabledAt pgtype.Timestamptz `json:"disabled_at"`
ActiveCount int64 `json:"active_count"`
ReauthCount int64 `json:"reauth_count"`
RevokedCount int64 `json:"revoked_count"`
Services []string `json:"services"`
LastConnectedAt pgtype.Timestamptz `json:"last_connected_at"`
}
func (q *Queries) AdminListConnectorUsers(ctx context.Context, arg AdminListConnectorUsersParams) ([]AdminListConnectorUsersRow, error) {
rows, err := q.db.Query(ctx, adminListConnectorUsers,
arg.Provider,
arg.Service,
arg.Q,
arg.PageOffset,
arg.PageLimit,
)
if err != nil {
return nil, err
}
defer rows.Close()
items := []AdminListConnectorUsersRow{}
for rows.Next() {
var i AdminListConnectorUsersRow
if err := rows.Scan(
&i.UserID,
&i.Name,
&i.Email,
&i.DisabledAt,
&i.ActiveCount,
&i.ReauthCount,
&i.RevokedCount,
&i.Services,
&i.LastConnectedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const consumeConnectorOAuthState = `-- name: ConsumeConnectorOAuthState :one
UPDATE connector_oauth_state
SET consumed_at = $1
WHERE nonce_hash = $2 AND consumed_at IS NULL AND expires_at > $1
RETURNING nonce_hash, provider, user_id, service, request_id, expires_at, consumed_at, created_at
`
type ConsumeConnectorOAuthStateParams struct {
Now pgtype.Timestamptz `json:"now"`
NonceHash []byte `json:"nonce_hash"`
}
// Atomic single-use: the first caller gets the row, replays get no rows.
func (q *Queries) ConsumeConnectorOAuthState(ctx context.Context, arg ConsumeConnectorOAuthStateParams) (ConnectorOauthState, error) {
row := q.db.QueryRow(ctx, consumeConnectorOAuthState, arg.Now, arg.NonceHash)
var i ConnectorOauthState
err := row.Scan(
&i.NonceHash,
&i.Provider,
&i.UserID,
&i.Service,
&i.RequestID,
&i.ExpiresAt,
&i.ConsumedAt,
&i.CreatedAt,
)
return i, err
}
const deleteExpiredConnectorOAuthStates = `-- name: DeleteExpiredConnectorOAuthStates :execrows
DELETE FROM connector_oauth_state WHERE expires_at < $1
`
func (q *Queries) DeleteExpiredConnectorOAuthStates(ctx context.Context, now pgtype.Timestamptz) (int64, error) {
result, err := q.db.Exec(ctx, deleteExpiredConnectorOAuthStates, now)
if err != nil {
return 0, err
}
return result.RowsAffected(), nil
}
const existsPendingConnectorOAuthForService = `-- name: ExistsPendingConnectorOAuthForService :one
SELECT EXISTS (
SELECT 1 FROM connector_oauth_state
WHERE provider = $1 AND service = $2
AND consumed_at IS NULL AND expires_at > $3
AND user_id <> $4
)
`
type ExistsPendingConnectorOAuthForServiceParams struct {
Provider string `json:"provider"`
Service string `json:"service"`
Now pgtype.Timestamptz `json:"now"`
UserID pgtype.UUID `json:"user_id"`
}
// True when a different user has an unconsumed, unexpired connect for the
// service (open-connector has one owner, so a second connect would supersede it).
func (q *Queries) ExistsPendingConnectorOAuthForService(ctx context.Context, arg ExistsPendingConnectorOAuthForServiceParams) (bool, error) {
row := q.db.QueryRow(ctx, existsPendingConnectorOAuthForService,
arg.Provider,
arg.Service,
arg.Now,
arg.UserID,
)
var exists bool
err := row.Scan(&exists)
return exists, err
}
const getConnectorOAuthStateByNonceHash = `-- name: GetConnectorOAuthStateByNonceHash :one
SELECT nonce_hash, provider, user_id, service, request_id, expires_at, consumed_at, created_at FROM connector_oauth_state
WHERE nonce_hash = $1 AND consumed_at IS NULL AND expires_at > $2
`
type GetConnectorOAuthStateByNonceHashParams struct {
NonceHash []byte `json:"nonce_hash"`
Now pgtype.Timestamptz `json:"now"`
}
func (q *Queries) GetConnectorOAuthStateByNonceHash(ctx context.Context, arg GetConnectorOAuthStateByNonceHashParams) (ConnectorOauthState, error) {
row := q.db.QueryRow(ctx, getConnectorOAuthStateByNonceHash, arg.NonceHash, arg.Now)
var i ConnectorOauthState
err := row.Scan(
&i.NonceHash,
&i.Provider,
&i.UserID,
&i.Service,
&i.RequestID,
&i.ExpiresAt,
&i.ConsumedAt,
&i.CreatedAt,
)
return i, err
}
const getConnectorServicePolicy = `-- name: GetConnectorServicePolicy :one
SELECT provider, service, enabled, allowed_tools, allowed_user_ids, updated_by, created_at, updated_at FROM connector_service_policy
WHERE provider = $1 AND service = $2
`
type GetConnectorServicePolicyParams struct {
Provider string `json:"provider"`
Service string `json:"service"`
}
func (q *Queries) GetConnectorServicePolicy(ctx context.Context, arg GetConnectorServicePolicyParams) (ConnectorServicePolicy, error) {
row := q.db.QueryRow(ctx, getConnectorServicePolicy, arg.Provider, arg.Service)
var i ConnectorServicePolicy
err := row.Scan(
&i.Provider,
&i.Service,
&i.Enabled,
&i.AllowedTools,
&i.AllowedUserIds,
&i.UpdatedBy,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const getUserConnectorConnection = `-- name: GetUserConnectorConnection :one
SELECT id, provider, user_id, service, connection_id, connection_name, auth_type, status, is_default, label, connected_at, last_used_at, created_at, updated_at FROM user_connector_connection
WHERE id = $1 AND user_id = $2
`
type GetUserConnectorConnectionParams struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
}
// Owner-scoped lookup so one user cannot act on another's connection by
// guessing the UUID.
func (q *Queries) GetUserConnectorConnection(ctx context.Context, arg GetUserConnectorConnectionParams) (UserConnectorConnection, error) {
row := q.db.QueryRow(ctx, getUserConnectorConnection, arg.ID, arg.UserID)
var i UserConnectorConnection
err := row.Scan(
&i.ID,
&i.Provider,
&i.UserID,
&i.Service,
&i.ConnectionID,
&i.ConnectionName,
&i.AuthType,
&i.Status,
&i.IsDefault,
&i.Label,
&i.ConnectedAt,
&i.LastUsedAt,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const insertConnectorOAuthState = `-- name: InsertConnectorOAuthState :exec
INSERT INTO connector_oauth_state (nonce_hash, provider, user_id, service, request_id, expires_at)
VALUES ($1, $2, $3, $4, $5, $6)
`
type InsertConnectorOAuthStateParams struct {
NonceHash []byte `json:"nonce_hash"`
Provider string `json:"provider"`
UserID pgtype.UUID `json:"user_id"`
Service string `json:"service"`
RequestID string `json:"request_id"`
ExpiresAt pgtype.Timestamptz `json:"expires_at"`
}
// =====================
// Connector OAuth state (in-flight connects)
// =====================
func (q *Queries) InsertConnectorOAuthState(ctx context.Context, arg InsertConnectorOAuthStateParams) error {
_, err := q.db.Exec(ctx, insertConnectorOAuthState,
arg.NonceHash,
arg.Provider,
arg.UserID,
arg.Service,
arg.RequestID,
arg.ExpiresAt,
)
return err
}
const listConnectorServicePolicies = `-- name: ListConnectorServicePolicies :many
SELECT provider, service, enabled, allowed_tools, allowed_user_ids, updated_by, created_at, updated_at FROM connector_service_policy
WHERE provider = $1
ORDER BY service ASC
`
// =====================
// Connector service policy (platform admin)
// =====================
func (q *Queries) ListConnectorServicePolicies(ctx context.Context, provider string) ([]ConnectorServicePolicy, error) {
rows, err := q.db.Query(ctx, listConnectorServicePolicies, provider)
if err != nil {
return nil, err
}
defer rows.Close()
items := []ConnectorServicePolicy{}
for rows.Next() {
var i ConnectorServicePolicy
if err := rows.Scan(
&i.Provider,
&i.Service,
&i.Enabled,
&i.AllowedTools,
&i.AllowedUserIds,
&i.UpdatedBy,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listUserConnectorConnections = `-- name: ListUserConnectorConnections :many
SELECT id, provider, user_id, service, connection_id, connection_name, auth_type, status, is_default, label, connected_at, last_used_at, created_at, updated_at FROM user_connector_connection
WHERE provider = $1 AND user_id = $2 AND status <> 'revoked'
ORDER BY service ASC, is_default DESC, connected_at ASC
`
type ListUserConnectorConnectionsParams struct {
Provider string `json:"provider"`
UserID pgtype.UUID `json:"user_id"`
}
// Non-revoked connections (active and reauth_required) so the owner can see and
// repair the latter; callers that mount connections filter on status = 'active'.
// Default connection first within each service.
func (q *Queries) ListUserConnectorConnections(ctx context.Context, arg ListUserConnectorConnectionsParams) ([]UserConnectorConnection, error) {
rows, err := q.db.Query(ctx, listUserConnectorConnections, arg.Provider, arg.UserID)
if err != nil {
return nil, err
}
defer rows.Close()
items := []UserConnectorConnection{}
for rows.Next() {
var i UserConnectorConnection
if err := rows.Scan(
&i.ID,
&i.Provider,
&i.UserID,
&i.Service,
&i.ConnectionID,
&i.ConnectionName,
&i.AuthType,
&i.Status,
&i.IsDefault,
&i.Label,
&i.ConnectedAt,
&i.LastUsedAt,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const listUserConnectorConnectionsByProviderAndStatus = `-- name: ListUserConnectorConnectionsByProviderAndStatus :many
SELECT id, provider, user_id, service, connection_id, connection_name, auth_type, status, is_default, label, connected_at, last_used_at, created_at, updated_at FROM user_connector_connection
WHERE provider = $1 AND status = $2
ORDER BY created_at ASC
`
type ListUserConnectorConnectionsByProviderAndStatusParams struct {
Provider string `json:"provider"`
Status string `json:"status"`
}
func (q *Queries) ListUserConnectorConnectionsByProviderAndStatus(ctx context.Context, arg ListUserConnectorConnectionsByProviderAndStatusParams) ([]UserConnectorConnection, error) {
rows, err := q.db.Query(ctx, listUserConnectorConnectionsByProviderAndStatus, arg.Provider, arg.Status)
if err != nil {
return nil, err
}
defer rows.Close()
items := []UserConnectorConnection{}
for rows.Next() {
var i UserConnectorConnection
if err := rows.Scan(
&i.ID,
&i.Provider,
&i.UserID,
&i.Service,
&i.ConnectionID,
&i.ConnectionName,
&i.AuthType,
&i.Status,
&i.IsDefault,
&i.Label,
&i.ConnectedAt,
&i.LastUsedAt,
&i.CreatedAt,
&i.UpdatedAt,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const markUserConnectorConnectionRevoked = `-- name: MarkUserConnectorConnectionRevoked :exec
UPDATE user_connector_connection
SET status = 'revoked', is_default = FALSE, updated_at = now()
WHERE id = $1 AND user_id = $2
`
type MarkUserConnectorConnectionRevokedParams struct {
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
}
// Idempotent; a revoked row is never the default.
func (q *Queries) MarkUserConnectorConnectionRevoked(ctx context.Context, arg MarkUserConnectorConnectionRevokedParams) error {
_, err := q.db.Exec(ctx, markUserConnectorConnectionRevoked, arg.ID, arg.UserID)
return err
}
const setConnectorServiceEnabled = `-- name: SetConnectorServiceEnabled :one
INSERT INTO connector_service_policy (provider, service, enabled, updated_by)
VALUES ($1, $2, $3, $4)
ON CONFLICT (provider, service) DO UPDATE SET
enabled = EXCLUDED.enabled,
updated_by = EXCLUDED.updated_by,
updated_at = now()
RETURNING provider, service, enabled, allowed_tools, allowed_user_ids, updated_by, created_at, updated_at
`
type SetConnectorServiceEnabledParams struct {
Provider string `json:"provider"`
Service string `json:"service"`
Enabled bool `json:"enabled"`
UpdatedBy pgtype.UUID `json:"updated_by"`
}
// Publishes or delists a service, leaving its tool and user allowlists intact.
func (q *Queries) SetConnectorServiceEnabled(ctx context.Context, arg SetConnectorServiceEnabledParams) (ConnectorServicePolicy, error) {
row := q.db.QueryRow(ctx, setConnectorServiceEnabled,
arg.Provider,
arg.Service,
arg.Enabled,
arg.UpdatedBy,
)
var i ConnectorServicePolicy
err := row.Scan(
&i.Provider,
&i.Service,
&i.Enabled,
&i.AllowedTools,
&i.AllowedUserIds,
&i.UpdatedBy,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const setConnectorServicePolicy = `-- name: SetConnectorServicePolicy :one
INSERT INTO connector_service_policy (provider, service, allowed_tools, allowed_user_ids, updated_by)
VALUES ($1, $2, $3::text[], $4::uuid[], $5)
ON CONFLICT (provider, service) DO UPDATE SET
allowed_tools = EXCLUDED.allowed_tools,
allowed_user_ids = EXCLUDED.allowed_user_ids,
updated_by = EXCLUDED.updated_by,
updated_at = now()
RETURNING provider, service, enabled, allowed_tools, allowed_user_ids, updated_by, created_at, updated_at
`
type SetConnectorServicePolicyParams struct {
Provider string `json:"provider"`
Service string `json:"service"`
AllowedTools []string `json:"allowed_tools"`
AllowedUserIds []pgtype.UUID `json:"allowed_user_ids"`
UpdatedBy pgtype.UUID `json:"updated_by"`
}
// Replaces the tool and user allowlists; a service without a row stays delisted.
func (q *Queries) SetConnectorServicePolicy(ctx context.Context, arg SetConnectorServicePolicyParams) (ConnectorServicePolicy, error) {
row := q.db.QueryRow(ctx, setConnectorServicePolicy,
arg.Provider,
arg.Service,
arg.AllowedTools,
arg.AllowedUserIds,
arg.UpdatedBy,
)
var i ConnectorServicePolicy
err := row.Scan(
&i.Provider,
&i.Service,
&i.Enabled,
&i.AllowedTools,
&i.AllowedUserIds,
&i.UpdatedBy,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const setUserConnectorConnectionDefault = `-- name: SetUserConnectorConnectionDefault :exec
UPDATE user_connector_connection
SET is_default = (id = $1), updated_at = now()
WHERE provider = $2
AND user_id = $3
AND service = $4
AND status = 'active'
AND (id = $1 OR is_default)
`
type SetUserConnectorConnectionDefaultParams struct {
ID pgtype.UUID `json:"id"`
Provider string `json:"provider"`
UserID pgtype.UUID `json:"user_id"`
Service string `json:"service"`
}
// Makes one active connection the default of its (provider, user, service)
// group and clears the flag on its siblings in a single statement.
func (q *Queries) SetUserConnectorConnectionDefault(ctx context.Context, arg SetUserConnectorConnectionDefaultParams) error {
_, err := q.db.Exec(ctx, setUserConnectorConnectionDefault,
arg.ID,
arg.Provider,
arg.UserID,
arg.Service,
)
return err
}
const updateUserConnectorConnectionLabel = `-- name: UpdateUserConnectorConnectionLabel :one
UPDATE user_connector_connection
SET label = $1, updated_at = now()
WHERE id = $2 AND user_id = $3
RETURNING id, provider, user_id, service, connection_id, connection_name, auth_type, status, is_default, label, connected_at, last_used_at, created_at, updated_at
`
type UpdateUserConnectorConnectionLabelParams struct {
Label string `json:"label"`
ID pgtype.UUID `json:"id"`
UserID pgtype.UUID `json:"user_id"`
}
func (q *Queries) UpdateUserConnectorConnectionLabel(ctx context.Context, arg UpdateUserConnectorConnectionLabelParams) (UserConnectorConnection, error) {
row := q.db.QueryRow(ctx, updateUserConnectorConnectionLabel, arg.Label, arg.ID, arg.UserID)
var i UserConnectorConnection
err := row.Scan(
&i.ID,
&i.Provider,
&i.UserID,
&i.Service,
&i.ConnectionID,
&i.ConnectionName,
&i.AuthType,
&i.Status,
&i.IsDefault,
&i.Label,
&i.ConnectedAt,
&i.LastUsedAt,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}
const updateUserConnectorConnectionStatus = `-- name: UpdateUserConnectorConnectionStatus :exec
UPDATE user_connector_connection
SET status = $1, updated_at = now()
WHERE id = $2 AND status <> $1
`
type UpdateUserConnectorConnectionStatusParams struct {
Status string `json:"status"`
ID pgtype.UUID `json:"id"`
}
func (q *Queries) UpdateUserConnectorConnectionStatus(ctx context.Context, arg UpdateUserConnectorConnectionStatusParams) error {
_, err := q.db.Exec(ctx, updateUserConnectorConnectionStatus, arg.Status, arg.ID)
return err
}
const upsertUserConnectorConnection = `-- name: UpsertUserConnectorConnection :one
INSERT INTO user_connector_connection (
provider, user_id, service, connection_id, connection_name, auth_type, label, is_default, status
) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, 'active'
)
ON CONFLICT (provider, user_id, connection_id) DO UPDATE SET
service = EXCLUDED.service,
connection_name = EXCLUDED.connection_name,
auth_type = EXCLUDED.auth_type,
label = CASE WHEN EXCLUDED.label <> '' THEN EXCLUDED.label ELSE user_connector_connection.label END,
status = 'active',
updated_at = now()
RETURNING id, provider, user_id, service, connection_id, connection_name, auth_type, status, is_default, label, connected_at, last_used_at, created_at, updated_at
`
type UpsertUserConnectorConnectionParams struct {
Provider string `json:"provider"`
UserID pgtype.UUID `json:"user_id"`
Service string `json:"service"`
ConnectionID string `json:"connection_id"`
ConnectionName string `json:"connection_name"`
AuthType string `json:"auth_type"`
Label string `json:"label"`
IsDefault bool `json:"is_default"`
}
// =====================
// User Connector Connection (open-connector)
// =====================
// Idempotent on (provider, user_id, connection_id): a duplicate callback
// re-activates the same row. is_default and connected_at are preserved on
// conflict; a non-empty label replaces the stored one.
func (q *Queries) UpsertUserConnectorConnection(ctx context.Context, arg UpsertUserConnectorConnectionParams) (UserConnectorConnection, error) {
row := q.db.QueryRow(ctx, upsertUserConnectorConnection,
arg.Provider,
arg.UserID,
arg.Service,
arg.ConnectionID,
arg.ConnectionName,
arg.AuthType,
arg.Label,
arg.IsDefault,
)
var i UserConnectorConnection
err := row.Scan(
&i.ID,
&i.Provider,
&i.UserID,
&i.Service,
&i.ConnectionID,
&i.ConnectionName,
&i.AuthType,
&i.Status,
&i.IsDefault,
&i.Label,
&i.ConnectedAt,
&i.LastUsedAt,
&i.CreatedAt,
&i.UpdatedAt,
)
return i, err
}