@sixb/pg 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +73 -0
- package/dist/agents/agent-storage.d.ts +20 -0
- package/dist/agents/agent-storage.d.ts.map +1 -0
- package/dist/agents/index.d.ts +6 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/messages.d.ts +13 -0
- package/dist/agents/messages.d.ts.map +1 -0
- package/dist/agents/rows.d.ts +77 -0
- package/dist/agents/rows.d.ts.map +1 -0
- package/dist/agents/runs.d.ts +25 -0
- package/dist/agents/runs.d.ts.map +1 -0
- package/dist/agents/threads.d.ts +13 -0
- package/dist/agents/threads.d.ts.map +1 -0
- package/dist/auth-storage/access-tokens.d.ts +33 -0
- package/dist/auth-storage/access-tokens.d.ts.map +1 -0
- package/dist/auth-storage/auth-storage.d.ts +41 -0
- package/dist/auth-storage/auth-storage.d.ts.map +1 -0
- package/dist/auth-storage/group-memberships.d.ts +21 -0
- package/dist/auth-storage/group-memberships.d.ts.map +1 -0
- package/dist/auth-storage/identities.d.ts +17 -0
- package/dist/auth-storage/identities.d.ts.map +1 -0
- package/dist/auth-storage/index.d.ts +3 -0
- package/dist/auth-storage/index.d.ts.map +1 -0
- package/dist/auth-storage/invitations.d.ts +29 -0
- package/dist/auth-storage/invitations.d.ts.map +1 -0
- package/dist/auth-storage/magic-links.d.ts +28 -0
- package/dist/auth-storage/magic-links.d.ts.map +1 -0
- package/dist/auth-storage/oidc-attempts.d.ts +18 -0
- package/dist/auth-storage/oidc-attempts.d.ts.map +1 -0
- package/dist/auth-storage/rows.d.ts +138 -0
- package/dist/auth-storage/rows.d.ts.map +1 -0
- package/dist/auth-storage/service-account-group-memberships.d.ts +17 -0
- package/dist/auth-storage/service-account-group-memberships.d.ts.map +1 -0
- package/dist/auth-storage/service-accounts.d.ts +14 -0
- package/dist/auth-storage/service-accounts.d.ts.map +1 -0
- package/dist/auth-storage/sessions.d.ts +55 -0
- package/dist/auth-storage/sessions.d.ts.map +1 -0
- package/dist/auth-storage/shared.d.ts +159 -0
- package/dist/auth-storage/shared.d.ts.map +1 -0
- package/dist/auth-storage/users.d.ts +19 -0
- package/dist/auth-storage/users.d.ts.map +1 -0
- package/dist/index.d.ts +127 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11957 -0
- package/dist/index.js.map +55 -0
- package/dist/latest-run-query.d.ts +24 -0
- package/dist/latest-run-query.d.ts.map +1 -0
- package/dist/migrations.d.ts +20 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/ontology-storage/commits.d.ts +11 -0
- package/dist/ontology-storage/commits.d.ts.map +1 -0
- package/dist/ontology-storage/index.d.ts +22 -0
- package/dist/ontology-storage/index.d.ts.map +1 -0
- package/dist/ontology-storage/materialization-session.d.ts +63 -0
- package/dist/ontology-storage/materialization-session.d.ts.map +1 -0
- package/dist/ontology-storage/materialization-state.d.ts +69 -0
- package/dist/ontology-storage/materialization-state.d.ts.map +1 -0
- package/dist/ontology-storage/materialization-writer.d.ts +15 -0
- package/dist/ontology-storage/materialization-writer.d.ts.map +1 -0
- package/dist/ontology-storage/materializations.d.ts +33 -0
- package/dist/ontology-storage/materializations.d.ts.map +1 -0
- package/dist/ontology-storage/outbox.d.ts +12 -0
- package/dist/ontology-storage/outbox.d.ts.map +1 -0
- package/dist/ontology-storage/shared.d.ts +95 -0
- package/dist/ontology-storage/shared.d.ts.map +1 -0
- package/dist/ontology-storage/sources.d.ts +25 -0
- package/dist/ontology-storage/sources.d.ts.map +1 -0
- package/dist/pg-action-run-storage.d.ts +21 -0
- package/dist/pg-action-run-storage.d.ts.map +1 -0
- package/dist/pg-client.d.ts +58 -0
- package/dist/pg-client.d.ts.map +1 -0
- package/dist/pg-object-query-compiler.d.ts +55 -0
- package/dist/pg-object-query-compiler.d.ts.map +1 -0
- package/dist/pg-object-storage.d.ts +90 -0
- package/dist/pg-object-storage.d.ts.map +1 -0
- package/dist/pg-pipeline-run-storage.d.ts +18 -0
- package/dist/pg-pipeline-run-storage.d.ts.map +1 -0
- package/dist/pg-projection-run-storage.d.ts +19 -0
- package/dist/pg-projection-run-storage.d.ts.map +1 -0
- package/dist/pg-rules-storage.d.ts +25 -0
- package/dist/pg-rules-storage.d.ts.map +1 -0
- package/dist/pg-sync-run-storage.d.ts +15 -0
- package/dist/pg-sync-run-storage.d.ts.map +1 -0
- package/dist/pg-timeseries-storage.d.ts +32 -0
- package/dist/pg-timeseries-storage.d.ts.map +1 -0
- package/dist/pg-webhook-delivery-storage.d.ts +17 -0
- package/dist/pg-webhook-delivery-storage.d.ts.map +1 -0
- package/dist/pg-webhook-run-storage.d.ts +14 -0
- package/dist/pg-webhook-run-storage.d.ts.map +1 -0
- package/dist/pg-workflow-intervention-storage.d.ts +16 -0
- package/dist/pg-workflow-intervention-storage.d.ts.map +1 -0
- package/dist/pg-workflow-run-storage.d.ts +49 -0
- package/dist/pg-workflow-run-storage.d.ts.map +1 -0
- package/dist/run-list-query.d.ts +30 -0
- package/dist/run-list-query.d.ts.map +1 -0
- package/dist/storage-errors.d.ts +16 -0
- package/dist/storage-errors.d.ts.map +1 -0
- package/dist/transactions.d.ts +10 -0
- package/dist/transactions.d.ts.map +1 -0
- package/dist/tsconfig.json +5 -0
- package/package.json +60 -0
- package/src/agents/agent-storage.ts +26 -0
- package/src/agents/index.ts +5 -0
- package/src/agents/messages.ts +144 -0
- package/src/agents/rows.ts +227 -0
- package/src/agents/runs.ts +330 -0
- package/src/agents/threads.ts +116 -0
- package/src/auth-storage/access-tokens.ts +254 -0
- package/src/auth-storage/auth-storage.ts +798 -0
- package/src/auth-storage/group-memberships.ts +47 -0
- package/src/auth-storage/identities.ts +85 -0
- package/src/auth-storage/index.ts +2 -0
- package/src/auth-storage/invitations.ts +280 -0
- package/src/auth-storage/magic-links.ts +140 -0
- package/src/auth-storage/oidc-attempts.ts +93 -0
- package/src/auth-storage/rows.ts +352 -0
- package/src/auth-storage/service-account-group-memberships.ts +150 -0
- package/src/auth-storage/service-accounts.ts +154 -0
- package/src/auth-storage/sessions.ts +193 -0
- package/src/auth-storage/shared.ts +799 -0
- package/src/auth-storage/users.ts +196 -0
- package/src/index.ts +367 -0
- package/src/latest-run-query.ts +42 -0
- package/src/migrations/001-initial-schema.sql +1195 -0
- package/src/migrations.ts +280 -0
- package/src/ontology-storage/commits.ts +115 -0
- package/src/ontology-storage/index.ts +35 -0
- package/src/ontology-storage/materialization-session.ts +426 -0
- package/src/ontology-storage/materialization-state.ts +1109 -0
- package/src/ontology-storage/materialization-writer.ts +509 -0
- package/src/ontology-storage/materializations.ts +939 -0
- package/src/ontology-storage/outbox.ts +216 -0
- package/src/ontology-storage/shared.ts +293 -0
- package/src/ontology-storage/sources.ts +658 -0
- package/src/pg-action-run-storage.ts +657 -0
- package/src/pg-client.ts +124 -0
- package/src/pg-object-query-compiler.ts +1545 -0
- package/src/pg-object-storage.ts +638 -0
- package/src/pg-pipeline-run-storage.ts +457 -0
- package/src/pg-projection-run-storage.ts +526 -0
- package/src/pg-rules-storage.ts +308 -0
- package/src/pg-sync-run-storage.ts +263 -0
- package/src/pg-timeseries-storage.ts +180 -0
- package/src/pg-webhook-delivery-storage.ts +180 -0
- package/src/pg-webhook-run-storage.ts +185 -0
- package/src/pg-workflow-intervention-storage.ts +339 -0
- package/src/pg-workflow-run-storage.ts +1065 -0
- package/src/run-list-query.ts +108 -0
- package/src/sql.d.ts +4 -0
- package/src/storage-errors.ts +72 -0
- package/src/transactions.ts +58 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AgentStorageError,
|
|
3
|
+
type AgentThreadRecord,
|
|
4
|
+
type AgentThreadStore,
|
|
5
|
+
type CreateAgentThreadInput,
|
|
6
|
+
type ListAgentThreadsInput,
|
|
7
|
+
type ListAgentThreadsResult,
|
|
8
|
+
} from "@sixb/core/storage"
|
|
9
|
+
import type { SqlParameter } from "../pg-client"
|
|
10
|
+
import { isUniqueViolation } from "../storage-errors"
|
|
11
|
+
import type { PgStoreClient } from "../transactions"
|
|
12
|
+
import { type AgentThreadRow, queryAgentList, rowToThreadRecord } from "./rows"
|
|
13
|
+
|
|
14
|
+
export class PgAgentThreadStore implements AgentThreadStore {
|
|
15
|
+
constructor(private readonly sql: PgStoreClient) {}
|
|
16
|
+
|
|
17
|
+
async create(input: CreateAgentThreadInput): Promise<AgentThreadRecord> {
|
|
18
|
+
const createdAt = input.createdAt ?? new Date()
|
|
19
|
+
const updatedAt = input.updatedAt ?? createdAt
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
const [row] = await this.sql<AgentThreadRow[]>`
|
|
23
|
+
INSERT INTO agent_threads (
|
|
24
|
+
project_id,
|
|
25
|
+
id,
|
|
26
|
+
agent_id,
|
|
27
|
+
owner_principal_type,
|
|
28
|
+
owner_principal_id,
|
|
29
|
+
title,
|
|
30
|
+
status,
|
|
31
|
+
created_at,
|
|
32
|
+
updated_at
|
|
33
|
+
) VALUES (
|
|
34
|
+
${input.projectId},
|
|
35
|
+
${input.id},
|
|
36
|
+
${input.agentId},
|
|
37
|
+
${input.ownerPrincipal.type},
|
|
38
|
+
${input.ownerPrincipal.id},
|
|
39
|
+
${input.title ?? null},
|
|
40
|
+
${input.status ?? "active"},
|
|
41
|
+
${createdAt},
|
|
42
|
+
${updatedAt}
|
|
43
|
+
)
|
|
44
|
+
RETURNING *
|
|
45
|
+
`
|
|
46
|
+
|
|
47
|
+
return rowToThreadRecord(row)
|
|
48
|
+
} catch (error) {
|
|
49
|
+
if (isUniqueViolation(error)) {
|
|
50
|
+
throw new AgentStorageError(
|
|
51
|
+
"duplicate_id",
|
|
52
|
+
`[SixbPg] Agent thread '${input.id}' already exists for project '${input.projectId}'.`
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
throw error
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async getById(params: { projectId: string; id: string }): Promise<AgentThreadRecord | null> {
|
|
61
|
+
const [row] = await this.sql<AgentThreadRow[]>`
|
|
62
|
+
SELECT * FROM agent_threads WHERE project_id = ${params.projectId} AND id = ${params.id}
|
|
63
|
+
`
|
|
64
|
+
|
|
65
|
+
return row ? rowToThreadRecord(row) : null
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async list(input: ListAgentThreadsInput): Promise<ListAgentThreadsResult> {
|
|
69
|
+
if (
|
|
70
|
+
(input.statuses !== undefined && input.statuses.length === 0) ||
|
|
71
|
+
(input.agentIds !== undefined && input.agentIds.length === 0)
|
|
72
|
+
) {
|
|
73
|
+
return { threads: [], hasMore: false, total: 0 }
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const whereClauses = ["project_id = $1"]
|
|
77
|
+
const params: SqlParameter[] = [input.projectId]
|
|
78
|
+
let index = 2
|
|
79
|
+
|
|
80
|
+
if (input.agentId) {
|
|
81
|
+
whereClauses.push(`agent_id = $${index++}`)
|
|
82
|
+
params.push(input.agentId)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (input.agentIds) {
|
|
86
|
+
const placeholders = input.agentIds.map(() => `$${index++}`)
|
|
87
|
+
whereClauses.push(`agent_id IN (${placeholders.join(", ")})`)
|
|
88
|
+
params.push(...input.agentIds)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
if (input.statuses) {
|
|
92
|
+
const placeholders = input.statuses.map(() => `$${index++}`)
|
|
93
|
+
whereClauses.push(`status IN (${placeholders.join(", ")})`)
|
|
94
|
+
params.push(...input.statuses)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (input.ownerPrincipal) {
|
|
98
|
+
whereClauses.push(`owner_principal_type = $${index++} AND owner_principal_id = $${index++}`)
|
|
99
|
+
params.push(input.ownerPrincipal.type, input.ownerPrincipal.id)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const dir = input.order === "asc" ? "ASC" : "DESC"
|
|
103
|
+
const { rows, total, hasMore } = await queryAgentList<AgentThreadRow>({
|
|
104
|
+
sql: this.sql,
|
|
105
|
+
table: "agent_threads",
|
|
106
|
+
whereClauses,
|
|
107
|
+
params,
|
|
108
|
+
nextIndex: index,
|
|
109
|
+
orderBy: `COALESCE(last_message_at, created_at) ${dir}, id ${dir}`,
|
|
110
|
+
limit: input.limit,
|
|
111
|
+
offset: input.offset,
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
return { threads: rows.map(rowToThreadRecord), hasMore, total }
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AccessTokenRecord,
|
|
3
|
+
AuthAccessTokenStore,
|
|
4
|
+
CreateAuthAccessTokenInput,
|
|
5
|
+
ListAuthAccessTokensInput,
|
|
6
|
+
ListAuthAccessTokensResult,
|
|
7
|
+
} from "@sixb/core/storage"
|
|
8
|
+
import { AuthStorageError } from "@sixb/core/storage"
|
|
9
|
+
import type { PgStoreClient } from "../transactions"
|
|
10
|
+
import type { PgAuthAccessTokenRow, PgAuthServiceAccountRow, PgAuthUserRow } from "./rows"
|
|
11
|
+
import { rowToAccessTokenRecord, serializeOptionalStringArray } from "./rows"
|
|
12
|
+
import {
|
|
13
|
+
appendPagination,
|
|
14
|
+
assertNonEmpty,
|
|
15
|
+
mapUniqueConstraintError,
|
|
16
|
+
normalizeGroupIds,
|
|
17
|
+
type PgValue,
|
|
18
|
+
} from "./shared"
|
|
19
|
+
|
|
20
|
+
export class PgAuthAccessTokenStore implements AuthAccessTokenStore {
|
|
21
|
+
constructor(private readonly sql: PgStoreClient) {}
|
|
22
|
+
|
|
23
|
+
async create(input: CreateAuthAccessTokenInput): Promise<AccessTokenRecord> {
|
|
24
|
+
const id = assertNonEmpty(input.id, "Access token id")
|
|
25
|
+
const projectId = assertNonEmpty(input.projectId, "Project id")
|
|
26
|
+
const name = assertNonEmpty(input.name, "Access token name")
|
|
27
|
+
const subjectId = assertNonEmpty(input.subjectId, "Access token subject id")
|
|
28
|
+
const tokenHash = assertNonEmpty(input.tokenHash, "Access token hash")
|
|
29
|
+
assertKindMatchesSubject(input)
|
|
30
|
+
await this.assertSubjectExists(projectId, input.subjectType, subjectId)
|
|
31
|
+
const groupIds = input.groupIds === undefined ? undefined : normalizeGroupIds(input.groupIds)
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
const [row] = await this.sql<PgAuthAccessTokenRow[]>`
|
|
35
|
+
INSERT INTO auth_access_tokens (
|
|
36
|
+
project_id,
|
|
37
|
+
id,
|
|
38
|
+
name,
|
|
39
|
+
kind,
|
|
40
|
+
subject_type,
|
|
41
|
+
subject_id,
|
|
42
|
+
token_hash,
|
|
43
|
+
group_ids,
|
|
44
|
+
created_by_user_id,
|
|
45
|
+
created_by_service_account_id,
|
|
46
|
+
created_by_system_id,
|
|
47
|
+
created_by_session_id,
|
|
48
|
+
created_at,
|
|
49
|
+
expires_at
|
|
50
|
+
) VALUES (
|
|
51
|
+
${projectId},
|
|
52
|
+
${id},
|
|
53
|
+
${name},
|
|
54
|
+
${input.kind},
|
|
55
|
+
${input.subjectType},
|
|
56
|
+
${subjectId},
|
|
57
|
+
${tokenHash},
|
|
58
|
+
${serializeOptionalStringArray(groupIds)},
|
|
59
|
+
${input.createdByPrincipal?.type === "user" ? input.createdByPrincipal.id : null},
|
|
60
|
+
${
|
|
61
|
+
input.createdByPrincipal?.type === "serviceAccount" ? input.createdByPrincipal.id : null
|
|
62
|
+
},
|
|
63
|
+
${input.createdByPrincipal?.type === "system" ? input.createdByPrincipal.id : null},
|
|
64
|
+
${input.createdBySessionId ?? null},
|
|
65
|
+
${input.createdAt},
|
|
66
|
+
${input.expiresAt}
|
|
67
|
+
)
|
|
68
|
+
RETURNING *
|
|
69
|
+
`
|
|
70
|
+
|
|
71
|
+
return rowToAccessTokenRecord(row)
|
|
72
|
+
} catch (error) {
|
|
73
|
+
mapUniqueConstraintError(
|
|
74
|
+
error,
|
|
75
|
+
"duplicate_access_token",
|
|
76
|
+
`[Sixb] Access token '${id}' already exists for project '${projectId}'.`
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async getById(params: {
|
|
82
|
+
readonly projectId: string
|
|
83
|
+
readonly id: string
|
|
84
|
+
}): Promise<AccessTokenRecord | null> {
|
|
85
|
+
const [row] = await this.sql<PgAuthAccessTokenRow[]>`
|
|
86
|
+
SELECT *
|
|
87
|
+
FROM auth_access_tokens
|
|
88
|
+
WHERE project_id = ${params.projectId}
|
|
89
|
+
AND id = ${params.id}
|
|
90
|
+
`
|
|
91
|
+
return row ? rowToAccessTokenRecord(row) : null
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async list(input: ListAuthAccessTokensInput): Promise<ListAuthAccessTokensResult> {
|
|
95
|
+
const whereClauses = ["project_id = $1"]
|
|
96
|
+
const params: PgValue[] = [input.projectId]
|
|
97
|
+
let nextIndex = 2
|
|
98
|
+
if (input.kind) {
|
|
99
|
+
whereClauses.push(`kind = $${nextIndex++}`)
|
|
100
|
+
params.push(input.kind)
|
|
101
|
+
}
|
|
102
|
+
if (input.subjectType) {
|
|
103
|
+
whereClauses.push(`subject_type = $${nextIndex++}`)
|
|
104
|
+
params.push(input.subjectType)
|
|
105
|
+
}
|
|
106
|
+
if (input.subjectId) {
|
|
107
|
+
whereClauses.push(`subject_id = $${nextIndex++}`)
|
|
108
|
+
params.push(input.subjectId)
|
|
109
|
+
}
|
|
110
|
+
if (!input.includeRevoked) {
|
|
111
|
+
whereClauses.push("revoked_at IS NULL")
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const where = `WHERE ${whereClauses.join(" AND ")}`
|
|
115
|
+
const order = input.order === "desc" ? "DESC" : "ASC"
|
|
116
|
+
const [totalRow] = await this.sql.unsafe<{ readonly count: string | number }[]>(
|
|
117
|
+
`SELECT COUNT(*)::bigint AS count FROM auth_access_tokens ${where}`,
|
|
118
|
+
[...params]
|
|
119
|
+
)
|
|
120
|
+
const queryParams = [...params]
|
|
121
|
+
const query = appendPagination(
|
|
122
|
+
`
|
|
123
|
+
SELECT *
|
|
124
|
+
FROM auth_access_tokens
|
|
125
|
+
${where}
|
|
126
|
+
ORDER BY created_at ${order}, id ${order}
|
|
127
|
+
`,
|
|
128
|
+
queryParams,
|
|
129
|
+
nextIndex,
|
|
130
|
+
input
|
|
131
|
+
)
|
|
132
|
+
const rows = await this.sql.unsafe<PgAuthAccessTokenRow[]>(query, queryParams)
|
|
133
|
+
const total = Number(totalRow?.count ?? 0)
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
accessTokens: rows.map(rowToAccessTokenRecord),
|
|
137
|
+
hasMore: input.limit === undefined ? false : (input.offset ?? 0) + input.limit < total,
|
|
138
|
+
total,
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async findValidByTokenHash(params: {
|
|
143
|
+
readonly projectId: string
|
|
144
|
+
readonly id: string
|
|
145
|
+
readonly kind: AccessTokenRecord["kind"]
|
|
146
|
+
readonly tokenHash: string
|
|
147
|
+
readonly now: Date
|
|
148
|
+
}): Promise<AccessTokenRecord | null> {
|
|
149
|
+
const [row] = await this.sql<PgAuthAccessTokenRow[]>`
|
|
150
|
+
SELECT *
|
|
151
|
+
FROM auth_access_tokens
|
|
152
|
+
WHERE project_id = ${params.projectId}
|
|
153
|
+
AND id = ${params.id}
|
|
154
|
+
AND kind = ${params.kind}
|
|
155
|
+
AND token_hash = ${params.tokenHash}
|
|
156
|
+
AND revoked_at IS NULL
|
|
157
|
+
AND expires_at > ${params.now}
|
|
158
|
+
`
|
|
159
|
+
|
|
160
|
+
return row ? rowToAccessTokenRecord(row) : null
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async revoke(params: {
|
|
164
|
+
readonly projectId: string
|
|
165
|
+
readonly id: string
|
|
166
|
+
readonly revokedAt: Date
|
|
167
|
+
}): Promise<AccessTokenRecord> {
|
|
168
|
+
const [row] = await this.sql<PgAuthAccessTokenRow[]>`
|
|
169
|
+
UPDATE auth_access_tokens
|
|
170
|
+
SET revoked_at = ${params.revokedAt}
|
|
171
|
+
WHERE project_id = ${params.projectId}
|
|
172
|
+
AND id = ${params.id}
|
|
173
|
+
RETURNING *
|
|
174
|
+
`
|
|
175
|
+
if (!row) {
|
|
176
|
+
throw new AuthStorageError(
|
|
177
|
+
"missing_access_token",
|
|
178
|
+
`[Sixb] Access token '${params.id}' not found for project '${params.projectId}'.`
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
return rowToAccessTokenRecord(row)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async touch(params: {
|
|
185
|
+
readonly projectId: string
|
|
186
|
+
readonly id: string
|
|
187
|
+
readonly lastUsedAt: Date
|
|
188
|
+
readonly userAgent?: string
|
|
189
|
+
readonly ipAddress?: string
|
|
190
|
+
}): Promise<AccessTokenRecord> {
|
|
191
|
+
const [row] = await this.sql<PgAuthAccessTokenRow[]>`
|
|
192
|
+
UPDATE auth_access_tokens
|
|
193
|
+
SET last_used_at = ${params.lastUsedAt},
|
|
194
|
+
last_used_user_agent = COALESCE(${params.userAgent ?? null}, last_used_user_agent),
|
|
195
|
+
last_used_ip_address = COALESCE(${params.ipAddress ?? null}, last_used_ip_address)
|
|
196
|
+
WHERE project_id = ${params.projectId}
|
|
197
|
+
AND id = ${params.id}
|
|
198
|
+
RETURNING *
|
|
199
|
+
`
|
|
200
|
+
if (!row) {
|
|
201
|
+
throw new AuthStorageError(
|
|
202
|
+
"missing_access_token",
|
|
203
|
+
`[Sixb] Access token '${params.id}' not found for project '${params.projectId}'.`
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
return rowToAccessTokenRecord(row)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
private async assertSubjectExists(
|
|
210
|
+
projectId: string,
|
|
211
|
+
subjectType: CreateAuthAccessTokenInput["subjectType"],
|
|
212
|
+
subjectId: string
|
|
213
|
+
): Promise<void> {
|
|
214
|
+
if (subjectType === "user") {
|
|
215
|
+
const [row] = await this.sql<PgAuthUserRow[]>`
|
|
216
|
+
SELECT *
|
|
217
|
+
FROM auth_users
|
|
218
|
+
WHERE project_id = ${projectId}
|
|
219
|
+
AND id = ${subjectId}
|
|
220
|
+
`
|
|
221
|
+
if (row) return
|
|
222
|
+
throw new AuthStorageError(
|
|
223
|
+
"missing_user",
|
|
224
|
+
`[Sixb] User '${subjectId}' not found for project '${projectId}'.`
|
|
225
|
+
)
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const [row] = await this.sql<PgAuthServiceAccountRow[]>`
|
|
229
|
+
SELECT *
|
|
230
|
+
FROM auth_service_accounts
|
|
231
|
+
WHERE project_id = ${projectId}
|
|
232
|
+
AND id = ${subjectId}
|
|
233
|
+
`
|
|
234
|
+
if (row) return
|
|
235
|
+
throw new AuthStorageError(
|
|
236
|
+
"missing_service_account",
|
|
237
|
+
`[Sixb] Service account '${subjectId}' not found for project '${projectId}'.`
|
|
238
|
+
)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function assertKindMatchesSubject(input: CreateAuthAccessTokenInput): void {
|
|
243
|
+
if (
|
|
244
|
+
(input.kind === "personal" && input.subjectType === "user") ||
|
|
245
|
+
(input.kind === "serviceAccount" && input.subjectType === "serviceAccount")
|
|
246
|
+
) {
|
|
247
|
+
return
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
throw new AuthStorageError(
|
|
251
|
+
"invalid_input",
|
|
252
|
+
`[Sixb] Access token kind '${input.kind}' cannot target subject type '${input.subjectType}'.`
|
|
253
|
+
)
|
|
254
|
+
}
|