Skip to content

Commit 07794f3

Browse files
committed
Use explicit selects and remove sensitive fields from responses
- Replace .selectAll()/.returningAll() with explicit select attributes - Add reusable helpers: timestampsSelect, resourceSelect - Use enumToText<T>() for enum compatibility with Postgate HTTP - Remove sensitive fields from response types: - connectionString from DatabaseConfigRow - accessKeyId/secretAccessKey from StorageConfigRow - Remove script from workers list (too large, fetched separately) - Add select constants for consistency across all db services Impact: Better performance, improved security, Postgate compatibility
1 parent acc59d8 commit 07794f3

11 files changed

Lines changed: 98 additions & 71 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "openworkers-api",
3-
"version": "1.5.2",
3+
"version": "1.5.3",
44
"license": "MIT",
55
"module": "src/index.ts",
66
"type": "module",

src/services/db/auth-tokens.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ interface AuthToken {
1212
createdAt: Date;
1313
}
1414

15+
const authTokenSelect = ['id', 'userId', 'token', 'type', 'expiresAt', 'createdAt'] as const;
16+
1517
function generateToken(): string {
1618
const bytes = new Uint8Array(32);
1719
crypto.getRandomValues(bytes);
@@ -40,7 +42,7 @@ export async function createAuthToken(userId: string, type: TokenType, expiresIn
4042
export async function findAuthToken(token: string, type: TokenType): Promise<AuthToken | null> {
4143
const authToken = await kysely
4244
.selectFrom('authTokens')
43-
.selectAll()
45+
.select(authTokenSelect)
4446
.where('token', '=', token)
4547
.where('type', '=', enumCast(type, 'auth_token_type'))
4648
.where('expiresAt', '>', now())

src/services/db/crons.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,21 @@ import { sql } from 'kysely';
44
import type { ICron } from '../../types';
55
import { findWorkerById } from './workers';
66

7+
const cronSelect = [
8+
'crons.id',
9+
'crons.value',
10+
'crons.workerId',
11+
'crons.nextRun',
12+
'crons.lastRun',
13+
'crons.createdAt',
14+
'crons.updatedAt'
15+
] as const;
16+
717
export async function findCronById(userId: string, cronId: string): Promise<ICron | null> {
818
const cron = await kysely
919
.selectFrom('crons')
1020
.innerJoin('workers', 'crons.workerId', 'workers.id')
11-
.select([
12-
'crons.id',
13-
'crons.value',
14-
'crons.workerId',
15-
'crons.nextRun',
16-
'crons.lastRun',
17-
'crons.createdAt',
18-
'crons.updatedAt'
19-
])
21+
.select(cronSelect)
2022
.where('crons.id', '=', uuid(cronId))
2123
.where('workers.userId', '=', uuid(userId))
2224
.executeTakeFirst();
@@ -38,7 +40,7 @@ export async function createCron(userId: string, workerId: string, value: string
3840
workerId: uuid(workerId),
3941
nextRun: timestamptz(nextRun)
4042
})
41-
.returningAll()
43+
.returning(cronSelect)
4244
.executeTakeFirstOrThrow();
4345
}
4446

src/services/db/databases.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { kysely } from './kysely-client';
2-
import { uuid, now, enumCast } from './kysely-helpers';
2+
import { uuid, now, enumCast, enumToText } from './kysely-helpers';
33
import type { DatabaseProvider } from '../../types';
44

55
interface DatabaseConfigRow {
@@ -8,18 +8,30 @@ interface DatabaseConfigRow {
88
desc: string | null;
99
userId: string;
1010
provider: DatabaseProvider;
11-
connectionString: string | null;
1211
schemaName: string | null;
1312
maxRows: number;
1413
timeoutSeconds: number;
1514
createdAt: Date;
1615
updatedAt: Date;
1716
}
1817

18+
const selectAttributes = [
19+
'id',
20+
'name',
21+
'desc',
22+
'userId',
23+
enumToText<DatabaseProvider>('provider').as('provider'),
24+
'schemaName',
25+
'maxRows',
26+
'timeoutSeconds',
27+
'createdAt',
28+
'updatedAt'
29+
] as const;
30+
1931
export async function findAllDatabases(userId: string): Promise<DatabaseConfigRow[]> {
2032
return kysely
2133
.selectFrom('databaseConfigs')
22-
.selectAll()
34+
.select(selectAttributes)
2335
.where('userId', '=', uuid(userId))
2436
.orderBy('createdAt', 'desc')
2537
.execute();
@@ -28,7 +40,7 @@ export async function findAllDatabases(userId: string): Promise<DatabaseConfigRo
2840
export async function findDatabaseById(userId: string, id: string): Promise<DatabaseConfigRow | null> {
2941
const row = await kysely
3042
.selectFrom('databaseConfigs')
31-
.selectAll()
43+
.select(selectAttributes)
3244
.where('id', '=', uuid(id))
3345
.where('userId', '=', uuid(userId))
3446
.executeTakeFirst();
@@ -39,7 +51,7 @@ export async function findDatabaseById(userId: string, id: string): Promise<Data
3951
export async function findDatabaseByName(userId: string, name: string): Promise<DatabaseConfigRow | null> {
4052
const row = await kysely
4153
.selectFrom('databaseConfigs')
42-
.selectAll()
54+
.select(selectAttributes)
4355
.where('name', '=', name)
4456
.where('userId', '=', uuid(userId))
4557
.executeTakeFirst();
@@ -67,7 +79,7 @@ export async function createPlatformDatabase(userId: string, input: CreatePlatfo
6779
maxRows: input.maxRows,
6880
timeoutSeconds: input.timeoutSeconds
6981
})
70-
.returningAll()
82+
.returning(selectAttributes)
7183
.executeTakeFirstOrThrow();
7284
}
7385

@@ -91,7 +103,7 @@ export async function createPostgresDatabase(userId: string, input: CreatePostgr
91103
maxRows: input.maxRows,
92104
timeoutSeconds: input.timeoutSeconds
93105
})
94-
.returningAll()
106+
.returning(selectAttributes)
95107
.executeTakeFirstOrThrow();
96108
}
97109

@@ -136,7 +148,7 @@ export async function updateDatabase(
136148
.set(updates)
137149
.where('id', '=', uuid(id))
138150
.where('userId', '=', uuid(userId))
139-
.returningAll()
151+
.returning(selectAttributes)
140152
.executeTakeFirst();
141153

142154
return row ?? null;

src/services/db/domains.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
import { kysely } from './kysely-client';
2-
import { uuid } from './kysely-helpers';
2+
import { timestampsSelect, uuid } from './kysely-helpers';
33
import type { IDomain } from '../../types';
44
import { findWorkerById } from './workers';
55

6+
const domainSelect = ['workerId', 'userId', 'name', ...timestampsSelect] as const;
7+
68
export async function findAllDomains(userId: string): Promise<IDomain[]> {
79
return kysely
810
.selectFrom('domains')
9-
.selectAll()
11+
.select(domainSelect)
1012
.where('userId', '=', uuid(userId))
1113
.orderBy('createdAt', 'desc')
1214
.execute();
1315
}
1416

1517
export async function findDomainByName(name: string): Promise<IDomain | null> {
16-
const domain = await kysely.selectFrom('domains').selectAll().where('name', '=', name).executeTakeFirst();
18+
const domain = await kysely.selectFrom('domains').select(domainSelect).where('name', '=', name).executeTakeFirst();
1719

1820
return domain ?? null;
1921
}
@@ -32,7 +34,7 @@ export async function createDomain(userId: string, workerId: string, name: strin
3234
workerId: uuid(workerId),
3335
userId: uuid(userId)
3436
})
35-
.returningAll()
37+
.returning(domainSelect)
3638
.executeTakeFirstOrThrow();
3739
}
3840

@@ -71,7 +73,7 @@ export async function updateWorkerDomains(userId: string, workerId: string, newD
7173
// Get current domains for this worker
7274
const currentDomains = await kysely
7375
.selectFrom('domains')
74-
.selectAll()
76+
.select(domainSelect)
7577
.where('workerId', '=', uuid(workerId))
7678
.where('userId', '=', uuid(userId))
7779
.execute();

src/services/db/environments.ts

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { kysely } from './kysely-client';
2-
import { uuid, enumCast } from './kysely-helpers';
2+
import { uuid, enumCast, resourceSelect } from './kysely-helpers';
33
import { sql } from 'kysely';
44
import type { IEnvironment, IEnvironmentValue } from '../../types';
55

@@ -14,12 +14,9 @@ interface EnvironmentRow {
1414
workers: IEnvironment['workers'];
1515
}
1616

17-
interface EnvironmentValueRow {
18-
id: string;
19-
key: string;
20-
value: string;
21-
type: string;
22-
}
17+
const environmentSelect = [...resourceSelect] as const;
18+
19+
const environmentValueSelect = ['id', 'key', 'value', 'type'] as const;
2320

2421
// Environments
2522
export async function findAllEnvironments(userId: string): Promise<IEnvironment[]> {
@@ -142,7 +139,7 @@ export async function createEnvironment(userId: string, name: string, desc?: str
142139
desc: desc ?? null,
143140
userId: uuid(userId)
144141
})
145-
.returning(['id', 'name', 'desc', 'userId', 'createdAt', 'updatedAt'])
142+
.returning(environmentSelect)
146143
.executeTakeFirstOrThrow();
147144

148145
// Return with empty values and workers arrays
@@ -175,7 +172,7 @@ export async function updateEnvironment(
175172
.set(updateData)
176173
.where('id', '=', uuid(envId))
177174
.where('userId', '=', uuid(userId))
178-
.returning(['id', 'name', 'desc', 'userId', 'createdAt', 'updatedAt'])
175+
.returning(environmentSelect)
179176
.executeTakeFirst();
180177

181178
if (!env) return null;
@@ -216,7 +213,7 @@ export async function createEnvironmentValue(
216213
environmentId: uuid(envId),
217214
userId: uuid(userId)
218215
})
219-
.returningAll()
216+
.returning(environmentValueSelect)
220217
.executeTakeFirstOrThrow();
221218
}
222219

@@ -242,7 +239,7 @@ export async function updateEnvironmentValue(
242239
if (Object.keys(updateData).length === 0) {
243240
const full = await kysely
244241
.selectFrom('environmentValues')
245-
.selectAll()
242+
.select(environmentValueSelect)
246243
.where('id', '=', uuid(valId))
247244
.executeTakeFirst();
248245
return full ?? null;
@@ -253,7 +250,7 @@ export async function updateEnvironmentValue(
253250
.set(updateData)
254251
.where('id', '=', uuid(valId))
255252
.where('userId', '=', uuid(userId))
256-
.returningAll()
253+
.returning(environmentValueSelect)
257254
.executeTakeFirst();
258255

259256
return val ?? null;

src/services/db/kv.ts

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ export interface KvNamespaceRow {
1010
updatedAt: Date;
1111
}
1212

13+
const kvNamespaceSelect = ['id', 'name', 'desc', 'createdAt', 'updatedAt'] as const;
14+
1315
export async function findAllKvNamespaces(userId: string): Promise<KvNamespaceRow[]> {
1416
return kysely
1517
.selectFrom('kvConfigs')
16-
.select(['id', 'name', 'desc', 'createdAt', 'updatedAt'])
18+
.select(kvNamespaceSelect)
1719
.where('userId', '=', uuid(userId))
1820
.orderBy('createdAt', 'desc')
1921
.execute();
@@ -22,7 +24,7 @@ export async function findAllKvNamespaces(userId: string): Promise<KvNamespaceRo
2224
export async function findKvNamespaceById(userId: string, id: string): Promise<KvNamespaceRow | null> {
2325
const result = await kysely
2426
.selectFrom('kvConfigs')
25-
.select(['id', 'name', 'desc', 'createdAt', 'updatedAt'])
27+
.select(kvNamespaceSelect)
2628
.where('userId', '=', uuid(userId))
2729
.where('id', '=', uuid(id))
2830
.executeTakeFirst();
@@ -33,7 +35,7 @@ export async function findKvNamespaceById(userId: string, id: string): Promise<K
3335
export async function findKvNamespaceByName(userId: string, name: string): Promise<KvNamespaceRow | null> {
3436
const result = await kysely
3537
.selectFrom('kvConfigs')
36-
.select(['id', 'name', 'desc', 'createdAt', 'updatedAt'])
38+
.select(kvNamespaceSelect)
3739
.where('userId', '=', uuid(userId))
3840
.where('name', '=', name)
3941
.executeTakeFirst();
@@ -49,7 +51,7 @@ export async function createKvNamespace(userId: string, name: string, desc?: str
4951
name,
5052
desc: desc ?? null
5153
})
52-
.returning(['id', 'name', 'desc', 'createdAt', 'updatedAt'])
54+
.returning(kvNamespaceSelect)
5355
.executeTakeFirstOrThrow();
5456
}
5557

@@ -75,7 +77,7 @@ export async function updateKvNamespace(
7577
.set(updates)
7678
.where('userId', '=', uuid(userId))
7779
.where('id', '=', uuid(id))
78-
.returning(['id', 'name', 'desc', 'createdAt', 'updatedAt'])
80+
.returning(kvNamespaceSelect)
7981
.executeTakeFirst();
8082

8183
return result ?? null;
@@ -112,6 +114,8 @@ export interface KvDataRow {
112114
updatedAt: Date;
113115
}
114116

117+
const kvDataSelect = ['key', 'value', 'expiresAt', 'createdAt', 'updatedAt'] as const;
118+
115119
export interface KvDataListResult {
116120
items: KvDataRow[];
117121
cursor: string | null;
@@ -126,7 +130,7 @@ export async function listKvData(
126130

127131
let query = kysely
128132
.selectFrom('kvData')
129-
.selectAll()
133+
.select(kvDataSelect)
130134
.where('namespaceId', '=', uuid(namespaceId))
131135
.where((eb) => eb.or([eb('expiresAt', 'is', null), eb('expiresAt', '>', now())]));
132136

@@ -173,7 +177,7 @@ export async function putKvData(
173177
updatedAt: now()
174178
})
175179
)
176-
.returningAll()
180+
.returning(kvDataSelect)
177181
.executeTakeFirstOrThrow();
178182
}
179183

src/services/db/kysely-helpers.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { sql } from 'kysely';
22
import type { RawBuilder } from 'kysely';
33

4+
export const timestampsSelect = ['createdAt', 'updatedAt'] as const;
5+
export const resourceSelect = ['id', 'name', 'desc', 'userId', ...timestampsSelect] as const;
6+
47
/**
58
* Cast value to UUID type for Postgate
69
* @example

0 commit comments

Comments
 (0)