feat: Convert helpers to use JS files
This commit is contained in:
@@ -1,6 +1,4 @@
|
||||
import { IApp } from '@automatisch/types';
|
||||
|
||||
function addAuthenticationSteps(app: IApp): IApp {
|
||||
function addAuthenticationSteps(app) {
|
||||
if (app.auth.generateAuthUrl) {
|
||||
app.auth.authenticationSteps = authenticationStepsWithAuthUrl;
|
||||
app.auth.sharedAuthenticationSteps = sharedAuthenticationStepsWithAuthUrl;
|
||||
@@ -13,7 +11,7 @@ function addAuthenticationSteps(app: IApp): IApp {
|
||||
|
||||
const authenticationStepsWithoutAuthUrl = [
|
||||
{
|
||||
type: 'mutation' as const,
|
||||
type: 'mutation',
|
||||
name: 'createConnection',
|
||||
arguments: [
|
||||
{
|
||||
@@ -27,7 +25,7 @@ const authenticationStepsWithoutAuthUrl = [
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'mutation' as const,
|
||||
type: 'mutation',
|
||||
name: 'verifyConnection',
|
||||
arguments: [
|
||||
{
|
||||
@@ -40,7 +38,7 @@ const authenticationStepsWithoutAuthUrl = [
|
||||
|
||||
const authenticationStepsWithAuthUrl = [
|
||||
{
|
||||
type: 'mutation' as const,
|
||||
type: 'mutation',
|
||||
name: 'createConnection',
|
||||
arguments: [
|
||||
{
|
||||
@@ -54,7 +52,7 @@ const authenticationStepsWithAuthUrl = [
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'mutation' as const,
|
||||
type: 'mutation',
|
||||
name: 'generateAuthUrl',
|
||||
arguments: [
|
||||
{
|
||||
@@ -64,7 +62,7 @@ const authenticationStepsWithAuthUrl = [
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'openWithPopup' as const,
|
||||
type: 'openWithPopup',
|
||||
name: 'openAuthPopup',
|
||||
arguments: [
|
||||
{
|
||||
@@ -74,7 +72,7 @@ const authenticationStepsWithAuthUrl = [
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'mutation' as const,
|
||||
type: 'mutation',
|
||||
name: 'updateConnection',
|
||||
arguments: [
|
||||
{
|
||||
@@ -88,7 +86,7 @@ const authenticationStepsWithAuthUrl = [
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'mutation' as const,
|
||||
type: 'mutation',
|
||||
name: 'verifyConnection',
|
||||
arguments: [
|
||||
{
|
||||
@@ -101,7 +99,7 @@ const authenticationStepsWithAuthUrl = [
|
||||
|
||||
const sharedAuthenticationStepsWithAuthUrl = [
|
||||
{
|
||||
type: 'mutation' as const,
|
||||
type: 'mutation',
|
||||
name: 'createConnection',
|
||||
arguments: [
|
||||
{
|
||||
@@ -115,7 +113,7 @@ const sharedAuthenticationStepsWithAuthUrl = [
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'mutation' as const,
|
||||
type: 'mutation',
|
||||
name: 'generateAuthUrl',
|
||||
arguments: [
|
||||
{
|
||||
@@ -125,7 +123,7 @@ const sharedAuthenticationStepsWithAuthUrl = [
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'openWithPopup' as const,
|
||||
type: 'openWithPopup',
|
||||
name: 'openAuthPopup',
|
||||
arguments: [
|
||||
{
|
||||
@@ -135,7 +133,7 @@ const sharedAuthenticationStepsWithAuthUrl = [
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'mutation' as const,
|
||||
type: 'mutation',
|
||||
name: 'updateConnection',
|
||||
arguments: [
|
||||
{
|
||||
@@ -149,7 +147,7 @@ const sharedAuthenticationStepsWithAuthUrl = [
|
||||
],
|
||||
},
|
||||
{
|
||||
type: 'mutation' as const,
|
||||
type: 'mutation',
|
||||
name: 'verifyConnection',
|
||||
arguments: [
|
||||
{
|
@@ -1,8 +1,3 @@
|
||||
import {
|
||||
IApp,
|
||||
IAuthenticationStep,
|
||||
IAuthenticationStepField,
|
||||
} from '@automatisch/types';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
|
||||
const connectionIdArgument = {
|
||||
@@ -11,20 +6,20 @@ const connectionIdArgument = {
|
||||
};
|
||||
|
||||
const resetConnectionStep = {
|
||||
type: 'mutation' as const,
|
||||
type: 'mutation',
|
||||
name: 'resetConnection',
|
||||
arguments: [connectionIdArgument],
|
||||
};
|
||||
|
||||
function replaceCreateConnection(string: string) {
|
||||
function replaceCreateConnection(string) {
|
||||
return string.replace('{createConnection.id}', '{connection.id}');
|
||||
}
|
||||
|
||||
function removeAppKeyArgument(args: IAuthenticationStepField[]) {
|
||||
function removeAppKeyArgument(args) {
|
||||
return args.filter((argument) => argument.name !== 'key');
|
||||
}
|
||||
|
||||
function addConnectionId(step: IAuthenticationStep) {
|
||||
function addConnectionId(step) {
|
||||
step.arguments = step.arguments.map((argument) => {
|
||||
if (typeof argument.value === 'string') {
|
||||
argument.value = replaceCreateConnection(argument.value);
|
||||
@@ -45,7 +40,7 @@ function addConnectionId(step: IAuthenticationStep) {
|
||||
return step;
|
||||
}
|
||||
|
||||
function replaceCreateConnectionsWithUpdate(steps: IAuthenticationStep[]) {
|
||||
function replaceCreateConnectionsWithUpdate(steps) {
|
||||
const updatedSteps = cloneDeep(steps);
|
||||
return updatedSteps.map((step) => {
|
||||
const updatedStep = addConnectionId(step);
|
||||
@@ -62,7 +57,7 @@ function replaceCreateConnectionsWithUpdate(steps: IAuthenticationStep[]) {
|
||||
});
|
||||
}
|
||||
|
||||
function addReconnectionSteps(app: IApp): IApp {
|
||||
function addReconnectionSteps(app) {
|
||||
const hasReconnectionSteps = app.auth.reconnectionSteps;
|
||||
|
||||
if (hasReconnectionSteps) return app;
|
||||
@@ -80,7 +75,10 @@ function addReconnectionSteps(app: IApp): IApp {
|
||||
app.auth.sharedAuthenticationSteps
|
||||
);
|
||||
|
||||
app.auth.sharedReconnectionSteps = [resetConnectionStep, ...updatedStepsWithEmbeddedDefaults];
|
||||
app.auth.sharedReconnectionSteps = [
|
||||
resetConnectionStep,
|
||||
...updatedStepsWithEmbeddedDefaults,
|
||||
];
|
||||
}
|
||||
|
||||
return app;
|
@@ -1,6 +1,6 @@
|
||||
import express, { Application } from 'express';
|
||||
import express from 'express';
|
||||
|
||||
const appAssetsHandler = async (app: Application) => {
|
||||
const appAssetsHandler = async (app) => {
|
||||
app.use('/apps/:appKey/assets/favicon.svg', (req, res, next) => {
|
||||
const { appKey } = req.params;
|
||||
const svgPath = `${__dirname}/../apps/${appKey}/assets/favicon.svg`;
|
@@ -1,7 +1,6 @@
|
||||
import type { IApp } from '@automatisch/types';
|
||||
import appConfig from '../config/app';
|
||||
|
||||
const appInfoConverter = (rawAppData: IApp) => {
|
||||
const appInfoConverter = (rawAppData) => {
|
||||
rawAppData.iconUrl = rawAppData.iconUrl.replace(
|
||||
'{BASE_URL}',
|
||||
appConfig.baseUrl
|
@@ -9,9 +9,8 @@ const isAuthenticated = rule()(async (_parent, _args, req) => {
|
||||
if (token == null) return false;
|
||||
|
||||
try {
|
||||
const { userId } = jwt.verify(token, appConfig.appSecretKey) as {
|
||||
userId: string;
|
||||
};
|
||||
const { userId } = jwt.verify(token, appConfig.appSecretKey);
|
||||
|
||||
req.currentUser = await User.query()
|
||||
.findById(userId)
|
||||
.leftJoinRelated({
|
@@ -1,8 +1,8 @@
|
||||
import axios, { AxiosRequestConfig } from 'axios';
|
||||
import axios from 'axios';
|
||||
import { HttpsProxyAgent } from 'https-proxy-agent';
|
||||
import { HttpProxyAgent } from 'http-proxy-agent';
|
||||
|
||||
const config: AxiosRequestConfig = {};
|
||||
const config = {};
|
||||
const httpProxyUrl = process.env.http_proxy;
|
||||
const httpsProxyUrl = process.env.https_proxy;
|
||||
const supportsProxy = httpProxyUrl || httpsProxyUrl;
|
@@ -9,7 +9,7 @@ const PADDLE_VENDOR_URL = appConfig.isDev
|
||||
|
||||
const axiosInstance = axios.create({ baseURL: PADDLE_VENDOR_URL });
|
||||
|
||||
const getSubscription = async (subscriptionId: number) => {
|
||||
const getSubscription = async (subscriptionId) => {
|
||||
const data = {
|
||||
vendor_id: appConfig.paddleVendorId,
|
||||
vendor_auth_code: appConfig.paddleVendorAuthCode,
|
||||
@@ -24,7 +24,7 @@ const getSubscription = async (subscriptionId: number) => {
|
||||
return subscription;
|
||||
};
|
||||
|
||||
const getInvoices = async (subscriptionId: number) => {
|
||||
const getInvoices = async (subscriptionId) => {
|
||||
// TODO: iterate over previous subscriptions and include their invoices
|
||||
const data = {
|
||||
vendor_id: appConfig.paddleVendorId,
|
@@ -22,7 +22,7 @@ const prodPlans = [
|
||||
|
||||
const plans = appConfig.isProd ? prodPlans : testPlans;
|
||||
|
||||
export function getPlanById(id: string) {
|
||||
export function getPlanById(id) {
|
||||
return plans.find((plan) => plan.productId === id);
|
||||
}
|
||||
|
@@ -1,8 +1,7 @@
|
||||
import { IRequest } from '@automatisch/types';
|
||||
import Subscription from '../../models/subscription.ee';
|
||||
import Billing from './index.ee';
|
||||
|
||||
const handleSubscriptionCreated = async (request: IRequest) => {
|
||||
const handleSubscriptionCreated = async (request) => {
|
||||
const subscription = await Subscription.query().insertAndFetch(
|
||||
formatSubscription(request)
|
||||
);
|
||||
@@ -11,7 +10,7 @@ const handleSubscriptionCreated = async (request: IRequest) => {
|
||||
.insert(formatUsageData(request));
|
||||
};
|
||||
|
||||
const handleSubscriptionUpdated = async (request: IRequest) => {
|
||||
const handleSubscriptionUpdated = async (request) => {
|
||||
await Subscription.query()
|
||||
.findOne({
|
||||
paddle_subscription_id: request.body.subscription_id,
|
||||
@@ -19,7 +18,7 @@ const handleSubscriptionUpdated = async (request: IRequest) => {
|
||||
.patch(formatSubscription(request));
|
||||
};
|
||||
|
||||
const handleSubscriptionCancelled = async (request: IRequest) => {
|
||||
const handleSubscriptionCancelled = async (request) => {
|
||||
const subscription = await Subscription.query().findOne({
|
||||
paddle_subscription_id: request.body.subscription_id,
|
||||
});
|
||||
@@ -27,7 +26,7 @@ const handleSubscriptionCancelled = async (request: IRequest) => {
|
||||
await subscription.$query().patchAndFetch(formatSubscription(request));
|
||||
};
|
||||
|
||||
const handleSubscriptionPaymentSucceeded = async (request: IRequest) => {
|
||||
const handleSubscriptionPaymentSucceeded = async (request) => {
|
||||
const subscription = await Subscription.query()
|
||||
.findOne({
|
||||
paddle_subscription_id: request.body.subscription_id,
|
||||
@@ -49,7 +48,7 @@ const handleSubscriptionPaymentSucceeded = async (request: IRequest) => {
|
||||
.insert(formatUsageData(request));
|
||||
};
|
||||
|
||||
const formatSubscription = (request: IRequest) => {
|
||||
const formatSubscription = (request) => {
|
||||
return {
|
||||
userId: JSON.parse(request.body.passthrough).id,
|
||||
paddleSubscriptionId: request.body.subscription_id,
|
||||
@@ -63,7 +62,7 @@ const formatSubscription = (request: IRequest) => {
|
||||
};
|
||||
};
|
||||
|
||||
const formatUsageData = (request: IRequest) => {
|
||||
const formatUsageData = (request) => {
|
||||
return {
|
||||
userId: JSON.parse(request.body.passthrough).id,
|
||||
consumedTaskCount: 0,
|
@@ -2,7 +2,7 @@ import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import * as handlebars from 'handlebars';
|
||||
|
||||
const compileEmail = (emailPath: string, replacements: object = {}): string => {
|
||||
const compileEmail = (emailPath, replacements = {}) => {
|
||||
const filePath = path.join(__dirname, `../views/emails/${emailPath}.ee.hbs`);
|
||||
const source = fs.readFileSync(filePath, 'utf-8').toString();
|
||||
const template = handlebars.compile(source);
|
@@ -1,23 +1,18 @@
|
||||
import Step from '../models/step';
|
||||
import ExecutionStep from '../models/execution-step';
|
||||
import get from 'lodash.get';
|
||||
|
||||
const variableRegExp = /({{step\.[\da-zA-Z-]+(?:\.[^.}{]+)+}})/g;
|
||||
|
||||
export default function computeParameters(
|
||||
parameters: Step['parameters'],
|
||||
executionSteps: ExecutionStep[]
|
||||
): Step['parameters'] {
|
||||
export default function computeParameters(parameters, executionSteps) {
|
||||
const entries = Object.entries(parameters);
|
||||
return entries.reduce((result, [key, value]: [string, unknown]) => {
|
||||
return entries.reduce((result, [key, value]) => {
|
||||
if (typeof value === 'string') {
|
||||
const parts = value.split(variableRegExp);
|
||||
|
||||
const computedValue = parts
|
||||
.map((part: string) => {
|
||||
.map((part) => {
|
||||
const isVariable = part.match(variableRegExp);
|
||||
if (isVariable) {
|
||||
const stepIdAndKeyPath = part.replace(/{{step.|}}/g, '') as string;
|
||||
const stepIdAndKeyPath = part.replace(/{{step.|}}/g, '');
|
||||
const [stepId, ...keyPaths] = stepIdAndKeyPath.split('.');
|
||||
const keyPath = keyPaths.join('.');
|
||||
const executionStep = executionSteps.find((executionStep) => {
|
@@ -3,7 +3,7 @@ import appConfig from '../config/app';
|
||||
|
||||
const TOKEN_EXPIRES_IN = '14d';
|
||||
|
||||
const createAuthTokenByUserId = (userId: string) => {
|
||||
const createAuthTokenByUserId = (userId) => {
|
||||
const token = jwt.sign({ userId }, appConfig.appSecretKey, {
|
||||
expiresIn: TOKEN_EXPIRES_IN,
|
||||
});
|
@@ -31,7 +31,7 @@ const shouldEnableBullDashboard = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const createBullBoardHandler = async (serverAdapter: ExpressAdapter) => {
|
||||
const createBullBoardHandler = async (serverAdapter) => {
|
||||
if (!shouldEnableBullDashboard) return;
|
||||
|
||||
createBullBoard({
|
3
packages/backend/src/helpers/define-action.js
Normal file
3
packages/backend/src/helpers/define-action.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function defineAction(actionDefinition) {
|
||||
return actionDefinition;
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
import { IRawAction } from '@automatisch/types';
|
||||
|
||||
export default function defineAction(actionDefinition: IRawAction): IRawAction {
|
||||
return actionDefinition;
|
||||
}
|
3
packages/backend/src/helpers/define-app.js
Normal file
3
packages/backend/src/helpers/define-app.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function defineApp(appDefinition) {
|
||||
return appDefinition;
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
import { IApp } from '@automatisch/types';
|
||||
|
||||
export default function defineApp(appDefinition: IApp): IApp {
|
||||
return appDefinition;
|
||||
}
|
3
packages/backend/src/helpers/define-trigger.js
Normal file
3
packages/backend/src/helpers/define-trigger.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export default function defineTrigger(triggerDefinition) {
|
||||
return triggerDefinition;
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
import { IRawTrigger } from '@automatisch/types';
|
||||
|
||||
export default function defineTrigger(
|
||||
triggerDefinition: IRawTrigger
|
||||
): IRawTrigger {
|
||||
return triggerDefinition;
|
||||
}
|
19
packages/backend/src/helpers/delay-as-milliseconds.js
Normal file
19
packages/backend/src/helpers/delay-as-milliseconds.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import delayForAsMilliseconds from './delay-for-as-milliseconds';
|
||||
import delayUntilAsMilliseconds from './delay-until-as-milliseconds';
|
||||
|
||||
const delayAsMilliseconds = (eventKey, computedParameters) => {
|
||||
let delayDuration = 0;
|
||||
|
||||
if (eventKey === 'delayFor') {
|
||||
const { delayForUnit, delayForValue } = computedParameters;
|
||||
|
||||
delayDuration = delayForAsMilliseconds(delayForUnit, Number(delayForValue));
|
||||
} else if (eventKey === 'delayUntil') {
|
||||
const { delayUntil } = computedParameters;
|
||||
delayDuration = delayUntilAsMilliseconds(delayUntil);
|
||||
}
|
||||
|
||||
return delayDuration;
|
||||
};
|
||||
|
||||
export default delayAsMilliseconds;
|
@@ -1,25 +0,0 @@
|
||||
import Step from '../models/step';
|
||||
import delayForAsMilliseconds, {
|
||||
TDelayForUnit,
|
||||
} from './delay-for-as-milliseconds';
|
||||
import delayUntilAsMilliseconds from './delay-until-as-milliseconds';
|
||||
|
||||
const delayAsMilliseconds = (eventKey: Step["key"], computedParameters: Step["parameters"]) => {
|
||||
let delayDuration = 0;
|
||||
|
||||
if (eventKey === 'delayFor') {
|
||||
const { delayForUnit, delayForValue } = computedParameters;
|
||||
|
||||
delayDuration = delayForAsMilliseconds(
|
||||
delayForUnit as TDelayForUnit,
|
||||
Number(delayForValue)
|
||||
);
|
||||
} else if (eventKey === 'delayUntil') {
|
||||
const { delayUntil } = computedParameters;
|
||||
delayDuration = delayUntilAsMilliseconds(delayUntil as string);
|
||||
}
|
||||
|
||||
return delayDuration;
|
||||
};
|
||||
|
||||
export default delayAsMilliseconds;
|
@@ -1,9 +1,4 @@
|
||||
export type TDelayForUnit = 'minutes' | 'hours' | 'days' | 'weeks';
|
||||
|
||||
const delayAsMilliseconds = (
|
||||
delayForUnit: TDelayForUnit,
|
||||
delayForValue: number
|
||||
) => {
|
||||
const delayAsMilliseconds = (delayForUnit, delayForValue) => {
|
||||
switch (delayForUnit) {
|
||||
case 'minutes':
|
||||
return delayForValue * 60 * 1000;
|
@@ -1,4 +1,4 @@
|
||||
const delayUntilAsMilliseconds = (delayUntil: string) => {
|
||||
const delayUntilAsMilliseconds = (delayUntil) => {
|
||||
const delayUntilDate = new Date(delayUntil);
|
||||
const now = new Date();
|
||||
|
@@ -1,22 +1,17 @@
|
||||
import SamlAuthProvider from '../models/saml-auth-provider.ee';
|
||||
import User from '../models/user';
|
||||
import Identity from '../models/identity.ee';
|
||||
import SamlAuthProvidersRoleMapping from '../models/saml-auth-providers-role-mapping.ee';
|
||||
|
||||
const getUser = (
|
||||
user: Record<string, unknown>,
|
||||
providerConfig: SamlAuthProvider
|
||||
) => ({
|
||||
const getUser = (user, providerConfig) => ({
|
||||
name: user[providerConfig.firstnameAttributeName],
|
||||
surname: user[providerConfig.surnameAttributeName],
|
||||
id: user.nameID,
|
||||
email: user[providerConfig.emailAttributeName],
|
||||
role: user[providerConfig.roleAttributeName] as string | string[],
|
||||
role: user[providerConfig.roleAttributeName],
|
||||
});
|
||||
|
||||
const findOrCreateUserBySamlIdentity = async (
|
||||
userIdentity: Record<string, unknown>,
|
||||
samlAuthProvider: SamlAuthProvider
|
||||
userIdentity,
|
||||
samlAuthProvider
|
||||
) => {
|
||||
const mappedUser = getUser(userIdentity, samlAuthProvider);
|
||||
const identity = await Identity.query().findOne({
|
||||
@@ -46,12 +41,12 @@ const findOrCreateUserBySamlIdentity = async (
|
||||
fullName: [mappedUser.name, mappedUser.surname]
|
||||
.filter(Boolean)
|
||||
.join(' '),
|
||||
email: mappedUser.email as string,
|
||||
email: mappedUser.email,
|
||||
roleId:
|
||||
samlAuthProviderRoleMapping?.roleId || samlAuthProvider.defaultRoleId,
|
||||
identities: [
|
||||
{
|
||||
remoteId: mappedUser.id as string,
|
||||
remoteId: mappedUser.id,
|
||||
providerId: samlAuthProvider.id,
|
||||
providerType: 'saml',
|
||||
},
|
@@ -1,17 +1,9 @@
|
||||
import path from 'node:path';
|
||||
import fs from 'node:fs';
|
||||
import {
|
||||
IAction,
|
||||
IApp,
|
||||
IRawAction,
|
||||
IRawTrigger,
|
||||
ITrigger,
|
||||
} from '@automatisch/types';
|
||||
import { omit, cloneDeep } from 'lodash';
|
||||
import addAuthenticationSteps from './add-authentication-steps';
|
||||
import addReconnectionSteps from './add-reconnection-steps';
|
||||
|
||||
type TApps = Record<string, Promise<{ default: IApp }>>;
|
||||
const apps = fs
|
||||
.readdirSync(path.resolve(__dirname, `../apps/`), { withFileTypes: true })
|
||||
.reduce((apps, dirent) => {
|
||||
@@ -20,33 +12,35 @@ const apps = fs
|
||||
apps[dirent.name] = import(path.resolve(__dirname, '../apps', dirent.name));
|
||||
|
||||
return apps;
|
||||
}, {} as TApps);
|
||||
}, {});
|
||||
|
||||
async function getAppDefaultExport(appKey: string) {
|
||||
async function getAppDefaultExport(appKey) {
|
||||
if (!Object.prototype.hasOwnProperty.call(apps, appKey)) {
|
||||
throw new Error(`An application with the "${appKey}" key couldn't be found.`);
|
||||
throw new Error(
|
||||
`An application with the "${appKey}" key couldn't be found.`
|
||||
);
|
||||
}
|
||||
|
||||
return (await apps[appKey]).default;
|
||||
}
|
||||
|
||||
function stripFunctions<C>(data: C): C {
|
||||
function stripFunctions(data) {
|
||||
return JSON.parse(JSON.stringify(data));
|
||||
}
|
||||
|
||||
const getApp = async (appKey: string, stripFuncs = true) => {
|
||||
let appData: IApp = cloneDeep(await getAppDefaultExport(appKey));
|
||||
const getApp = async (appKey, stripFuncs = true) => {
|
||||
let appData = cloneDeep(await getAppDefaultExport(appKey));
|
||||
|
||||
if (appData.auth) {
|
||||
appData = addAuthenticationSteps(appData);
|
||||
appData = addReconnectionSteps(appData);
|
||||
}
|
||||
|
||||
appData.triggers = appData?.triggers?.map((trigger: IRawTrigger) => {
|
||||
appData.triggers = appData?.triggers?.map((trigger) => {
|
||||
return addStaticSubsteps('trigger', appData, trigger);
|
||||
});
|
||||
|
||||
appData.actions = appData?.actions?.map((action: IRawAction) => {
|
||||
appData.actions = appData?.actions?.map((action) => {
|
||||
return addStaticSubsteps('action', appData, action);
|
||||
});
|
||||
|
||||
@@ -62,19 +56,15 @@ const chooseConnectionStep = {
|
||||
name: 'Choose connection',
|
||||
};
|
||||
|
||||
const testStep = (stepType: 'trigger' | 'action') => {
|
||||
const testStep = (stepType) => {
|
||||
return {
|
||||
key: 'testStep',
|
||||
name: stepType === 'trigger' ? 'Test trigger' : 'Test action',
|
||||
};
|
||||
};
|
||||
|
||||
const addStaticSubsteps = (
|
||||
stepType: 'trigger' | 'action',
|
||||
appData: IApp,
|
||||
step: IRawTrigger | IRawAction
|
||||
) => {
|
||||
const computedStep: ITrigger | IAction = omit(step, ['arguments']);
|
||||
const addStaticSubsteps = (stepType, appData, step) => {
|
||||
const computedStep = omit(step, ['arguments']);
|
||||
|
||||
computedStep.substeps = [];
|
||||
|
@@ -1,32 +1,8 @@
|
||||
import createHttpClient from './http-client';
|
||||
import Connection from '../models/connection';
|
||||
import Flow from '../models/flow';
|
||||
import Step from '../models/step';
|
||||
import Execution from '../models/execution';
|
||||
import {
|
||||
IJSONObject,
|
||||
IApp,
|
||||
IGlobalVariable,
|
||||
ITriggerItem,
|
||||
IActionItem,
|
||||
IRequest,
|
||||
} from '@automatisch/types';
|
||||
import EarlyExitError from '../errors/early-exit';
|
||||
import AlreadyProcessedError from '../errors/already-processed';
|
||||
|
||||
type GlobalVariableOptions = {
|
||||
connection?: Connection;
|
||||
app?: IApp;
|
||||
flow?: Flow;
|
||||
step?: Step;
|
||||
execution?: Execution;
|
||||
testRun?: boolean;
|
||||
request?: IRequest;
|
||||
};
|
||||
|
||||
const globalVariable = async (
|
||||
options: GlobalVariableOptions
|
||||
): Promise<IGlobalVariable> => {
|
||||
const globalVariable = async (options) => {
|
||||
const {
|
||||
connection,
|
||||
app,
|
||||
@@ -41,9 +17,9 @@ const globalVariable = async (
|
||||
const lastInternalId = testRun ? undefined : await flow?.lastInternalId();
|
||||
const nextStep = await step?.getNextStep();
|
||||
|
||||
const $: IGlobalVariable = {
|
||||
const $ = {
|
||||
auth: {
|
||||
set: async (args: IJSONObject) => {
|
||||
set: async (args) => {
|
||||
if (connection) {
|
||||
await connection.$query().patchAndFetch({
|
||||
formattedData: {
|
||||
@@ -91,7 +67,7 @@ const globalVariable = async (
|
||||
raw: null,
|
||||
},
|
||||
},
|
||||
pushTriggerItem: (triggerItem: ITriggerItem) => {
|
||||
pushTriggerItem: (triggerItem) => {
|
||||
if (
|
||||
isAlreadyProcessed(triggerItem.meta.internalId) &&
|
||||
!$.execution.testRun
|
||||
@@ -109,7 +85,7 @@ const globalVariable = async (
|
||||
throw new EarlyExitError();
|
||||
}
|
||||
},
|
||||
setActionItem: (actionItem: IActionItem) => {
|
||||
setActionItem: (actionItem) => {
|
||||
$.actionOutput.data = actionItem;
|
||||
},
|
||||
};
|
||||
@@ -151,7 +127,7 @@ const globalVariable = async (
|
||||
? []
|
||||
: await flow?.lastInternalIds(2000);
|
||||
|
||||
const isAlreadyProcessed = (internalId: string) => {
|
||||
const isAlreadyProcessed = (internalId) => {
|
||||
return lastInternalIds?.includes(internalId);
|
||||
};
|
||||
|
@@ -6,9 +6,9 @@ import { addResolversToSchema } from '@graphql-tools/schema';
|
||||
import { applyMiddleware } from 'graphql-middleware';
|
||||
|
||||
import appConfig from '../config/app';
|
||||
import logger from '../helpers/logger';
|
||||
import authentication from '../helpers/authentication';
|
||||
import * as Sentry from '../helpers/sentry.ee';
|
||||
import logger from './logger';
|
||||
import authentication from './authentication';
|
||||
import * as Sentry from './sentry.ee';
|
||||
import resolvers from '../graphql/resolvers';
|
||||
import HttpError from '../errors/http';
|
||||
|
||||
@@ -28,7 +28,7 @@ const graphQLInstance = graphqlHTTP({
|
||||
logger.error(error.path + ' : ' + error.message + '\n' + error.stack);
|
||||
|
||||
if (error.originalError instanceof HttpError) {
|
||||
delete (error.originalError as HttpError).response;
|
||||
delete error.originalError.response;
|
||||
}
|
||||
|
||||
Sentry.captureException(error, {
|
||||
@@ -36,9 +36,9 @@ const graphQLInstance = graphqlHTTP({
|
||||
extra: {
|
||||
source: error.source?.body,
|
||||
positions: error.positions,
|
||||
path: error.path
|
||||
}
|
||||
})
|
||||
path: error.path,
|
||||
},
|
||||
});
|
||||
|
||||
return error;
|
||||
},
|
@@ -1,14 +1,10 @@
|
||||
import { IHttpClientParams } from '@automatisch/types';
|
||||
import { InternalAxiosRequestConfig } from 'axios';
|
||||
import { URL } from 'node:url';
|
||||
export { AxiosInstance as IHttpClient } from 'axios';
|
||||
|
||||
import HttpError from '../../errors/http';
|
||||
import axios from '../axios-with-proxy';
|
||||
|
||||
const removeBaseUrlForAbsoluteUrls = (
|
||||
requestConfig: InternalAxiosRequestConfig
|
||||
): InternalAxiosRequestConfig => {
|
||||
const removeBaseUrlForAbsoluteUrls = (requestConfig) => {
|
||||
try {
|
||||
const url = new URL(requestConfig.url);
|
||||
requestConfig.baseURL = url.origin;
|
||||
@@ -20,33 +16,27 @@ const removeBaseUrlForAbsoluteUrls = (
|
||||
}
|
||||
};
|
||||
|
||||
export default function createHttpClient({
|
||||
$,
|
||||
baseURL,
|
||||
beforeRequest = [],
|
||||
}: IHttpClientParams) {
|
||||
export default function createHttpClient({ $, baseURL, beforeRequest = [] }) {
|
||||
const instance = axios.create({
|
||||
baseURL,
|
||||
});
|
||||
|
||||
instance.interceptors.request.use(
|
||||
(requestConfig: InternalAxiosRequestConfig): InternalAxiosRequestConfig => {
|
||||
const newRequestConfig = removeBaseUrlForAbsoluteUrls(requestConfig);
|
||||
instance.interceptors.request.use((requestConfig) => {
|
||||
const newRequestConfig = removeBaseUrlForAbsoluteUrls(requestConfig);
|
||||
|
||||
const result = beforeRequest.reduce((newConfig, beforeRequestFunc) => {
|
||||
return beforeRequestFunc($, newConfig);
|
||||
}, newRequestConfig);
|
||||
const result = beforeRequest.reduce((newConfig, beforeRequestFunc) => {
|
||||
return beforeRequestFunc($, newConfig);
|
||||
}, newRequestConfig);
|
||||
|
||||
/**
|
||||
* axios seems to want InternalAxiosRequestConfig returned not AxioRequestConfig
|
||||
* anymore even though requests do require AxiosRequestConfig.
|
||||
*
|
||||
* Since both interfaces are very similar (InternalAxiosRequestConfig
|
||||
* extends AxiosRequestConfig), we can utilize an assertion below
|
||||
**/
|
||||
return result as InternalAxiosRequestConfig;
|
||||
}
|
||||
);
|
||||
/**
|
||||
* axios seems to want InternalAxiosRequestConfig returned not AxioRequestConfig
|
||||
* anymore even though requests do require AxiosRequestConfig.
|
||||
*
|
||||
* Since both interfaces are very similar (InternalAxiosRequestConfig
|
||||
* extends AxiosRequestConfig), we can utilize an assertion below
|
||||
**/
|
||||
return result;
|
||||
});
|
||||
|
||||
instance.interceptors.response.use(
|
||||
(response) => response,
|
@@ -1,12 +1,7 @@
|
||||
import { Application } from 'express';
|
||||
import { ExpressAdapter } from '@bull-board/express';
|
||||
import basicAuth from 'express-basic-auth';
|
||||
import appConfig from '../config/app';
|
||||
|
||||
const injectBullBoardHandler = async (
|
||||
app: Application,
|
||||
serverAdapter: ExpressAdapter
|
||||
) => {
|
||||
const injectBullBoardHandler = async (app, serverAdapter) => {
|
||||
if (
|
||||
!appConfig.enableBullMQDashboard ||
|
||||
!appConfig.bullMQDashboardUsername ||
|
@@ -1,14 +1,13 @@
|
||||
import morgan, { StreamOptions } from 'morgan';
|
||||
import { Request } from 'express';
|
||||
import morgan from 'morgan';
|
||||
import logger from './logger';
|
||||
|
||||
const stream: StreamOptions = {
|
||||
const stream = {
|
||||
write: (message) =>
|
||||
logger.http(message.substring(0, message.lastIndexOf('\n'))),
|
||||
};
|
||||
|
||||
const registerGraphQLToken = () => {
|
||||
morgan.token('graphql-query', (req: Request) => {
|
||||
morgan.token('graphql-query', (req) => {
|
||||
if (req.body.query) {
|
||||
return `GraphQL ${req.body.query}`;
|
||||
}
|
@@ -1,12 +1,4 @@
|
||||
import { Model } from 'objection';
|
||||
import ExtendedQueryBuilder from '../models/query-builder';
|
||||
import type Base from '../models/base';
|
||||
|
||||
const paginate = async (
|
||||
query: ExtendedQueryBuilder<Model, Model[]>,
|
||||
limit: number,
|
||||
offset: number,
|
||||
) => {
|
||||
const paginate = async (query, limit, offset) => {
|
||||
if (limit < 1 || limit > 100) {
|
||||
throw new Error('Limit must be between 1 and 100');
|
||||
}
|
||||
@@ -22,7 +14,7 @@ const paginate = async (
|
||||
totalPages: Math.ceil(count / limit),
|
||||
},
|
||||
totalCount: count,
|
||||
edges: records.map((record: Base) => ({
|
||||
edges: records.map((record) => ({
|
||||
node: record,
|
||||
})),
|
||||
};
|
@@ -1,38 +1,16 @@
|
||||
type TParameters = {
|
||||
[key: string]: string;
|
||||
rel?: string;
|
||||
};
|
||||
|
||||
type TReference = {
|
||||
uri: string;
|
||||
parameters: TParameters;
|
||||
};
|
||||
|
||||
type TRel = 'next' | 'prev' | 'first' | 'last';
|
||||
|
||||
type TParsedLinkHeader = {
|
||||
next?: TReference;
|
||||
prev?: TReference;
|
||||
first?: TReference;
|
||||
last?: TReference;
|
||||
};
|
||||
|
||||
export default function parseLinkHeader(link: string): TParsedLinkHeader {
|
||||
const parsed: TParsedLinkHeader = {};
|
||||
export default function parseLinkHeader(link) {
|
||||
const parsed = {};
|
||||
|
||||
if (!link) return parsed;
|
||||
|
||||
const items = link.split(',');
|
||||
|
||||
for (const item of items) {
|
||||
const [rawUriReference, ...rawLinkParameters] = item.split(';') as [
|
||||
string,
|
||||
...string[]
|
||||
];
|
||||
const [rawUriReference, ...rawLinkParameters] = item.split(';');
|
||||
const trimmedUriReference = rawUriReference.trim();
|
||||
|
||||
const reference = trimmedUriReference.slice(1, -1);
|
||||
const parameters: TParameters = {};
|
||||
const parameters = {};
|
||||
|
||||
for (const rawParameter of rawLinkParameters) {
|
||||
const trimmedRawParameter = rawParameter.trim();
|
||||
@@ -41,7 +19,7 @@ export default function parseLinkHeader(link: string): TParsedLinkHeader {
|
||||
parameters[key.trim()] = value.slice(1, -1);
|
||||
}
|
||||
|
||||
parsed[parameters.rel as TRel] = {
|
||||
parsed[parameters.rel] = {
|
||||
uri: reference,
|
||||
parameters,
|
||||
};
|
89
packages/backend/src/helpers/passport.js
Normal file
89
packages/backend/src/helpers/passport.js
Normal file
@@ -0,0 +1,89 @@
|
||||
import { URL } from 'node:url';
|
||||
import { MultiSamlStrategy } from '@node-saml/passport-saml';
|
||||
import passport from 'passport';
|
||||
|
||||
import appConfig from '../config/app';
|
||||
import createAuthTokenByUserId from './create-auth-token-by-user-id';
|
||||
import SamlAuthProvider from '../models/saml-auth-provider.ee';
|
||||
import findOrCreateUserBySamlIdentity from './find-or-create-user-by-saml-identity.ee';
|
||||
|
||||
export default function configurePassport(app) {
|
||||
app.use(
|
||||
passport.initialize({
|
||||
userProperty: 'currentUser',
|
||||
})
|
||||
);
|
||||
|
||||
passport.use(
|
||||
new MultiSamlStrategy(
|
||||
{
|
||||
passReqToCallback: true,
|
||||
getSamlOptions: async function (request, done) {
|
||||
const { issuer } = request.params;
|
||||
const notFoundIssuer = new Error('Issuer cannot be found!');
|
||||
|
||||
if (!issuer) return done(notFoundIssuer);
|
||||
|
||||
const authProvider = await SamlAuthProvider.query().findOne({
|
||||
issuer: request.params.issuer,
|
||||
});
|
||||
|
||||
if (!authProvider) {
|
||||
return done(notFoundIssuer);
|
||||
}
|
||||
|
||||
return done(null, authProvider.config);
|
||||
},
|
||||
},
|
||||
async function (request, user, done) {
|
||||
const { issuer } = request.params;
|
||||
const notFoundIssuer = new Error('Issuer cannot be found!');
|
||||
|
||||
if (!issuer) return done(notFoundIssuer);
|
||||
|
||||
const authProvider = await SamlAuthProvider.query().findOne({
|
||||
issuer: request.params.issuer,
|
||||
});
|
||||
|
||||
if (!authProvider) {
|
||||
return done(notFoundIssuer);
|
||||
}
|
||||
|
||||
const foundUserWithIdentity = await findOrCreateUserBySamlIdentity(
|
||||
user,
|
||||
authProvider
|
||||
);
|
||||
return done(null, foundUserWithIdentity);
|
||||
},
|
||||
function (request, user, done) {
|
||||
return done(null, null);
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
app.get(
|
||||
'/login/saml/:issuer',
|
||||
passport.authenticate('saml', {
|
||||
session: false,
|
||||
successRedirect: '/',
|
||||
})
|
||||
);
|
||||
|
||||
app.post(
|
||||
'/login/saml/:issuer/callback',
|
||||
passport.authenticate('saml', {
|
||||
session: false,
|
||||
failureRedirect: '/',
|
||||
failureFlash: true,
|
||||
}),
|
||||
(req, res) => {
|
||||
const token = createAuthTokenByUserId(req.currentUser.id);
|
||||
|
||||
const redirectUrl = new URL(
|
||||
`/login/callback?token=${token}`,
|
||||
appConfig.webAppUrl
|
||||
).toString();
|
||||
res.redirect(redirectUrl);
|
||||
}
|
||||
);
|
||||
}
|
@@ -1,84 +0,0 @@
|
||||
import { URL } from 'node:url';
|
||||
import { IRequest } from '@automatisch/types';
|
||||
import { MultiSamlStrategy } from '@node-saml/passport-saml';
|
||||
import { Express } from 'express';
|
||||
import passport from 'passport';
|
||||
|
||||
import appConfig from '../config/app';
|
||||
import createAuthTokenByUserId from '../helpers/create-auth-token-by-user-id';
|
||||
import SamlAuthProvider from '../models/saml-auth-provider.ee';
|
||||
import findOrCreateUserBySamlIdentity from './find-or-create-user-by-saml-identity.ee'
|
||||
|
||||
export default function configurePassport(app: Express) {
|
||||
app.use(passport.initialize({
|
||||
userProperty: 'currentUser',
|
||||
}));
|
||||
|
||||
passport.use(new MultiSamlStrategy(
|
||||
{
|
||||
passReqToCallback: true,
|
||||
getSamlOptions: async function (request, done) {
|
||||
const { issuer } = request.params;
|
||||
const notFoundIssuer = new Error('Issuer cannot be found!');
|
||||
|
||||
if (!issuer) return done(notFoundIssuer);
|
||||
|
||||
const authProvider = await SamlAuthProvider.query().findOne({
|
||||
issuer: request.params.issuer as string,
|
||||
});
|
||||
|
||||
if (!authProvider) {
|
||||
return done(notFoundIssuer);
|
||||
}
|
||||
|
||||
return done(null, authProvider.config);
|
||||
},
|
||||
},
|
||||
async function (request, user: Record<string, unknown>, done) {
|
||||
const { issuer } = request.params;
|
||||
const notFoundIssuer = new Error('Issuer cannot be found!');
|
||||
|
||||
if (!issuer) return done(notFoundIssuer);
|
||||
|
||||
const authProvider = await SamlAuthProvider.query().findOne({
|
||||
issuer: request.params.issuer as string,
|
||||
});
|
||||
|
||||
if (!authProvider) {
|
||||
return done(notFoundIssuer);
|
||||
}
|
||||
|
||||
const foundUserWithIdentity = await findOrCreateUserBySamlIdentity(user, authProvider);
|
||||
return done(null, foundUserWithIdentity as unknown as Record<string, unknown>);
|
||||
},
|
||||
function (request, user: Record<string, unknown>, done: (error: any, user: Record<string, unknown>) => void) {
|
||||
return done(null, null);
|
||||
}
|
||||
));
|
||||
|
||||
app.get('/login/saml/:issuer',
|
||||
passport.authenticate('saml',
|
||||
{
|
||||
session: false,
|
||||
successRedirect: '/',
|
||||
})
|
||||
);
|
||||
|
||||
app.post(
|
||||
'/login/saml/:issuer/callback',
|
||||
passport.authenticate('saml', {
|
||||
session: false,
|
||||
failureRedirect: '/',
|
||||
failureFlash: true,
|
||||
}),
|
||||
(req: IRequest, res) => {
|
||||
const token = createAuthTokenByUserId(req.currentUser.id);
|
||||
|
||||
const redirectUrl = new URL(
|
||||
`/login/callback?token=${token}`,
|
||||
appConfig.webAppUrl,
|
||||
).toString();
|
||||
res.redirect(redirectUrl);
|
||||
}
|
||||
);
|
||||
};
|
@@ -1,13 +1,11 @@
|
||||
import { Express } from 'express';
|
||||
import * as Sentry from '@sentry/node';
|
||||
import type { CaptureContext } from '@sentry/types';
|
||||
import * as Tracing from '@sentry/tracing';
|
||||
|
||||
import appConfig from '../config/app';
|
||||
|
||||
const isSentryEnabled = !!appConfig.sentryDsn;
|
||||
|
||||
export function init(app?: Express) {
|
||||
export function init(app) {
|
||||
if (!isSentryEnabled) return;
|
||||
|
||||
return Sentry.init({
|
||||
@@ -22,31 +20,32 @@ export function init(app?: Express) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
export function attachRequestHandler(app: Express) {
|
||||
export function attachRequestHandler(app) {
|
||||
if (!isSentryEnabled) return;
|
||||
|
||||
app.use(Sentry.Handlers.requestHandler());
|
||||
}
|
||||
|
||||
export function attachTracingHandler(app: Express) {
|
||||
export function attachTracingHandler(app) {
|
||||
if (!isSentryEnabled) return;
|
||||
|
||||
app.use(Sentry.Handlers.tracingHandler());
|
||||
}
|
||||
|
||||
export function attachErrorHandler(app: Express) {
|
||||
export function attachErrorHandler(app) {
|
||||
if (!isSentryEnabled) return;
|
||||
|
||||
app.use(Sentry.Handlers.errorHandler({
|
||||
shouldHandleError() {
|
||||
// TODO: narrow down the captured errors in time as we receive samples
|
||||
return true;
|
||||
}
|
||||
}));
|
||||
app.use(
|
||||
Sentry.Handlers.errorHandler({
|
||||
shouldHandleError() {
|
||||
// TODO: narrow down the captured errors in time as we receive samples
|
||||
return true;
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
export function captureException(exception: any, captureContext?: CaptureContext) {
|
||||
export function captureException(exception, captureContext) {
|
||||
if (!isSentryEnabled) return;
|
||||
|
||||
return Sentry.captureException(exception, captureContext);
|
@@ -1,12 +1,7 @@
|
||||
import Analytics, { apiObject } from '@rudderstack/rudder-sdk-node';
|
||||
import Analytics from '@rudderstack/rudder-sdk-node';
|
||||
import organizationId from './organization-id';
|
||||
import instanceId from './instance-id';
|
||||
import appConfig from '../../config/app';
|
||||
import Step from '../../models/step';
|
||||
import Flow from '../../models/flow';
|
||||
import Execution from '../../models/execution';
|
||||
import ExecutionStep from '../../models/execution-step';
|
||||
import Connection from '../../models/connection';
|
||||
import os from 'os';
|
||||
|
||||
const WRITE_KEY = '284Py4VgK2MsNYV7xlKzyrALx0v';
|
||||
@@ -15,22 +10,17 @@ const CPUS = os.cpus();
|
||||
const SIX_HOURS_IN_MILLISECONDS = 21600000;
|
||||
|
||||
class Telemetry {
|
||||
organizationId: string;
|
||||
instanceId: string;
|
||||
client: Analytics;
|
||||
serviceType: string;
|
||||
|
||||
constructor() {
|
||||
this.client = new Analytics(WRITE_KEY, DATA_PLANE_URL);
|
||||
this.organizationId = organizationId();
|
||||
this.instanceId = instanceId();
|
||||
}
|
||||
|
||||
setServiceType(type: string) {
|
||||
setServiceType(type) {
|
||||
this.serviceType = type;
|
||||
}
|
||||
|
||||
track(name: string, properties: apiObject) {
|
||||
track(name, properties) {
|
||||
if (!appConfig.telemetryEnabled) {
|
||||
return;
|
||||
}
|
||||
@@ -48,7 +38,7 @@ class Telemetry {
|
||||
});
|
||||
}
|
||||
|
||||
stepCreated(step: Step) {
|
||||
stepCreated(step) {
|
||||
this.track('stepCreated', {
|
||||
stepId: step.id,
|
||||
flowId: step.flowId,
|
||||
@@ -57,7 +47,7 @@ class Telemetry {
|
||||
});
|
||||
}
|
||||
|
||||
stepUpdated(step: Step) {
|
||||
stepUpdated(step) {
|
||||
this.track('stepUpdated', {
|
||||
stepId: step.id,
|
||||
flowId: step.flowId,
|
||||
@@ -71,7 +61,7 @@ class Telemetry {
|
||||
});
|
||||
}
|
||||
|
||||
flowCreated(flow: Flow) {
|
||||
flowCreated(flow) {
|
||||
this.track('flowCreated', {
|
||||
flowId: flow.id,
|
||||
name: flow.name,
|
||||
@@ -81,7 +71,7 @@ class Telemetry {
|
||||
});
|
||||
}
|
||||
|
||||
flowUpdated(flow: Flow) {
|
||||
flowUpdated(flow) {
|
||||
this.track('flowUpdated', {
|
||||
flowId: flow.id,
|
||||
name: flow.name,
|
||||
@@ -91,7 +81,7 @@ class Telemetry {
|
||||
});
|
||||
}
|
||||
|
||||
executionCreated(execution: Execution) {
|
||||
executionCreated(execution) {
|
||||
this.track('executionCreated', {
|
||||
executionId: execution.id,
|
||||
flowId: execution.flowId,
|
||||
@@ -101,7 +91,7 @@ class Telemetry {
|
||||
});
|
||||
}
|
||||
|
||||
executionStepCreated(executionStep: ExecutionStep) {
|
||||
executionStepCreated(executionStep) {
|
||||
this.track('executionStepCreated', {
|
||||
executionStepId: executionStep.id,
|
||||
executionId: executionStep.executionId,
|
||||
@@ -112,7 +102,7 @@ class Telemetry {
|
||||
});
|
||||
}
|
||||
|
||||
connectionCreated(connection: Connection) {
|
||||
connectionCreated(connection) {
|
||||
this.track('connectionCreated', {
|
||||
connectionId: connection.id,
|
||||
key: connection.key,
|
||||
@@ -122,7 +112,7 @@ class Telemetry {
|
||||
});
|
||||
}
|
||||
|
||||
connectionUpdated(connection: Connection) {
|
||||
connectionUpdated(connection) {
|
||||
this.track('connectionUpdated', {
|
||||
connectionId: connection.id,
|
||||
key: connection.key,
|
@@ -1,20 +1,23 @@
|
||||
import { PureAbility, fieldPatternMatcher, mongoQueryMatcher } from '@casl/ability';
|
||||
import type User from '../models/user'
|
||||
import {
|
||||
PureAbility,
|
||||
fieldPatternMatcher,
|
||||
mongoQueryMatcher,
|
||||
} from '@casl/ability';
|
||||
|
||||
// Must be kept in sync with `packages/web/src/helpers/userAbility.ts`!
|
||||
export default function userAbility(user: Partial<User>) {
|
||||
export default function userAbility(user) {
|
||||
const permissions = user?.permissions;
|
||||
const role = user?.role;
|
||||
|
||||
// We're not using mongo, but our fields, conditions match
|
||||
const options = {
|
||||
conditionsMatcher: mongoQueryMatcher,
|
||||
fieldMatcher: fieldPatternMatcher
|
||||
fieldMatcher: fieldPatternMatcher,
|
||||
};
|
||||
|
||||
if (!role || !permissions) {
|
||||
return new PureAbility([], options);
|
||||
}
|
||||
|
||||
return new PureAbility<[string, string], string[]>(permissions, options);
|
||||
return new PureAbility(permissions, options);
|
||||
}
|
@@ -1,8 +1,8 @@
|
||||
import express, { Application } from 'express';
|
||||
import express from 'express';
|
||||
import { dirname, join } from 'path';
|
||||
import appConfig from '../config/app';
|
||||
|
||||
const webUIHandler = async (app: Application) => {
|
||||
const webUIHandler = async (app) => {
|
||||
if (appConfig.serveWebAppSeparately) return;
|
||||
|
||||
const webAppPath = require.resolve('@automatisch/web');
|
@@ -1,5 +1,3 @@
|
||||
import { Response } from 'express';
|
||||
import { IRequest } from '@automatisch/types';
|
||||
import isEmpty from 'lodash/isEmpty';
|
||||
|
||||
import Flow from '../models/flow';
|
||||
@@ -12,11 +10,7 @@ import {
|
||||
REMOVE_AFTER_7_DAYS_OR_50_JOBS,
|
||||
} from './remove-job-configuration';
|
||||
|
||||
export default async (
|
||||
flowId: string,
|
||||
request: IRequest,
|
||||
response: Response
|
||||
) => {
|
||||
export default async (flowId, request, response) => {
|
||||
const flow = await Flow.query().findById(flowId).throwIfNotFound();
|
||||
const user = await flow.$relatedQuery('user');
|
||||
|
Reference in New Issue
Block a user