Skip to content

Commit a49ed0e

Browse files
cezudasCopilot
andauthored
Enable tables block actions to use database tokens for fields and rows helpers (#1666)
Fixes OPS-3022, OPS-3023, OPS-3024. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit ## Release Notes * **Refactor** * Updated authentication and token handling to use a more flexible token resolution mechanism across all table operations. * Improved context-aware token resolution for enhanced security and flexibility. * Standardized token parameter naming and propagation throughout the table actions API. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Copilot <[email protected]>
1 parent 9f521b7 commit a49ed0e

File tree

10 files changed

+129
-65
lines changed

10 files changed

+129
-65
lines changed

packages/blocks/openops-tables/src/actions/delete-record-action.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { BlockAuth, createAction, Property } from '@openops/blocks-framework';
22
import {
3-
authenticateDefaultUserInOpenOpsTables,
43
deleteRow,
54
getFields,
65
getPrimaryKeyFieldFromFields,
76
getRowByPrimaryKeyValue,
87
getTableIdByTableName,
8+
OpenOpsField,
99
openopsTablesDropdownProperty,
10+
resolveTokenProvider,
11+
TokenOrResolver,
1012
} from '@openops/common';
1113
import { cacheWrapper } from '@openops/server-shared';
1214
import { convertToStringWithValidation, isEmpty } from '@openops/shared';
@@ -34,19 +36,19 @@ export const deleteRecordAction = createAction({
3436
[tableName],
3537
);
3638

37-
const { token } = await authenticateDefaultUserInOpenOpsTables();
39+
const tokenOrResolver = await resolveTokenProvider(context.server);
3840

3941
const fieldsCacheKey = `${context.run.id}-${tableId}-fields`;
40-
const fields = await cacheWrapper.getOrAdd(fieldsCacheKey, getFields, [
41-
tableId,
42-
token,
43-
]);
42+
const fields = await cacheWrapper.getOrAdd<
43+
OpenOpsField[],
44+
[number, TokenOrResolver]
45+
>(fieldsCacheKey, getFields, [tableId, tokenOrResolver]);
4446

4547
const primaryKeyField = getPrimaryKeyFieldFromFields(fields);
4648
const rowPrimaryKey = getPrimaryKey(context.propsValue.rowPrimaryKey);
4749

4850
const rowToDelete = await getRowByPrimaryKeyValue(
49-
token,
51+
tokenOrResolver,
5052
tableId,
5153
rowPrimaryKey,
5254
primaryKeyField.name,
@@ -58,8 +60,8 @@ export const deleteRecordAction = createAction({
5860

5961
return await deleteRow({
6062
tableId: tableId,
61-
token: token,
6263
rowId: rowToDelete.id,
64+
tokenOrResolver,
6365
});
6466
},
6567
});

packages/blocks/openops-tables/src/actions/get-records-action.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { BlockAuth, createAction, Property } from '@openops/blocks-framework';
22
import {
3-
authenticateDefaultUserInOpenOpsTables,
43
FilterType,
54
getPropertyFromField,
65
getRows,
76
getTableFields,
87
getTableIdByTableName,
98
isSingleValueFilter,
109
openopsTablesDropdownProperty,
10+
resolveTokenProvider,
1111
ViewFilterTypesEnum,
1212
} from '@openops/common';
1313
import { cacheWrapper } from '@openops/server-shared';
@@ -113,8 +113,6 @@ export const getRecordsAction = createAction({
113113
}),
114114
},
115115
async run(context) {
116-
const { token } = await authenticateDefaultUserInOpenOpsTables();
117-
118116
const tableName = context.propsValue.tableName as unknown as string;
119117

120118
const tableCacheKey = `${context.run.id}-table-${tableName}`;
@@ -142,10 +140,11 @@ export const getRecordsAction = createAction({
142140
};
143141
});
144142
const filterType = context.propsValue.filterType as FilterType;
143+
const tokenOrResolver = await resolveTokenProvider(context.server);
145144

146145
const rows = await getRows({
147146
tableId: tableId,
148-
token: token,
147+
tokenOrResolver,
149148
filters,
150149
filterType: filterType,
151150
});

packages/blocks/openops-tables/src/actions/update-record-action.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
import { BlockAuth, createAction, Property } from '@openops/blocks-framework';
22
import {
3-
authenticateDefaultUserInOpenOpsTables,
43
getFields,
54
getPrimaryKeyFieldFromFields,
65
getPropertyFromField,
76
getTableFields,
87
getTableIdByTableName,
98
OpenOpsField,
109
openopsTablesDropdownProperty,
10+
resolveTokenProvider,
11+
TokenOrResolver,
1112
upsertRow,
1213
} from '@openops/common';
1314
import { cacheWrapper } from '@openops/server-shared';
@@ -61,7 +62,7 @@ export const updateRecordAction = createAction({
6162
description: '',
6263
required: true,
6364
refreshers: ['tableName'],
64-
props: async ({ tableName }) => {
65+
props: async ({ tableName }, context) => {
6566
if (!tableName) {
6667
return {};
6768
}
@@ -131,13 +132,12 @@ export const updateRecordAction = createAction({
131132
[tableName],
132133
);
133134

134-
const { token } = await authenticateDefaultUserInOpenOpsTables();
135-
136135
const fieldsCacheKey = `${context.run.id}-${tableId}-fields`;
137-
const tableFields = await cacheWrapper.getOrAdd(fieldsCacheKey, getFields, [
138-
tableId,
139-
token,
140-
]);
136+
const tokenOrResolver = await resolveTokenProvider(context.server);
137+
const tableFields = await cacheWrapper.getOrAdd<
138+
OpenOpsField[],
139+
[number, TokenOrResolver]
140+
>(fieldsCacheKey, getFields, [tableId, tokenOrResolver]);
141141

142142
const fieldsToUpdate = mapFieldsToObject(
143143
tableName,
@@ -152,8 +152,8 @@ export const updateRecordAction = createAction({
152152

153153
return await upsertRow({
154154
tableId: tableId,
155-
token: token,
156155
fields: fieldsToUpdate,
156+
tokenOrResolver,
157157
});
158158
},
159159
});

packages/blocks/openops-tables/test/actions/delete-record-action.test.ts

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ const openopsCommonMock = {
1818
type: 'DROPDOWN',
1919
}),
2020
deleteRow: jest.fn(),
21+
resolveTokenProvider: jest.fn(async (serverContext) => {
22+
return {
23+
getToken: () => serverContext.tablesDatabaseToken,
24+
};
25+
}),
2126
};
2227

2328
jest.mock('@openops/common', () => openopsCommonMock);
@@ -65,12 +70,11 @@ describe('deleteRecordAction', () => {
6570
validateWrapperCall(context);
6671

6772
expect(result).toStrictEqual('mock result');
68-
expect(
69-
openopsCommonMock.authenticateDefaultUserInOpenOpsTables,
70-
).toHaveBeenCalledTimes(1);
71-
expect(
72-
openopsCommonMock.authenticateDefaultUserInOpenOpsTables,
73-
).toHaveBeenCalledWith();
73+
expect(openopsCommonMock.resolveTokenProvider).toHaveBeenCalledTimes(1);
74+
expect(openopsCommonMock.resolveTokenProvider).toHaveBeenCalledWith({
75+
tablesDatabaseId: 1,
76+
tablesDatabaseToken: 'some databaseToken',
77+
});
7478
});
7579

7680
test.each([[[]], [{}]])(
@@ -170,7 +174,9 @@ describe('deleteRecordAction', () => {
170174
);
171175
expect(openopsCommonMock.getRowByPrimaryKeyValue).toHaveBeenCalledTimes(1);
172176
expect(openopsCommonMock.getRowByPrimaryKeyValue).toHaveBeenCalledWith(
173-
'some databaseToken',
177+
expect.objectContaining({
178+
getToken: expect.any(Function),
179+
}),
174180
1,
175181
'some primary key value',
176182
'primary key field',
@@ -204,7 +210,9 @@ describe('deleteRecordAction', () => {
204210

205211
expect(openopsCommonMock.getRowByPrimaryKeyValue).toHaveBeenCalledTimes(1);
206212
expect(openopsCommonMock.getRowByPrimaryKeyValue).toHaveBeenCalledWith(
207-
'some databaseToken',
213+
expect.objectContaining({
214+
getToken: expect.any(Function),
215+
}),
208216
1,
209217
'some primary key value',
210218
'primary key field',
@@ -219,7 +227,9 @@ describe('deleteRecordAction', () => {
219227
expect(openopsCommonMock.deleteRow).toHaveBeenCalledTimes(1);
220228
expect(openopsCommonMock.deleteRow).toHaveBeenCalledWith({
221229
tableId: 1,
222-
token: 'some databaseToken',
230+
tokenOrResolver: expect.objectContaining({
231+
getToken: expect.any(Function),
232+
}),
223233
rowId: 1,
224234
});
225235
});
@@ -237,7 +247,12 @@ function validateWrapperCall(context: any) {
237247
2,
238248
`${context.run.id}-1-fields`,
239249
getFields,
240-
[1, 'some databaseToken'],
250+
[
251+
1,
252+
expect.objectContaining({
253+
getToken: expect.any(Function),
254+
}),
255+
],
241256
);
242257
}
243258

@@ -253,6 +268,10 @@ function createContext(params?: ContextParams) {
253268
tableName: params?.tableName ?? '1',
254269
rowPrimaryKey: params?.rowPrimaryKey ?? 'default primary key',
255270
},
271+
server: {
272+
tablesDatabaseId: 1,
273+
tablesDatabaseToken: 'some databaseToken',
274+
},
256275
run: {
257276
id: nanoid(),
258277
},

packages/blocks/openops-tables/test/actions/get-records-action.test.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ const openopsCommonMock = {
2424
type: 'text',
2525
},
2626
]),
27+
resolveTokenProvider: jest.fn(async (serverContext) => {
28+
return {
29+
getToken: () => serverContext.tablesDatabaseToken,
30+
};
31+
}),
2732
openopsTablesDropdownProperty: jest.fn().mockReturnValue({
2833
required: true,
2934
defaultValue: false,
@@ -110,12 +115,11 @@ describe('getRecordsAction test', () => {
110115

111116
validateWrapperCall(context);
112117
expect(result).toStrictEqual({ items: [], count: 0 });
113-
expect(
114-
openopsCommonMock.authenticateDefaultUserInOpenOpsTables,
115-
).toHaveBeenCalledTimes(1);
116-
expect(
117-
openopsCommonMock.authenticateDefaultUserInOpenOpsTables,
118-
).toHaveBeenCalledWith();
118+
expect(openopsCommonMock.resolveTokenProvider).toHaveBeenCalledTimes(1);
119+
expect(openopsCommonMock.resolveTokenProvider).toHaveBeenCalledWith({
120+
tablesDatabaseId: 1,
121+
tablesDatabaseToken: 'token',
122+
});
119123
});
120124

121125
test('should get row with the given filters', async () => {
@@ -145,7 +149,9 @@ describe('getRecordsAction test', () => {
145149
expect(openopsCommonMock.getRows).toHaveBeenCalledTimes(1);
146150
expect(openopsCommonMock.getRows).toHaveBeenCalledWith({
147151
tableId: 123,
148-
token: 'some databaseToken',
152+
tokenOrResolver: expect.objectContaining({
153+
getToken: expect.any(Function),
154+
}),
149155
filters: [
150156
{
151157
fieldName: 'field name',
@@ -279,7 +285,9 @@ describe('getRecordsAction test', () => {
279285
expect(openopsCommonMock.getRows).toHaveBeenCalledTimes(1);
280286
expect(openopsCommonMock.getRows).toHaveBeenCalledWith({
281287
tableId: 123,
282-
token: 'some databaseToken',
288+
tokenOrResolver: expect.objectContaining({
289+
getToken: expect.any(Function),
290+
}),
283291
filters: [
284292
{
285293
fieldName: 'a',
@@ -328,6 +336,10 @@ function createContext(params?: ContextParams) {
328336
filterType: params?.filterType,
329337
filters: { filters: params?.filters || [] },
330338
},
339+
server: {
340+
tablesDatabaseId: 1,
341+
tablesDatabaseToken: 'token',
342+
},
331343
run: {
332344
id: nanoid(),
333345
},

packages/blocks/openops-tables/test/actions/get-table-url-action.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ describe('getTableUrlAction', () => {
5050
propsValue: {
5151
tableName: 'my table',
5252
},
53+
server: {
54+
tablesDatabaseId: 1,
55+
tablesDatabaseToken: 'token',
56+
},
5357
};
5458

5559
const result = (await getTableUrlAction.run(context)) as any;

packages/blocks/openops-tables/test/actions/update-record-action.test.ts

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ const openopsCommonMock = {
1414
authenticateDefaultUserInOpenOpsTables: jest.fn(),
1515
getPrimaryKeyFieldFromFields: jest.fn(),
1616
getTableFields: jest.fn().mockResolvedValue([{}]),
17+
resolveTokenProvider: jest.fn(async (serverContext) => {
18+
return {
19+
getToken: () => serverContext.tablesDatabaseToken,
20+
};
21+
}),
1722
openopsTablesDropdownProperty: jest.fn().mockReturnValue({
1823
required: true,
1924
defaultValue: false,
@@ -32,7 +37,9 @@ describe('updateRowAction', () => {
3237
beforeEach(() => {
3338
jest.clearAllMocks();
3439
openopsCommonMock.authenticateDefaultUserInOpenOpsTables.mockResolvedValue({
35-
token: 'some databaseToken',
40+
tokenOrResolver: expect.objectContaining({
41+
getToken: expect.any(Function),
42+
}),
3643
});
3744
});
3845

@@ -117,12 +124,11 @@ describe('updateRowAction', () => {
117124

118125
validateWrapperCall(context);
119126
expect(result).toStrictEqual('mock result');
120-
expect(
121-
openopsCommonMock.authenticateDefaultUserInOpenOpsTables,
122-
).toHaveBeenCalledTimes(1);
123-
expect(
124-
openopsCommonMock.authenticateDefaultUserInOpenOpsTables,
125-
).toHaveBeenCalledWith();
127+
expect(openopsCommonMock.resolveTokenProvider).toHaveBeenCalledTimes(1);
128+
expect(openopsCommonMock.resolveTokenProvider).toHaveBeenCalledWith({
129+
tablesDatabaseId: 1,
130+
tablesDatabaseToken: 'token',
131+
});
126132
});
127133

128134
test('should invoke upsertRow operation', async () => {
@@ -153,7 +159,9 @@ describe('updateRowAction', () => {
153159
expect(openopsCommonMock.upsertRow).toHaveBeenCalledTimes(1);
154160
expect(openopsCommonMock.upsertRow).toHaveBeenCalledWith({
155161
tableId: 1,
156-
token: 'some databaseToken',
162+
tokenOrResolver: expect.objectContaining({
163+
getToken: expect.any(Function),
164+
}),
157165
fields: {
158166
'primary key field': 'some primary key value',
159167
field1: 'new value',
@@ -381,7 +389,12 @@ function validateWrapperCall(context: any) {
381389
2,
382390
`${context.run.id}-1-fields`,
383391
getFields,
384-
[1, 'some databaseToken'],
392+
[
393+
1,
394+
expect.objectContaining({
395+
getToken: expect.any(Function),
396+
}),
397+
],
385398
);
386399
}
387400

@@ -401,6 +414,10 @@ function createContext(params?: ContextParams) {
401414
},
402415
fieldsProperties: { fieldsProperties: params?.fieldsProperties },
403416
},
417+
server: {
418+
tablesDatabaseId: 1,
419+
tablesDatabaseToken: 'token',
420+
},
404421
run: {
405422
id: nanoid(),
406423
},

packages/openops/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export * from './lib/aws/pricing';
3838
export * from './lib/openops-analytics';
3939
export * from './lib/openops-tables/applications-service';
4040
export * from './lib/openops-tables/auth-user';
41+
export * from './lib/openops-tables/context-helpers';
4142
export * from './lib/openops-tables/create-axios-headers';
4243
export * from './lib/openops-tables/fields';
4344
export * from './lib/openops-tables/filters';

0 commit comments

Comments
 (0)