@pikku/kysely 0.12.6 → 0.12.8
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/CHANGELOG.md +24 -0
- package/dist/src/kysely-agent-run-service.js +59 -59
- package/dist/src/kysely-ai-storage-service.js +174 -174
- package/dist/src/kysely-channel-store.js +12 -12
- package/dist/src/kysely-credential-service.d.ts +2 -0
- package/dist/src/kysely-credential-service.js +47 -29
- package/dist/src/kysely-deployment-service.js +22 -22
- package/dist/src/kysely-eventhub-store.js +8 -8
- package/dist/src/kysely-secret-service.js +19 -19
- package/dist/src/kysely-tables.d.ts +91 -91
- package/dist/src/kysely-workflow-run-service.js +73 -73
- package/dist/src/kysely-workflow-service.js +127 -127
- package/package.json +2 -2
- package/src/kysely-agent-run-service.ts +59 -59
- package/src/kysely-ai-storage-service.ts +174 -174
- package/src/kysely-channel-store.ts +12 -12
- package/src/kysely-credential-service.ts +51 -29
- package/src/kysely-deployment-service.ts +24 -24
- package/src/kysely-eventhub-store.ts +8 -8
- package/src/kysely-secret-service.ts +19 -19
- package/src/kysely-services.test.ts +19 -18
- package/src/kysely-tables.ts +91 -91
- package/src/kysely-workflow-run-service.ts +76 -76
- package/src/kysely-workflow-service.ts +129 -129
|
@@ -57,9 +57,9 @@ export class KyselyChannelStore extends ChannelStore {
|
|
|
57
57
|
await this.db
|
|
58
58
|
.insertInto('channels')
|
|
59
59
|
.values({
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
channelId: channelId,
|
|
61
|
+
channelName: channelName,
|
|
62
|
+
openingData: JSON.stringify(openingData || {}),
|
|
63
63
|
})
|
|
64
64
|
.execute()
|
|
65
65
|
}
|
|
@@ -71,7 +71,7 @@ export class KyselyChannelStore extends ChannelStore {
|
|
|
71
71
|
|
|
72
72
|
await this.db
|
|
73
73
|
.deleteFrom('channels')
|
|
74
|
-
.where('
|
|
74
|
+
.where('channelId', 'in', channelIds)
|
|
75
75
|
.execute()
|
|
76
76
|
}
|
|
77
77
|
|
|
@@ -81,8 +81,8 @@ export class KyselyChannelStore extends ChannelStore {
|
|
|
81
81
|
): Promise<void> {
|
|
82
82
|
await this.db
|
|
83
83
|
.updateTable('channels')
|
|
84
|
-
.set({
|
|
85
|
-
.where('
|
|
84
|
+
.set({ userSession: session ? JSON.stringify(session) : null })
|
|
85
|
+
.where('channelId', '=', channelId)
|
|
86
86
|
.execute()
|
|
87
87
|
}
|
|
88
88
|
|
|
@@ -91,8 +91,8 @@ export class KyselyChannelStore extends ChannelStore {
|
|
|
91
91
|
): Promise<Channel & { session: CoreUserSession }> {
|
|
92
92
|
const row = await this.db
|
|
93
93
|
.selectFrom('channels')
|
|
94
|
-
.select(['
|
|
95
|
-
.where('
|
|
94
|
+
.select(['channelId', 'channelName', 'openingData', 'userSession'])
|
|
95
|
+
.where('channelId', '=', channelId)
|
|
96
96
|
.executeTakeFirst()
|
|
97
97
|
|
|
98
98
|
if (!row) {
|
|
@@ -100,10 +100,10 @@ export class KyselyChannelStore extends ChannelStore {
|
|
|
100
100
|
}
|
|
101
101
|
|
|
102
102
|
return {
|
|
103
|
-
channelId: row.
|
|
104
|
-
channelName: row.
|
|
105
|
-
openingData: parseJson(row.
|
|
106
|
-
session: (parseJson(row.
|
|
103
|
+
channelId: row.channelId,
|
|
104
|
+
channelName: row.channelName,
|
|
105
|
+
openingData: parseJson(row.openingData) ?? {},
|
|
106
|
+
session: (parseJson(row.userSession) ?? {}) as CoreUserSession,
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
@@ -84,13 +84,13 @@ export class KyselyCredentialService implements CredentialService {
|
|
|
84
84
|
if (action === 'read' && !this.auditReads) return
|
|
85
85
|
|
|
86
86
|
await this.db
|
|
87
|
-
.insertInto('
|
|
87
|
+
.insertInto('credentialsAudit')
|
|
88
88
|
.values({
|
|
89
89
|
id: crypto.randomUUID(),
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
credentialName: name,
|
|
91
|
+
userId: userId ?? null,
|
|
92
92
|
action,
|
|
93
|
-
|
|
93
|
+
performedAt: new Date().toISOString() as unknown as Date,
|
|
94
94
|
})
|
|
95
95
|
.execute()
|
|
96
96
|
}
|
|
@@ -103,25 +103,25 @@ export class KyselyCredentialService implements CredentialService {
|
|
|
103
103
|
|
|
104
104
|
private whereUserId(qb: any, userId?: string) {
|
|
105
105
|
return userId
|
|
106
|
-
? qb.where('
|
|
107
|
-
: qb.where('
|
|
106
|
+
? qb.where('userId', '=', userId)
|
|
107
|
+
: qb.where('userId', 'is', null)
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
async get<T = unknown>(name: string, userId?: string): Promise<T | null> {
|
|
111
111
|
let qb = this.db
|
|
112
112
|
.selectFrom('credentials')
|
|
113
|
-
.select(['ciphertext', '
|
|
113
|
+
.select(['ciphertext', 'wrappedDek', 'keyVersion'])
|
|
114
114
|
.where('name', '=', name)
|
|
115
115
|
qb = this.whereUserId(qb, userId)
|
|
116
116
|
|
|
117
117
|
const row = await qb.executeTakeFirst()
|
|
118
118
|
if (!row) return null
|
|
119
119
|
|
|
120
|
-
const kek = this.getKEK(row.
|
|
120
|
+
const kek = this.getKEK(row.keyVersion)
|
|
121
121
|
const plaintext = await envelopeDecrypt<string>(
|
|
122
122
|
kek,
|
|
123
123
|
row.ciphertext,
|
|
124
|
-
row.
|
|
124
|
+
row.wrappedDek
|
|
125
125
|
)
|
|
126
126
|
await this.logAudit(name, userId, 'read')
|
|
127
127
|
|
|
@@ -146,9 +146,9 @@ export class KyselyCredentialService implements CredentialService {
|
|
|
146
146
|
.updateTable('credentials')
|
|
147
147
|
.set({
|
|
148
148
|
ciphertext,
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
wrappedDek: wrappedDEK,
|
|
150
|
+
keyVersion: this.keyVersion,
|
|
151
|
+
updatedAt: now as unknown as Date,
|
|
152
152
|
})
|
|
153
153
|
.where('name', '=', name)
|
|
154
154
|
qb = this.whereUserId(qb, userId)
|
|
@@ -158,12 +158,12 @@ export class KyselyCredentialService implements CredentialService {
|
|
|
158
158
|
.insertInto('credentials')
|
|
159
159
|
.values({
|
|
160
160
|
name,
|
|
161
|
-
|
|
161
|
+
userId: userId ?? null,
|
|
162
162
|
ciphertext,
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
163
|
+
wrappedDek: wrappedDEK,
|
|
164
|
+
keyVersion: this.keyVersion,
|
|
165
|
+
createdAt: now as unknown as Date,
|
|
166
|
+
updatedAt: now as unknown as Date,
|
|
167
167
|
})
|
|
168
168
|
.execute()
|
|
169
169
|
}
|
|
@@ -193,17 +193,17 @@ export class KyselyCredentialService implements CredentialService {
|
|
|
193
193
|
async getAll(userId: string): Promise<Record<string, unknown>> {
|
|
194
194
|
const rows = await this.db
|
|
195
195
|
.selectFrom('credentials')
|
|
196
|
-
.select(['name', 'ciphertext', '
|
|
197
|
-
.where('
|
|
196
|
+
.select(['name', 'ciphertext', 'wrappedDek', 'keyVersion'])
|
|
197
|
+
.where('userId', '=', userId)
|
|
198
198
|
.execute()
|
|
199
199
|
|
|
200
200
|
const result: Record<string, unknown> = {}
|
|
201
201
|
for (const row of rows) {
|
|
202
|
-
const kek = this.getKEK(row.
|
|
202
|
+
const kek = this.getKEK(row.keyVersion)
|
|
203
203
|
const plaintext = await envelopeDecrypt<string>(
|
|
204
204
|
kek,
|
|
205
205
|
row.ciphertext,
|
|
206
|
-
row.
|
|
206
|
+
row.wrappedDek
|
|
207
207
|
)
|
|
208
208
|
try {
|
|
209
209
|
result[row.name] = JSON.parse(plaintext)
|
|
@@ -216,6 +216,28 @@ export class KyselyCredentialService implements CredentialService {
|
|
|
216
216
|
return result
|
|
217
217
|
}
|
|
218
218
|
|
|
219
|
+
async getUsersWithCredential(name: string): Promise<string[]> {
|
|
220
|
+
const rows = await this.db
|
|
221
|
+
.selectFrom('credentials')
|
|
222
|
+
.select('userId')
|
|
223
|
+
.where('name', '=', name)
|
|
224
|
+
.where('userId', 'is not', null)
|
|
225
|
+
.execute()
|
|
226
|
+
|
|
227
|
+
return rows.map((row) => row.userId!).filter(Boolean)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async getAllUsers(): Promise<string[]> {
|
|
231
|
+
const rows = await this.db
|
|
232
|
+
.selectFrom('credentials')
|
|
233
|
+
.select('userId')
|
|
234
|
+
.distinct()
|
|
235
|
+
.where('userId', 'is not', null)
|
|
236
|
+
.execute()
|
|
237
|
+
|
|
238
|
+
return rows.map((row) => row.userId!).filter(Boolean)
|
|
239
|
+
}
|
|
240
|
+
|
|
219
241
|
async rotateKEK(): Promise<number> {
|
|
220
242
|
if (!this.previousKey) {
|
|
221
243
|
throw new Error('No previousKey configured — nothing to rotate from')
|
|
@@ -223,28 +245,28 @@ export class KyselyCredentialService implements CredentialService {
|
|
|
223
245
|
|
|
224
246
|
const rows = await this.db
|
|
225
247
|
.selectFrom('credentials')
|
|
226
|
-
.select(['name', '
|
|
227
|
-
.where('
|
|
248
|
+
.select(['name', 'userId', 'wrappedDek'])
|
|
249
|
+
.where('keyVersion', '<', this.keyVersion)
|
|
228
250
|
.execute()
|
|
229
251
|
|
|
230
252
|
for (const row of rows) {
|
|
231
253
|
const newWrappedDEK = await envelopeRewrap(
|
|
232
254
|
this.previousKey,
|
|
233
255
|
this.key,
|
|
234
|
-
row.
|
|
256
|
+
row.wrappedDek
|
|
235
257
|
)
|
|
236
258
|
let qb = this.db
|
|
237
259
|
.updateTable('credentials')
|
|
238
260
|
.set({
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
261
|
+
wrappedDek: newWrappedDEK,
|
|
262
|
+
keyVersion: this.keyVersion,
|
|
263
|
+
updatedAt: new Date().toISOString() as unknown as Date,
|
|
242
264
|
})
|
|
243
265
|
.where('name', '=', row.name)
|
|
244
|
-
qb = this.whereUserId(qb, row.
|
|
266
|
+
qb = this.whereUserId(qb, row.userId ?? undefined)
|
|
245
267
|
await qb.execute()
|
|
246
268
|
|
|
247
|
-
await this.logAudit(row.name, row.
|
|
269
|
+
await this.logAudit(row.name, row.userId ?? undefined, 'rotate')
|
|
248
270
|
}
|
|
249
271
|
|
|
250
272
|
return rows.length
|
|
@@ -83,32 +83,32 @@ export class KyselyDeploymentService implements DeploymentService {
|
|
|
83
83
|
|
|
84
84
|
await this.db.transaction().execute(async (trx) => {
|
|
85
85
|
await trx
|
|
86
|
-
.insertInto('
|
|
86
|
+
.insertInto('pikkuDeployments')
|
|
87
87
|
.values({
|
|
88
|
-
|
|
88
|
+
deploymentId: config.deploymentId,
|
|
89
89
|
endpoint: config.endpoint,
|
|
90
|
-
|
|
90
|
+
lastHeartbeat: new Date(),
|
|
91
91
|
})
|
|
92
92
|
.onConflict((oc) =>
|
|
93
|
-
oc.column('
|
|
93
|
+
oc.column('deploymentId').doUpdateSet({
|
|
94
94
|
endpoint: config.endpoint,
|
|
95
|
-
|
|
95
|
+
lastHeartbeat: new Date(),
|
|
96
96
|
})
|
|
97
97
|
)
|
|
98
98
|
.execute()
|
|
99
99
|
|
|
100
100
|
await trx
|
|
101
|
-
.deleteFrom('
|
|
102
|
-
.where('
|
|
101
|
+
.deleteFrom('pikkuDeploymentFunctions')
|
|
102
|
+
.where('deploymentId', '=', config.deploymentId)
|
|
103
103
|
.execute()
|
|
104
104
|
|
|
105
105
|
if (functions.length > 0) {
|
|
106
106
|
await trx
|
|
107
|
-
.insertInto('
|
|
107
|
+
.insertInto('pikkuDeploymentFunctions')
|
|
108
108
|
.values(
|
|
109
109
|
functions.map((fn) => ({
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
deploymentId: config.deploymentId,
|
|
111
|
+
functionName: fn,
|
|
112
112
|
}))
|
|
113
113
|
)
|
|
114
114
|
.execute()
|
|
@@ -129,8 +129,8 @@ export class KyselyDeploymentService implements DeploymentService {
|
|
|
129
129
|
|
|
130
130
|
if (this.deploymentConfig) {
|
|
131
131
|
await this.db
|
|
132
|
-
.deleteFrom('
|
|
133
|
-
.where('
|
|
132
|
+
.deleteFrom('pikkuDeployments')
|
|
133
|
+
.where('deploymentId', '=', this.deploymentConfig.deploymentId)
|
|
134
134
|
.execute()
|
|
135
135
|
}
|
|
136
136
|
}
|
|
@@ -140,20 +140,20 @@ export class KyselyDeploymentService implements DeploymentService {
|
|
|
140
140
|
const cutoff = new Date(Date.now() - ttlMs)
|
|
141
141
|
|
|
142
142
|
const result = await this.db
|
|
143
|
-
.selectFrom('
|
|
143
|
+
.selectFrom('pikkuDeployments as d')
|
|
144
144
|
.innerJoin(
|
|
145
|
-
'
|
|
146
|
-
'f.
|
|
147
|
-
'd.
|
|
145
|
+
'pikkuDeploymentFunctions as f',
|
|
146
|
+
'f.deploymentId',
|
|
147
|
+
'd.deploymentId'
|
|
148
148
|
)
|
|
149
|
-
.select(['d.
|
|
150
|
-
.where('f.
|
|
151
|
-
.where('d.
|
|
152
|
-
.orderBy('d.
|
|
149
|
+
.select(['d.deploymentId', 'd.endpoint'])
|
|
150
|
+
.where('f.functionName', '=', name)
|
|
151
|
+
.where('d.lastHeartbeat', '>', cutoff)
|
|
152
|
+
.orderBy('d.lastHeartbeat', 'desc')
|
|
153
153
|
.execute()
|
|
154
154
|
|
|
155
155
|
return result.map((row) => ({
|
|
156
|
-
deploymentId: row.
|
|
156
|
+
deploymentId: row.deploymentId,
|
|
157
157
|
endpoint: row.endpoint,
|
|
158
158
|
}))
|
|
159
159
|
}
|
|
@@ -176,9 +176,9 @@ export class KyselyDeploymentService implements DeploymentService {
|
|
|
176
176
|
|
|
177
177
|
try {
|
|
178
178
|
await this.db
|
|
179
|
-
.updateTable('
|
|
180
|
-
.set({
|
|
181
|
-
.where('
|
|
179
|
+
.updateTable('pikkuDeployments')
|
|
180
|
+
.set({ lastHeartbeat: new Date() })
|
|
181
|
+
.where('deploymentId', '=', this.deploymentConfig.deploymentId)
|
|
182
182
|
.execute()
|
|
183
183
|
} catch {
|
|
184
184
|
// Heartbeat failed, will retry on next interval
|
|
@@ -18,20 +18,20 @@ export class KyselyEventHubStore extends EventHubStore {
|
|
|
18
18
|
|
|
19
19
|
public async getChannelIdsForTopic(topic: string): Promise<string[]> {
|
|
20
20
|
const result = await this.db
|
|
21
|
-
.selectFrom('
|
|
22
|
-
.select('
|
|
21
|
+
.selectFrom('channelSubscriptions')
|
|
22
|
+
.select('channelId')
|
|
23
23
|
.where('topic', '=', topic)
|
|
24
24
|
.execute()
|
|
25
25
|
|
|
26
|
-
return result.map((row) => row.
|
|
26
|
+
return result.map((row) => row.channelId)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
public async subscribe(topic: string, channelId: string): Promise<boolean> {
|
|
30
30
|
try {
|
|
31
31
|
await this.db
|
|
32
|
-
.insertInto('
|
|
33
|
-
.values({
|
|
34
|
-
.onConflict((oc) => oc.columns(['
|
|
32
|
+
.insertInto('channelSubscriptions')
|
|
33
|
+
.values({ channelId: channelId, topic: topic as string })
|
|
34
|
+
.onConflict((oc) => oc.columns(['channelId', 'topic']).doNothing())
|
|
35
35
|
.execute()
|
|
36
36
|
return true
|
|
37
37
|
} catch {
|
|
@@ -41,8 +41,8 @@ export class KyselyEventHubStore extends EventHubStore {
|
|
|
41
41
|
|
|
42
42
|
public async unsubscribe(topic: string, channelId: string): Promise<boolean> {
|
|
43
43
|
const result = await this.db
|
|
44
|
-
.deleteFrom('
|
|
45
|
-
.where('
|
|
44
|
+
.deleteFrom('channelSubscriptions')
|
|
45
|
+
.where('channelId', '=', channelId)
|
|
46
46
|
.where('topic', '=', topic as string)
|
|
47
47
|
.executeTakeFirst()
|
|
48
48
|
|
|
@@ -77,12 +77,12 @@ export class KyselySecretService implements SecretService {
|
|
|
77
77
|
if (action === 'read' && !this.auditReads) return
|
|
78
78
|
|
|
79
79
|
await this.db
|
|
80
|
-
.insertInto('
|
|
80
|
+
.insertInto('secretsAudit')
|
|
81
81
|
.values({
|
|
82
82
|
id: crypto.randomUUID(),
|
|
83
|
-
|
|
83
|
+
secretKey: secretKey,
|
|
84
84
|
action,
|
|
85
|
-
|
|
85
|
+
performedAt: new Date().toISOString() as unknown as Date,
|
|
86
86
|
})
|
|
87
87
|
.execute()
|
|
88
88
|
}
|
|
@@ -96,17 +96,17 @@ export class KyselySecretService implements SecretService {
|
|
|
96
96
|
async getSecret(key: string): Promise<string> {
|
|
97
97
|
const row = await this.db
|
|
98
98
|
.selectFrom('secrets')
|
|
99
|
-
.select(['ciphertext', '
|
|
99
|
+
.select(['ciphertext', 'wrappedDek', 'keyVersion'])
|
|
100
100
|
.where('key', '=', key)
|
|
101
101
|
.executeTakeFirst()
|
|
102
102
|
|
|
103
103
|
if (!row) throw new Error('Requested secret not found')
|
|
104
104
|
|
|
105
|
-
const kek = this.getKEK(row.
|
|
105
|
+
const kek = this.getKEK(row.keyVersion)
|
|
106
106
|
const result = await envelopeDecrypt<string>(
|
|
107
107
|
kek,
|
|
108
108
|
row.ciphertext,
|
|
109
|
-
row.
|
|
109
|
+
row.wrappedDek
|
|
110
110
|
)
|
|
111
111
|
await this.logAudit(key, 'read')
|
|
112
112
|
return result
|
|
@@ -139,17 +139,17 @@ export class KyselySecretService implements SecretService {
|
|
|
139
139
|
.values({
|
|
140
140
|
key,
|
|
141
141
|
ciphertext,
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
142
|
+
wrappedDek: wrappedDEK,
|
|
143
|
+
keyVersion: this.keyVersion,
|
|
144
|
+
createdAt: now as unknown as Date,
|
|
145
|
+
updatedAt: now as unknown as Date,
|
|
146
146
|
})
|
|
147
147
|
.onConflict((oc) =>
|
|
148
148
|
oc.column('key').doUpdateSet({
|
|
149
149
|
ciphertext,
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
150
|
+
wrappedDek: wrappedDEK,
|
|
151
|
+
keyVersion: this.keyVersion,
|
|
152
|
+
updatedAt: now as unknown as Date,
|
|
153
153
|
})
|
|
154
154
|
)
|
|
155
155
|
.execute()
|
|
@@ -169,22 +169,22 @@ export class KyselySecretService implements SecretService {
|
|
|
169
169
|
|
|
170
170
|
const rows = await this.db
|
|
171
171
|
.selectFrom('secrets')
|
|
172
|
-
.select(['key', '
|
|
173
|
-
.where('
|
|
172
|
+
.select(['key', 'wrappedDek'])
|
|
173
|
+
.where('keyVersion', '<', this.keyVersion)
|
|
174
174
|
.execute()
|
|
175
175
|
|
|
176
176
|
for (const row of rows) {
|
|
177
177
|
const newWrappedDEK = await envelopeRewrap(
|
|
178
178
|
this.previousKey,
|
|
179
179
|
this.key,
|
|
180
|
-
row.
|
|
180
|
+
row.wrappedDek
|
|
181
181
|
)
|
|
182
182
|
await this.db
|
|
183
183
|
.updateTable('secrets')
|
|
184
184
|
.set({
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
185
|
+
wrappedDek: newWrappedDEK,
|
|
186
|
+
keyVersion: this.keyVersion,
|
|
187
|
+
updatedAt: new Date().toISOString() as unknown as Date,
|
|
188
188
|
})
|
|
189
189
|
.where('key', '=', row.key)
|
|
190
190
|
.execute()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, test, before, after } from 'node:test'
|
|
2
2
|
import assert from 'node:assert/strict'
|
|
3
|
-
import { Kysely, SqliteDialect } from 'kysely'
|
|
3
|
+
import { CamelCasePlugin, Kysely, SqliteDialect } from 'kysely'
|
|
4
4
|
import { SerializePlugin } from 'kysely-plugin-serialize'
|
|
5
5
|
import Database from 'better-sqlite3'
|
|
6
6
|
import { PostgresJSDialect } from 'kysely-postgres-js'
|
|
@@ -23,7 +23,7 @@ function createSqliteDb(): Kysely<KyselyPikkuDB> {
|
|
|
23
23
|
dialect: new SqliteDialect({
|
|
24
24
|
database: new Database(':memory:'),
|
|
25
25
|
}),
|
|
26
|
-
plugins: [new SerializePlugin()],
|
|
26
|
+
plugins: [new CamelCasePlugin(), new SerializePlugin()],
|
|
27
27
|
})
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -33,6 +33,7 @@ function createPostgresDb(): Kysely<KyselyPikkuDB> | null {
|
|
|
33
33
|
|
|
34
34
|
return new Kysely<KyselyPikkuDB>({
|
|
35
35
|
dialect: new PostgresJSDialect({ postgres: postgres(url) }),
|
|
36
|
+
plugins: [new CamelCasePlugin()],
|
|
36
37
|
})
|
|
37
38
|
}
|
|
38
39
|
|
|
@@ -126,10 +127,10 @@ function registerTests(
|
|
|
126
127
|
await service.deleteSecret('audit-test')
|
|
127
128
|
|
|
128
129
|
const logs = await getDb()
|
|
129
|
-
.selectFrom('
|
|
130
|
-
.select(['
|
|
131
|
-
.where('
|
|
132
|
-
.orderBy('
|
|
130
|
+
.selectFrom('secretsAudit')
|
|
131
|
+
.select(['secretKey', 'action'])
|
|
132
|
+
.where('secretKey', '=', 'audit-test')
|
|
133
|
+
.orderBy('performedAt', 'asc')
|
|
133
134
|
.execute()
|
|
134
135
|
|
|
135
136
|
assert.equal(logs.length, 3)
|
|
@@ -149,9 +150,9 @@ function registerTests(
|
|
|
149
150
|
await service.getSecret('no-read-audit')
|
|
150
151
|
|
|
151
152
|
const logs = await getDb()
|
|
152
|
-
.selectFrom('
|
|
153
|
+
.selectFrom('secretsAudit')
|
|
153
154
|
.select(['action'])
|
|
154
|
-
.where('
|
|
155
|
+
.where('secretKey', '=', 'no-read-audit')
|
|
155
156
|
.execute()
|
|
156
157
|
|
|
157
158
|
assert.equal(logs.length, 1)
|
|
@@ -174,15 +175,15 @@ function registerTests(
|
|
|
174
175
|
await service.delete('audit-cred', 'user-1')
|
|
175
176
|
|
|
176
177
|
const logs = await getDb()
|
|
177
|
-
.selectFrom('
|
|
178
|
-
.select(['
|
|
179
|
-
.where('
|
|
180
|
-
.orderBy('
|
|
178
|
+
.selectFrom('credentialsAudit')
|
|
179
|
+
.select(['credentialName', 'userId', 'action'])
|
|
180
|
+
.where('credentialName', '=', 'audit-cred')
|
|
181
|
+
.orderBy('performedAt', 'asc')
|
|
181
182
|
.execute()
|
|
182
183
|
|
|
183
184
|
assert.equal(logs.length, 3)
|
|
184
185
|
assert.equal(logs[0]!.action, 'write')
|
|
185
|
-
assert.equal(logs[0]!.
|
|
186
|
+
assert.equal(logs[0]!.userId, 'user-1')
|
|
186
187
|
assert.equal(logs[1]!.action, 'read')
|
|
187
188
|
assert.equal(logs[2]!.action, 'delete')
|
|
188
189
|
})
|
|
@@ -198,14 +199,14 @@ function registerTests(
|
|
|
198
199
|
await service.get('global-cred')
|
|
199
200
|
|
|
200
201
|
const logs = await getDb()
|
|
201
|
-
.selectFrom('
|
|
202
|
-
.select(['
|
|
203
|
-
.where('
|
|
202
|
+
.selectFrom('credentialsAudit')
|
|
203
|
+
.select(['credentialName', 'userId', 'action'])
|
|
204
|
+
.where('credentialName', '=', 'global-cred')
|
|
204
205
|
.execute()
|
|
205
206
|
|
|
206
207
|
assert.equal(logs.length, 2)
|
|
207
|
-
assert.equal(logs[0]!.
|
|
208
|
-
assert.equal(logs[1]!.
|
|
208
|
+
assert.equal(logs[0]!.userId, null)
|
|
209
|
+
assert.equal(logs[1]!.userId, null)
|
|
209
210
|
})
|
|
210
211
|
})
|
|
211
212
|
}
|