mirror of
https://github.com/dadosfera/maestro.git
synced 2026-09-08 06:14:48 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84218c128a | ||
|
|
d642a8d823 |
@@ -65,7 +65,7 @@ describe('ConnectionTestService catalog cache', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('maps cached columns to the existing table metadata contract', async () => {
|
||||
it('maps cached columns and derives references from the engine allowlist', async () => {
|
||||
connectionsApiService.proxy.mockResolvedValue({
|
||||
columns: [
|
||||
{
|
||||
@@ -73,6 +73,16 @@ describe('ConnectionTestService catalog cache', () => {
|
||||
data_type: 'bigint',
|
||||
is_primary_key: true,
|
||||
},
|
||||
{
|
||||
column_name: 'name',
|
||||
data_type: 'varchar',
|
||||
is_primary_key: false,
|
||||
},
|
||||
],
|
||||
});
|
||||
platformApiService.proxy.mockResolvedValue({
|
||||
allowed_datatypes: [
|
||||
{ engine: 'postgresql', allowed_datatypes: ['bigint', 'timestamp'] },
|
||||
],
|
||||
});
|
||||
|
||||
@@ -92,13 +102,10 @@ describe('ConnectionTestService catalog cache', () => {
|
||||
{
|
||||
table_name: 'customers',
|
||||
columns: [
|
||||
{
|
||||
name: 'id',
|
||||
type: 'bigint',
|
||||
is_primary_key: true,
|
||||
},
|
||||
{ name: 'id', type: 'bigint', is_primary_key: true },
|
||||
{ name: 'name', type: 'varchar', is_primary_key: false },
|
||||
],
|
||||
references: [],
|
||||
references: [{ name: 'id', type: 'bigint', is_primary_key: true }],
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -107,6 +114,39 @@ describe('ConnectionTestService catalog cache', () => {
|
||||
'/connection_catalog/config-id/schemas/public/tables/customers/columns',
|
||||
user,
|
||||
);
|
||||
expect(platformApiService.proxy).toHaveBeenCalledWith(
|
||||
'GET',
|
||||
'/jobs/jdbc/configs/allowed_datatypes',
|
||||
user,
|
||||
);
|
||||
});
|
||||
|
||||
it('returns empty references when the allowlist call fails', async () => {
|
||||
connectionsApiService.proxy.mockResolvedValue({
|
||||
columns: [{ column_name: 'id', data_type: 'bigint', is_primary_key: true }],
|
||||
});
|
||||
platformApiService.proxy.mockRejectedValue(new Error('platform down'));
|
||||
|
||||
await expect(
|
||||
service.getTableMetadata(
|
||||
{
|
||||
connection_id: 'config-id',
|
||||
plugin: 'postgresql',
|
||||
schema: 'public',
|
||||
table_list: ['customers'],
|
||||
},
|
||||
user,
|
||||
),
|
||||
).resolves.toEqual({
|
||||
operation_result: true,
|
||||
tables_metadata: [
|
||||
{
|
||||
table_name: 'customers',
|
||||
columns: [{ name: 'id', type: 'bigint', is_primary_key: true }],
|
||||
references: [],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it('submits a catalog refresh without holding the request open', async () => {
|
||||
|
||||
@@ -187,6 +187,20 @@ export class ConnectionTestService {
|
||||
body: GetTableMetadataReq,
|
||||
user: RequestUser,
|
||||
): Promise<GetTableMetadataRes> {
|
||||
// Columns eligible as the incremental reference field are the ones whose
|
||||
// data type is allowed for this engine (e.g. int/date/timestamp). The
|
||||
// allowlist is owned by the platform API, keyed by engine === plugin.
|
||||
const allowedByEngine = await this.platformApiService
|
||||
.proxy('GET', '/jobs/jdbc/configs/allowed_datatypes', user)
|
||||
.catch(() => null);
|
||||
const allowedDataTypes: string[] =
|
||||
allowedByEngine?.allowed_datatypes?.find(
|
||||
(datatypes) => datatypes.engine === body.plugin,
|
||||
)?.allowed_datatypes ?? [];
|
||||
const allowedSet = new Set(
|
||||
allowedDataTypes.map((type) => type.toLowerCase()),
|
||||
);
|
||||
|
||||
const tables_metadata = await Promise.all(
|
||||
body.table_list.map(async (table_name) => {
|
||||
const result = await this.connectionsApiService.proxy(
|
||||
@@ -196,14 +210,18 @@ export class ConnectionTestService {
|
||||
`/tables/${encodeURIComponent(table_name)}/columns`,
|
||||
user,
|
||||
);
|
||||
const columns = result.columns.map((column) => ({
|
||||
name: column.column_name,
|
||||
type: column.data_type,
|
||||
is_primary_key: column.is_primary_key,
|
||||
}));
|
||||
const references = columns.filter((column) =>
|
||||
allowedSet.has(String(column.type).toLowerCase()),
|
||||
);
|
||||
return {
|
||||
table_name,
|
||||
columns: result.columns.map((column) => ({
|
||||
name: column.column_name,
|
||||
type: column.data_type,
|
||||
is_primary_key: column.is_primary_key,
|
||||
})),
|
||||
references: [],
|
||||
columns,
|
||||
references,
|
||||
};
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
let mockStrategyOptions: { scope: string };
|
||||
|
||||
jest.mock('passport-hubspot-oauth2', () => ({
|
||||
Strategy: class {
|
||||
constructor(options: { scope: string }) {
|
||||
mockStrategyOptions = options;
|
||||
}
|
||||
|
||||
authenticate() {}
|
||||
},
|
||||
}));
|
||||
|
||||
jest.mock('@nestjs/passport', () => ({
|
||||
PassportStrategy: (Strategy) => Strategy,
|
||||
}));
|
||||
|
||||
import { HubspotStrategy } from './hubspot-strategy';
|
||||
import type { OauthSecrets } from 'src/utils/OauthSecrets';
|
||||
import type { OauthService } from '../oauth.service';
|
||||
|
||||
describe('HubspotStrategy', () => {
|
||||
it('requests the content scope without requesting Marketing write scopes', () => {
|
||||
const oauthSecrets = {
|
||||
hubspot: {
|
||||
client_id: '',
|
||||
client_secret: '',
|
||||
redirect_uri: '',
|
||||
},
|
||||
} as OauthSecrets;
|
||||
|
||||
new HubspotStrategy(oauthSecrets, {} as OauthService);
|
||||
|
||||
const scopes = mockStrategyOptions.scope.split(' ');
|
||||
|
||||
expect(scopes).toEqual([
|
||||
'tickets',
|
||||
'automation',
|
||||
'business-intelligence',
|
||||
'oauth',
|
||||
'forms',
|
||||
'content',
|
||||
'integration-sync',
|
||||
'sales-email-read',
|
||||
'crm.lists.read',
|
||||
'crm.objects.contacts.read',
|
||||
'crm.schemas.contacts.read',
|
||||
'crm.objects.companies.read',
|
||||
'crm.objects.deals.read',
|
||||
'crm.schemas.companies.read',
|
||||
'crm.schemas.deals.read',
|
||||
'crm.objects.owners.read',
|
||||
'crm.objects.quotes.read',
|
||||
'crm.schemas.quotes.read',
|
||||
'crm.objects.line_items.read',
|
||||
'crm.schemas.line_items.read',
|
||||
]);
|
||||
expect(scopes).not.toContain('marketing.email.write');
|
||||
});
|
||||
});
|
||||
@@ -17,7 +17,7 @@ export class HubspotStrategy extends PassportStrategy(Strategy) {
|
||||
clientSecret: oauthSecrets.hubspot.client_secret,
|
||||
callbackURL: oauthSecrets.hubspot.redirect_uri,
|
||||
scope:
|
||||
'tickets automation business-intelligence oauth forms content integration-sync sales-email-read crm.lists.read crm.objects.contacts.read crm.schemas.contacts.read crm.objects.companies.read crm.objects.deals.read crm.schemas.companies.read crm.schemas.deals.read crm.objects.owners.read crm.objects.quotes.read crm.schemas.quotes.read crm.objects.line_items.read crm.schemas.line_items.read',
|
||||
'tickets automation business-intelligence oauth forms integration-sync sales-email-read crm.lists.read crm.objects.contacts.read crm.schemas.contacts.read crm.objects.companies.read crm.objects.deals.read crm.schemas.companies.read crm.schemas.deals.read crm.objects.owners.read crm.objects.quotes.read crm.schemas.quotes.read crm.objects.line_items.read crm.schemas.line_items.read',
|
||||
passReqToCallback: true,
|
||||
},
|
||||
(accessToken, refreshToken, tokenInfo, profile, done) => {
|
||||
|
||||
Reference in New Issue
Block a user