mirror of
https://github.com/lingble/twenty.git
synced 2025-10-29 20:02:29 +00:00
@@ -1,4 +1,4 @@
|
||||
import { Injectable, UnauthorizedException } from '@nestjs/common';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { JwtService, JwtSignOptions, JwtVerifyOptions } from '@nestjs/jwt';
|
||||
|
||||
import { createHash } from 'crypto';
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
AuthExceptionCode,
|
||||
} from 'src/engine/core-modules/auth/auth.exception';
|
||||
import { EnvironmentService } from 'src/engine/core-modules/environment/environment.service';
|
||||
import { isDefined } from 'src/utils/is-defined';
|
||||
|
||||
export type WorkspaceTokenType =
|
||||
| 'ACCESS'
|
||||
@@ -53,9 +54,16 @@ export class JwtWrapperService {
|
||||
json: true,
|
||||
});
|
||||
|
||||
if (!isDefined(payload)) {
|
||||
throw new AuthException('No payload', AuthExceptionCode.UNAUTHENTICATED);
|
||||
}
|
||||
|
||||
// TODO: check if this is really needed
|
||||
if (type !== 'FILE' && !payload.sub) {
|
||||
throw new UnauthorizedException('No payload sub');
|
||||
throw new AuthException(
|
||||
'No payload sub',
|
||||
AuthExceptionCode.UNAUTHENTICATED,
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
@@ -64,15 +64,36 @@ const computeQueryParameters = (
|
||||
}
|
||||
};
|
||||
|
||||
const getOperationFromDatabaseEventAction = (
|
||||
z: ZObject,
|
||||
databaseEventAction: DatabaseEventAction,
|
||||
): 'create' | 'update' | 'delete' => {
|
||||
switch (databaseEventAction) {
|
||||
case DatabaseEventAction.CREATED:
|
||||
return 'create';
|
||||
case DatabaseEventAction.UPDATED:
|
||||
return 'update';
|
||||
case DatabaseEventAction.DELETED:
|
||||
return 'delete';
|
||||
default:
|
||||
throw new z.errors.Error(
|
||||
`Unknown databaseEventAction: ${databaseEventAction}`,
|
||||
'Error',
|
||||
404,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const perform = async (z: ZObject, bundle: Bundle) => {
|
||||
const data = bundle.inputData;
|
||||
const operation = data.crudZapierOperation;
|
||||
const queryOperation = getOperationFromDatabaseEventAction(z, operation);
|
||||
const nameSingular = data.nameSingular;
|
||||
delete data.nameSingular;
|
||||
delete data.crudZapierOperation;
|
||||
const query = `
|
||||
mutation ${operation}${capitalize(nameSingular)} {
|
||||
${operation}${capitalize(nameSingular)}(
|
||||
mutation ${queryOperation}${capitalize(nameSingular)} {
|
||||
${queryOperation}${capitalize(nameSingular)}(
|
||||
${computeQueryParameters(operation, data)}
|
||||
)
|
||||
{id}
|
||||
|
||||
@@ -15,6 +15,6 @@ describe('triggers.list_record_ids', () => {
|
||||
);
|
||||
expect(result).toBeDefined();
|
||||
expect(result.length).toBeGreaterThan(1);
|
||||
expect(result[0].id).toBeDefined();
|
||||
expect(result[0].record.id).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -24,18 +24,18 @@ describe('triggers.trigger_record.created', () => {
|
||||
requestDb(
|
||||
z,
|
||||
bundle,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operations}}}}`,
|
||||
),
|
||||
bundle,
|
||||
);
|
||||
expect(checkDbResult.data.webhooks.edges[0].node.operation).toEqual(
|
||||
'create.company',
|
||||
expect(checkDbResult.data.webhooks.edges[0].node.operations[0]).toEqual(
|
||||
'company.created',
|
||||
);
|
||||
});
|
||||
test('should succeed to unsubscribe', async () => {
|
||||
const bundle = getBundle({});
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = 'create';
|
||||
bundle.inputData.operation = DatabaseEventAction.CREATED;
|
||||
bundle.targetUrl = 'https://test.com';
|
||||
const result = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||
@@ -54,7 +54,7 @@ describe('triggers.trigger_record.created', () => {
|
||||
requestDb(
|
||||
z,
|
||||
bundle,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operations}}}}`,
|
||||
),
|
||||
bundle,
|
||||
);
|
||||
@@ -83,19 +83,19 @@ describe('triggers.trigger_record.created', () => {
|
||||
);
|
||||
expect(results.length).toEqual(1);
|
||||
const company = results[0];
|
||||
expect(company.id).toEqual('d6ccb1d1-a90b-4822-a992-a0dd946592c9');
|
||||
expect(company.record.id).toEqual('d6ccb1d1-a90b-4822-a992-a0dd946592c9');
|
||||
});
|
||||
it('should load companies from list', async () => {
|
||||
const bundle = getBundle({});
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = 'create';
|
||||
bundle.inputData.operation = DatabaseEventAction.CREATED;
|
||||
const results = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performList,
|
||||
bundle,
|
||||
);
|
||||
expect(results.length).toBeGreaterThan(1);
|
||||
const firstCompany = results[0];
|
||||
expect(firstCompany).toBeDefined();
|
||||
expect(firstCompany.record).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -103,7 +103,7 @@ describe('triggers.trigger_record.update', () => {
|
||||
test('should succeed to subscribe', async () => {
|
||||
const bundle = getBundle({});
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = 'update';
|
||||
bundle.inputData.operation = DatabaseEventAction.UPDATED;
|
||||
bundle.targetUrl = 'https://test.com';
|
||||
const result = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||
@@ -116,18 +116,18 @@ describe('triggers.trigger_record.update', () => {
|
||||
requestDb(
|
||||
z,
|
||||
bundle,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operations}}}}`,
|
||||
),
|
||||
bundle,
|
||||
);
|
||||
expect(checkDbResult.data.webhooks.edges[0].node.operation).toEqual(
|
||||
'update.company',
|
||||
expect(checkDbResult.data.webhooks.edges[0].node.operations[0]).toEqual(
|
||||
'company.updated',
|
||||
);
|
||||
});
|
||||
test('should succeed to unsubscribe', async () => {
|
||||
const bundle = getBundle({});
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = 'update';
|
||||
bundle.inputData.operation = DatabaseEventAction.UPDATED;
|
||||
bundle.targetUrl = 'https://test.com';
|
||||
const result = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||
@@ -146,7 +146,7 @@ describe('triggers.trigger_record.update', () => {
|
||||
requestDb(
|
||||
z,
|
||||
bundle,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operations}}}}`,
|
||||
),
|
||||
bundle,
|
||||
);
|
||||
@@ -155,14 +155,15 @@ describe('triggers.trigger_record.update', () => {
|
||||
it('should load companies from list', async () => {
|
||||
const bundle = getBundle({});
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = 'update';
|
||||
bundle.inputData.operation = DatabaseEventAction.UPDATED;
|
||||
const results = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performList,
|
||||
bundle,
|
||||
);
|
||||
expect(results.length).toBeGreaterThan(1);
|
||||
const firstCompany = results[0];
|
||||
expect(firstCompany).toBeDefined();
|
||||
expect(firstCompany.record).toBeDefined();
|
||||
expect(firstCompany.updatedFields).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -170,7 +171,7 @@ describe('triggers.trigger_record.delete', () => {
|
||||
test('should succeed to subscribe', async () => {
|
||||
const bundle = getBundle({});
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = 'delete';
|
||||
bundle.inputData.operation = DatabaseEventAction.DELETED;
|
||||
bundle.targetUrl = 'https://test.com';
|
||||
const result = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||
@@ -183,18 +184,18 @@ describe('triggers.trigger_record.delete', () => {
|
||||
requestDb(
|
||||
z,
|
||||
bundle,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operations}}}}`,
|
||||
),
|
||||
bundle,
|
||||
);
|
||||
expect(checkDbResult.data.webhooks.edges[0].node.operation).toEqual(
|
||||
'delete.company',
|
||||
expect(checkDbResult.data.webhooks.edges[0].node.operations[0]).toEqual(
|
||||
'company.deleted',
|
||||
);
|
||||
});
|
||||
test('should succeed to unsubscribe', async () => {
|
||||
const bundle = getBundle({});
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = 'delete';
|
||||
bundle.inputData.operation = DatabaseEventAction.DELETED;
|
||||
bundle.targetUrl = 'https://test.com';
|
||||
const result = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performSubscribe,
|
||||
@@ -213,7 +214,7 @@ describe('triggers.trigger_record.delete', () => {
|
||||
requestDb(
|
||||
z,
|
||||
bundle,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operation}}}}`,
|
||||
`query webhook {webhooks(filter: {id: {eq: "${result.id}"}}){edges {node {id operations}}}}`,
|
||||
),
|
||||
bundle,
|
||||
);
|
||||
@@ -222,7 +223,7 @@ describe('triggers.trigger_record.delete', () => {
|
||||
it('should load companies from list', async () => {
|
||||
const bundle = getBundle({});
|
||||
bundle.inputData.nameSingular = 'company';
|
||||
bundle.inputData.operation = 'delete';
|
||||
bundle.inputData.operation = DatabaseEventAction.DELETED;
|
||||
const results = await appTester(
|
||||
App.triggers[triggerRecordKey].operation.performList,
|
||||
bundle,
|
||||
@@ -230,7 +231,7 @@ describe('triggers.trigger_record.delete', () => {
|
||||
expect(results.length).toBeGreaterThan(1);
|
||||
const firstCompany = results[0];
|
||||
expect(firstCompany).toBeDefined();
|
||||
expect(firstCompany.id).toBeDefined();
|
||||
expect(firstCompany.record.id).toBeDefined();
|
||||
expect(Object.keys(firstCompany).length).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,14 +1,4 @@
|
||||
import { Bundle, ZObject } from 'zapier-platform-core';
|
||||
|
||||
import { ObjectData } from '../utils/data.types';
|
||||
import { listSample } from '../utils/triggers/triggers.utils';
|
||||
|
||||
const listRecordIdsRequest = async (
|
||||
z: ZObject,
|
||||
bundle: Bundle,
|
||||
): Promise<ObjectData[]> => {
|
||||
return listSample(z, bundle, true);
|
||||
};
|
||||
import { performList } from '../utils/triggers/triggers.utils';
|
||||
|
||||
export const listRecordIdsKey = 'list_record_ids';
|
||||
|
||||
@@ -21,6 +11,6 @@ export default {
|
||||
key: listRecordIdsKey,
|
||||
noun: 'Object',
|
||||
operation: {
|
||||
perform: listRecordIdsRequest,
|
||||
perform: performList,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
export type InputData = { [x: string]: any };
|
||||
|
||||
export type ObjectData = { id: string } | { [x: string]: any };
|
||||
|
||||
export type NodeField = {
|
||||
type: FieldMetadataType;
|
||||
name: string;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Bundle, ZObject } from 'zapier-platform-core';
|
||||
|
||||
import { ObjectData } from '../../utils/data.types';
|
||||
import handleQueryParams from '../../utils/handleQueryParams';
|
||||
import requestDb, {
|
||||
requestDbViaRestApi,
|
||||
@@ -11,7 +10,6 @@ export enum DatabaseEventAction {
|
||||
CREATED = 'created',
|
||||
UPDATED = 'updated',
|
||||
DELETED = 'deleted',
|
||||
DESTROYED = 'destroyed',
|
||||
}
|
||||
|
||||
export const performSubscribe = async (z: ZObject, bundle: Bundle) => {
|
||||
@@ -81,7 +79,7 @@ const getNamePluralFromNameSingular = async (
|
||||
export const performList = async (
|
||||
z: ZObject,
|
||||
bundle: Bundle,
|
||||
): Promise<ObjectData[]> => {
|
||||
): Promise<{ record: Record<string, any>; updatedFields?: string[] }[]> => {
|
||||
const nameSingular = bundle.inputData.nameSingular;
|
||||
const namePlural = await getNamePluralFromNameSingular(
|
||||
z,
|
||||
@@ -92,9 +90,9 @@ export const performList = async (
|
||||
return results.map((result) => ({
|
||||
record: result,
|
||||
...(bundle.inputData.operation === DatabaseEventAction.UPDATED && {
|
||||
updatedFields: Object.keys(result).filter((key) => key !== 'id')?.[0] || [
|
||||
'updatedField',
|
||||
],
|
||||
updatedFields: [
|
||||
Object.keys(result).filter((key) => key !== 'id')?.[0],
|
||||
] || ['updatedField'],
|
||||
}),
|
||||
}));
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user