Skip to content

Commit ba42672

Browse files
authored
Remove feature flag to use Database tokens (#1674)
Part of OPS-3006.
1 parent 75b0bce commit ba42672

8 files changed

Lines changed: 53 additions & 140 deletions

File tree

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
1-
import { AppSystemProp, cacheWrapper, system } from '@openops/server-shared';
21
import { AxiosHeaders } from 'axios';
32
import { IAxiosRetryConfig } from 'axios-retry';
43
import { makeOpenOpsTablesPost } from './requests-helpers';
5-
const tokenLifetimeMinutes = system.getNumber(
6-
AppSystemProp.TABLES_TOKEN_LIFETIME_MINUTES,
7-
);
8-
9-
const tokenLifetimeSeconds = tokenLifetimeMinutes
10-
? (tokenLifetimeMinutes - 10) * 60 // Subtract 10 minutes to ensure the cache expired before the token
11-
: undefined;
124

135
export interface AuthTokens {
146
token: string;
@@ -36,29 +28,3 @@ export async function authenticateUserInOpenOpsTables(
3628
axiosRetryConfig,
3729
);
3830
}
39-
40-
export async function authenticateDefaultUserInOpenOpsTables(
41-
axiosRetryConfig?: IAxiosRetryConfig,
42-
): Promise<AuthTokens> {
43-
const cacheKey = 'openops-tables-token';
44-
45-
let tokens = await cacheWrapper.getSerializedObject<AuthTokens>(cacheKey);
46-
47-
if (!tokens) {
48-
const email = system.getOrThrow(AppSystemProp.OPENOPS_ADMIN_EMAIL);
49-
const password = system.getOrThrow(AppSystemProp.OPENOPS_ADMIN_PASSWORD);
50-
51-
tokens = await authenticateUserInOpenOpsTables(
52-
email,
53-
password,
54-
axiosRetryConfig,
55-
);
56-
await cacheWrapper.setSerializedObject(
57-
cacheKey,
58-
tokens,
59-
tokenLifetimeSeconds,
60-
);
61-
}
62-
63-
return tokens;
64-
}
Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
import { ServerContext } from '@openops/blocks-framework';
2-
import { AppSystemProp, encryptUtils, system } from '@openops/server-shared';
3-
import { authenticateDefaultUserInOpenOpsTables } from './auth-user';
4-
5-
export function shouldUseDatabaseToken(): boolean {
6-
return system.getBoolean(AppSystemProp.ENABLE_TABLES_DATABASE_TOKEN) ?? false;
7-
}
2+
import { encryptUtils } from '@openops/server-shared';
83

94
export type TokenOrResolver = string | { getToken: () => string };
105
export type TablesServerContext = Pick<
@@ -15,15 +10,10 @@ export type TablesServerContext = Pick<
1510
export async function resolveTokenProvider(
1611
serverContext: TablesServerContext,
1712
): Promise<TokenOrResolver> {
18-
if (shouldUseDatabaseToken()) {
19-
return {
20-
getToken: () => {
21-
const { tablesDatabaseToken } = serverContext;
22-
return encryptUtils.decryptString(tablesDatabaseToken);
23-
},
24-
};
25-
}
26-
27-
const { token } = await authenticateDefaultUserInOpenOpsTables();
28-
return token;
13+
return {
14+
getToken: () => {
15+
const { tablesDatabaseToken } = serverContext;
16+
return encryptUtils.decryptString(tablesDatabaseToken);
17+
},
18+
};
2919
}

packages/openops/src/lib/openops-tables/create-axios-headers.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { AxiosHeaders } from 'axios';
2-
import { shouldUseDatabaseToken, TokenOrResolver } from './context-helpers';
2+
import { TokenOrResolver } from './context-helpers';
33

44
export enum AuthType {
55
JWT = 'JWT',
@@ -12,21 +12,13 @@ function getToken(tokenOrResolver: TokenOrResolver): string {
1212
: tokenOrResolver.getToken();
1313
}
1414

15-
function getAuthPrefix(
16-
useJwtOverride: boolean,
17-
shouldUseDatabaseTokenConfig: boolean,
18-
): AuthType {
19-
const useJwt = useJwtOverride || !shouldUseDatabaseTokenConfig;
20-
return useJwt ? AuthType.JWT : AuthType.Token;
21-
}
22-
2315
export const createAxiosHeaders = (
2416
tokenOrResolver: TokenOrResolver,
2517
): AxiosHeaders => {
26-
const useJwtOverride = typeof tokenOrResolver === 'string';
2718
const token = getToken(tokenOrResolver);
2819

29-
const prefix = getAuthPrefix(useJwtOverride, shouldUseDatabaseToken());
20+
const prefix =
21+
typeof tokenOrResolver === 'string' ? AuthType.JWT : AuthType.Token;
3022

3123
return new AxiosHeaders({
3224
'Content-Type': 'application/json',

packages/openops/test/openops-tables/openops-tables-common-properties.test.ts

Lines changed: 16 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -10,21 +10,6 @@ const getFieldsMock = jest.fn();
1010
jest.mock('../../src/lib/openops-tables/fields', () => {
1111
return { getFields: getFieldsMock };
1212
});
13-
const authenticateDefaultUserInOpenOpsTablesMock = jest.fn();
14-
jest.mock('../../src/lib/openops-tables/auth-user', () => {
15-
return {
16-
authenticateDefaultUserInOpenOpsTables:
17-
authenticateDefaultUserInOpenOpsTablesMock,
18-
};
19-
});
20-
21-
jest.mock('@openops/server-shared', () => ({
22-
...jest.requireActual('@openops/server-shared'),
23-
system: {
24-
...jest.requireActual('@openops/server-shared').system,
25-
getBoolean: jest.fn().mockReturnValue(false),
26-
},
27-
}));
2813

2914
import { EncryptedObject } from '@openops/shared';
3015
import { TablesServerContext } from '../../src/lib/openops-tables/context-helpers';
@@ -52,9 +37,6 @@ describe('table property', () => {
5237
});
5338

5439
test('should return dropdown with all tables', async () => {
55-
authenticateDefaultUserInOpenOpsTablesMock.mockResolvedValue({
56-
token: 'token',
57-
});
5840
getTableNamesMock.mockResolvedValue(['table1', 'table2']);
5941

6042
const result = await openopsTablesDropdownProperty().options(undefined, {
@@ -68,6 +50,7 @@ describe('table property', () => {
6850
{ label: 'table2', value: 'table2' },
6951
],
7052
});
53+
7154
expect(getTableNamesMock).toHaveBeenCalledTimes(1);
7255
});
7356

@@ -92,9 +75,6 @@ describe('getTableFields', () => {
9275
});
9376

9477
test('should return the options', async () => {
95-
authenticateDefaultUserInOpenOpsTablesMock.mockResolvedValue({
96-
token: 'token',
97-
});
9878
getFieldsMock.mockResolvedValue([
9979
{
10080
name: 'field1',
@@ -136,37 +116,33 @@ describe('getTableFields', () => {
136116
type: 'equal',
137117
},
138118
]);
139-
expect(authenticateDefaultUserInOpenOpsTablesMock).toHaveBeenCalledTimes(1);
140-
expect(getFieldsMock).toHaveBeenCalledTimes(1);
141-
expect(getFieldsMock).toHaveBeenCalledWith(1, 'token', false);
142-
});
143119

144-
test('should handle authentication failure', async () => {
145-
authenticateDefaultUserInOpenOpsTablesMock.mockRejectedValueOnce(
146-
new Error('Authentication failed'),
120+
expect(getFieldsMock).toHaveBeenCalledTimes(1);
121+
expect(getFieldsMock).toHaveBeenCalledWith(
122+
1,
123+
{
124+
getToken: expect.any(Function),
125+
},
126+
false,
147127
);
148-
getTableIdByTableNameMock.mockResolvedValue(1);
149-
150-
await expect(
151-
getTableFields('Opportunity', mockTablesServerContext),
152-
).rejects.toThrow('Authentication failed');
153-
expect(authenticateDefaultUserInOpenOpsTablesMock).toHaveBeenCalledTimes(1);
154-
expect(getFieldsMock).not.toHaveBeenCalled();
155128
});
156129

157130
test('should handle empty fields', async () => {
158-
authenticateDefaultUserInOpenOpsTablesMock.mockResolvedValue({
159-
token: 'token',
160-
});
161131
getFieldsMock.mockResolvedValue([]);
162132
getTableIdByTableNameMock.mockResolvedValue(1);
163133

164134
const result = await getTableFields('Opportunity', mockTablesServerContext);
165135

166136
expect(result).toMatchObject([]);
167-
expect(authenticateDefaultUserInOpenOpsTablesMock).toHaveBeenCalledTimes(1);
137+
168138
expect(getFieldsMock).toHaveBeenCalledTimes(1);
169-
expect(getFieldsMock).toHaveBeenCalledWith(1, 'token', false);
139+
expect(getFieldsMock).toHaveBeenCalledWith(
140+
1,
141+
{
142+
getToken: expect.any(Function),
143+
},
144+
false,
145+
);
170146
});
171147

172148
test('should return our supported properties for the field', async () => {
@@ -207,9 +183,6 @@ describe('getTableFields', () => {
207183
duration_format: 'format',
208184
};
209185

210-
authenticateDefaultUserInOpenOpsTablesMock.mockResolvedValue({
211-
token: 'token',
212-
});
213186
getFieldsMock.mockResolvedValue([
214187
numberField,
215188
singleSelectField,

packages/openops/test/openops-tables/tables.test.ts

Lines changed: 27 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
const authenticateDefaultUserInOpenOpsTablesMock = jest.fn();
21
const makeOpenOpsTablesGetMock = jest.fn();
32
const createAxiosHeadersMock = jest.fn();
43

@@ -10,19 +9,6 @@ jest.mock('../../src/lib/openops-tables/create-axios-headers', () => ({
109
createAxiosHeaders: createAxiosHeadersMock,
1110
}));
1211

13-
jest.mock('../../src/lib/openops-tables/auth-user', () => ({
14-
authenticateDefaultUserInOpenOpsTables:
15-
authenticateDefaultUserInOpenOpsTablesMock,
16-
}));
17-
18-
jest.mock('@openops/server-shared', () => ({
19-
...jest.requireActual('@openops/server-shared'),
20-
system: {
21-
...jest.requireActual('@openops/server-shared').system,
22-
getBoolean: jest.fn().mockReturnValue(false),
23-
},
24-
}));
25-
2612
import { EncryptedObject } from '@openops/shared';
2713
import { TablesServerContext } from '../../src/lib/openops-tables/context-helpers';
2814
import {
@@ -42,9 +28,6 @@ const mockTablesServerContext: TablesServerContext = {
4228
describe('get table names', () => {
4329
beforeEach(() => {
4430
jest.clearAllMocks();
45-
authenticateDefaultUserInOpenOpsTablesMock.mockResolvedValue({
46-
token: 'token',
47-
});
4831
});
4932

5033
test('should return the list of available table names', async () => {
@@ -64,7 +47,9 @@ describe('get table names', () => {
6447
'some header',
6548
);
6649
expect(createAxiosHeadersMock).toBeCalledTimes(1);
67-
expect(createAxiosHeadersMock).toHaveBeenCalledWith('token');
50+
expect(createAxiosHeadersMock).toHaveBeenCalledWith({
51+
getToken: expect.any(Function),
52+
});
6853
});
6954

7055
test('should return the list of available table names in a flatten list', async () => {
@@ -86,7 +71,9 @@ describe('get table names', () => {
8671
'some header',
8772
);
8873
expect(createAxiosHeadersMock).toBeCalledTimes(1);
89-
expect(createAxiosHeadersMock).toHaveBeenCalledWith('token');
74+
expect(createAxiosHeadersMock).toHaveBeenCalledWith({
75+
getToken: expect.any(Function),
76+
});
9077
});
9178

9279
test('should return the list of distinct table names', async () => {
@@ -109,16 +96,15 @@ describe('get table names', () => {
10996
'some header',
11097
);
11198
expect(createAxiosHeadersMock).toBeCalledTimes(1);
112-
expect(createAxiosHeadersMock).toHaveBeenCalledWith('token');
99+
expect(createAxiosHeadersMock).toHaveBeenCalledWith({
100+
getToken: expect.any(Function),
101+
});
113102
});
114103
});
115104

116105
describe('get table id by table name', () => {
117106
beforeEach(() => {
118107
jest.clearAllMocks();
119-
authenticateDefaultUserInOpenOpsTablesMock.mockResolvedValue({
120-
token: 'token',
121-
});
122108
});
123109

124110
test('should return the right table id', async () => {
@@ -140,7 +126,9 @@ describe('get table id by table name', () => {
140126
'some header',
141127
);
142128
expect(createAxiosHeadersMock).toBeCalledTimes(1);
143-
expect(createAxiosHeadersMock).toHaveBeenCalledWith('token');
129+
expect(createAxiosHeadersMock).toHaveBeenCalledWith({
130+
getToken: expect.any(Function),
131+
});
144132
});
145133

146134
test('should throw an error if the table name is not found', async () => {
@@ -157,7 +145,9 @@ describe('get table id by table name', () => {
157145
'some header',
158146
);
159147
expect(createAxiosHeadersMock).toBeCalledTimes(1);
160-
expect(createAxiosHeadersMock).toHaveBeenCalledWith('token');
148+
expect(createAxiosHeadersMock).toHaveBeenCalledWith({
149+
getToken: expect.any(Function),
150+
});
161151
});
162152

163153
test('should return the lowest table id when multiple tables have the same name', async () => {
@@ -180,16 +170,15 @@ describe('get table id by table name', () => {
180170
'some header',
181171
);
182172
expect(createAxiosHeadersMock).toBeCalledTimes(1);
183-
expect(createAxiosHeadersMock).toHaveBeenCalledWith('token');
173+
expect(createAxiosHeadersMock).toHaveBeenCalledWith({
174+
getToken: expect.any(Function),
175+
});
184176
});
185177
});
186178

187179
describe('get table by table name', () => {
188180
beforeEach(() => {
189181
jest.clearAllMocks();
190-
authenticateDefaultUserInOpenOpsTablesMock.mockResolvedValue({
191-
token: 'token',
192-
});
193182
});
194183

195184
test('should return the right table', async () => {
@@ -208,7 +197,9 @@ describe('get table by table name', () => {
208197
'some header',
209198
);
210199
expect(createAxiosHeadersMock).toBeCalledTimes(1);
211-
expect(createAxiosHeadersMock).toHaveBeenCalledWith('token');
200+
expect(createAxiosHeadersMock).toHaveBeenCalledWith({
201+
getToken: expect.any(Function),
202+
});
212203
});
213204

214205
test('should return undefined if table was not found', async () => {
@@ -224,7 +215,9 @@ describe('get table by table name', () => {
224215
'some header',
225216
);
226217
expect(createAxiosHeadersMock).toBeCalledTimes(1);
227-
expect(createAxiosHeadersMock).toHaveBeenCalledWith('token');
218+
expect(createAxiosHeadersMock).toHaveBeenCalledWith({
219+
getToken: expect.any(Function),
220+
});
228221
});
229222

230223
test('should return the lowest table when multiple tables have the same name', async () => {
@@ -244,6 +237,8 @@ describe('get table by table name', () => {
244237
'some header',
245238
);
246239
expect(createAxiosHeadersMock).toBeCalledTimes(1);
247-
expect(createAxiosHeadersMock).toHaveBeenCalledWith('token');
240+
expect(createAxiosHeadersMock).toHaveBeenCalledWith({
241+
getToken: expect.any(Function),
242+
});
248243
});
249244
});

packages/server/api/test/unit/mcp/llm-query-router.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ jest.mock('@openops/server-shared', () => ({
3939
},
4040
AppSystemProp: {
4141
DB_TYPE: 'DB_TYPE',
42-
ENABLE_TABLES_DATABASE_TOKEN: 'ENABLE_TABLES_DATABASE_TOKEN',
4342
},
4443
}));
4544

packages/server/shared/src/lib/system/system-prop.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ export enum AppSystemProp {
110110

111111
MAX_LLM_CALLS_WITHOUT_INTERACTION = 'MAX_LLM_CALLS_WITHOUT_INTERACTION',
112112
LLM_CHAT_EXPIRE_TIME_SECONDS = 'LLM_CHAT_EXPIRE_TIME_SECONDS',
113-
ENABLE_TABLES_DATABASE_TOKEN = 'ENABLE_TABLES_DATABASE_TOKEN',
114113
}
115114

116115
export enum SharedSystemProp {

packages/server/shared/src/lib/system/system.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ const systemPropDefaultValues: Partial<Record<SystemProp, string>> = {
9898
[AppSystemProp.LLM_CHAT_EXPIRE_TIME_SECONDS]: '86400', // 24 hours
9999
[AppSystemProp.TELEMETRY_MODE]: 'COLLECTOR',
100100
[AppSystemProp.TELEMETRY_COLLECTOR_URL]: 'https://telemetry.openops.com/save',
101-
[AppSystemProp.ENABLE_TABLES_DATABASE_TOKEN]: 'false',
102101
[SharedSystemProp.ENABLE_HOST_VALIDATION]: 'true',
103102
};
104103

0 commit comments

Comments
 (0)