Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c762f0562f | ||
![]() |
98274c3d71 |
@@ -8,7 +8,7 @@
|
|||||||
"version": "latest"
|
"version": "latest"
|
||||||
},
|
},
|
||||||
"ghcr.io/devcontainers/features/node:1": {
|
"ghcr.io/devcontainers/features/node:1": {
|
||||||
"version": 18
|
"version": 20
|
||||||
},
|
},
|
||||||
"ghcr.io/devcontainers/features/common-utils:1": {
|
"ghcr.io/devcontainers/features/common-utils:1": {
|
||||||
"username": "vscode",
|
"username": "vscode",
|
||||||
|
@@ -33,6 +33,7 @@
|
|||||||
"axios": "1.6.0",
|
"axios": "1.6.0",
|
||||||
"bcrypt": "^5.0.1",
|
"bcrypt": "^5.0.1",
|
||||||
"bullmq": "^3.0.0",
|
"bullmq": "^3.0.0",
|
||||||
|
"copyfiles": "^2.4.1",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"debug": "~2.6.9",
|
"debug": "~2.6.9",
|
||||||
@@ -44,6 +45,7 @@
|
|||||||
"graphql-middleware": "^6.1.15",
|
"graphql-middleware": "^6.1.15",
|
||||||
"graphql-shield": "^7.5.0",
|
"graphql-shield": "^7.5.0",
|
||||||
"graphql-tools": "^8.2.0",
|
"graphql-tools": "^8.2.0",
|
||||||
|
"graphql-type-json": "^0.3.2",
|
||||||
"handlebars": "^4.7.7",
|
"handlebars": "^4.7.7",
|
||||||
"http-errors": "~1.6.3",
|
"http-errors": "~1.6.3",
|
||||||
"http-proxy-agent": "^7.0.0",
|
"http-proxy-agent": "^7.0.0",
|
||||||
@@ -66,6 +68,7 @@
|
|||||||
"pluralize": "^8.0.0",
|
"pluralize": "^8.0.0",
|
||||||
"raw-body": "^2.5.2",
|
"raw-body": "^2.5.2",
|
||||||
"showdown": "^2.1.0",
|
"showdown": "^2.1.0",
|
||||||
|
"stripe": "^11.13.0",
|
||||||
"winston": "^3.7.1",
|
"winston": "^3.7.1",
|
||||||
"xmlrpc": "^1.3.2"
|
"xmlrpc": "^1.3.2"
|
||||||
},
|
},
|
||||||
|
1
packages/backend/src/apps/airbrake/assets/favicon.svg
Normal file
1
packages/backend/src/apps/airbrake/assets/favicon.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg height="255" preserveAspectRatio="xMidYMid" viewBox="0 0 256 255" width="256" xmlns="http://www.w3.org/2000/svg"><path d="m128.636514 155.746615v-155.23361889h-3.522242v.06873152l-124.60824865 64.03287157v60.8642488h.00597665v3.234366h-.00597665v60.868233l124.60824865 64.747082h3.842989v-98.581914z" fill="#ff8e4a"/><path d="m129.941416 254.328529 125.568498-64.747082v-124.9668478l-125.887253-64.10160309h-2.243237v253.81055289h2.243237" fill="#f48746"/><path d="m109.097837 87.2551595h36.19561v59.2077195h-36.19561z" fill="#ff8e4a"/><path d="m66.1735097 188.397074h14.8639378c9.4102412 0 12.6087471-2.238257 15.6189883-9.988981l8.2796572-21.353587h45.159596l8.280653 21.353587c3.011238 7.750724 6.396016 9.988981 15.805261 9.988981h14.677665v-19.114335h-3.011237c-3.19751 0-4.704622-.689307-5.831222-3.790194l-39.516638-99.3658524h-25.779299l-39.703907 99.3658524c-1.1285915 3.100887-2.632716 3.790194-5.833214 3.790194h-3.0102413zm44.4075333-49.939922 11.478163-30.655253c2.445448-6.714771 5.269417-18.2556889 5.269417-18.2556889h.375533s2.822972 11.5409179 5.269416 18.2556889l11.478163 30.655253z" fill="#fff"/><path d="m231.204856 150.082739v-51.8086223c.235082 4.5233303 2.970397 16.8432063 24.305058 27.8512063v11.653479zm0-53.1623343v1.353712c-.029883-.5926848-.01793-1.0479066 0-1.353712zm.041837-.4392841s-.022911.1534008-.041837.4392841v-.4392841z" fill="#d4763c"/><path d="m231.155051 94.3016342c-.013946.9931207.05877 1.8945993.049805 2.0460078-.01793.2480312-2.220327 16.094132 24.305058 29.777681v-60.863253c-23.325883 12.0349884-24.449494 25.7414475-24.354863 29.0395642" fill="#ff8e4a"/></svg>
|
After Width: | Height: | Size: 1.6 KiB |
44
packages/backend/src/apps/airbrake/auth/index.js
Normal file
44
packages/backend/src/apps/airbrake/auth/index.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import verifyCredentials from './verify-credentials.js';
|
||||||
|
import isStillVerified from './is-still-verified.js';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
key: 'screenName',
|
||||||
|
label: 'Screen Name',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: false,
|
||||||
|
value: null,
|
||||||
|
placeholder: null,
|
||||||
|
description:
|
||||||
|
'Screen name of your connection to be used on Automatisch UI.',
|
||||||
|
clickToCopy: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'instanceUrl',
|
||||||
|
label: 'Instance URL',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: false,
|
||||||
|
value: null,
|
||||||
|
placeholder: null,
|
||||||
|
description: 'Your subdomain as https://{yoursubdomain}.airbrake.io',
|
||||||
|
clickToCopy: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'authToken',
|
||||||
|
label: 'Auth Token',
|
||||||
|
type: 'string',
|
||||||
|
required: true,
|
||||||
|
readOnly: false,
|
||||||
|
value: null,
|
||||||
|
placeholder: null,
|
||||||
|
description: 'Airbrake Auth Token of your account.',
|
||||||
|
clickToCopy: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
verifyCredentials,
|
||||||
|
isStillVerified,
|
||||||
|
};
|
@@ -0,0 +1,8 @@
|
|||||||
|
import verifyCredentials from './verify-credentials.js';
|
||||||
|
|
||||||
|
const isStillVerified = async ($) => {
|
||||||
|
await verifyCredentials($);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default isStillVerified;
|
@@ -0,0 +1,14 @@
|
|||||||
|
const verifyCredentials = async ($) => {
|
||||||
|
await $.http.get(`/api/v4/projects?key=${$.auth.data.authToken}`, {
|
||||||
|
additionalProperties: {
|
||||||
|
skipAddingAuthToken: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await $.auth.set({
|
||||||
|
screenName: $.auth.data.screenName,
|
||||||
|
authToken: $.auth.data.authToken,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default verifyCredentials;
|
10
packages/backend/src/apps/airbrake/common/add-auth-token.js
Normal file
10
packages/backend/src/apps/airbrake/common/add-auth-token.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
const addAuthToken = ($, requestConfig) => {
|
||||||
|
if (requestConfig.additionalProperties?.skipAddingAuthToken)
|
||||||
|
return requestConfig;
|
||||||
|
|
||||||
|
requestConfig.url = requestConfig.url + `?key=${$.auth.data.authToken}`;
|
||||||
|
|
||||||
|
return requestConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default addAuthToken;
|
11
packages/backend/src/apps/airbrake/common/set-base-url.js
Normal file
11
packages/backend/src/apps/airbrake/common/set-base-url.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
const setBaseUrl = ($, requestConfig) => {
|
||||||
|
const subdomain = $.auth.data.instanceUrl;
|
||||||
|
|
||||||
|
if (subdomain) {
|
||||||
|
requestConfig.baseURL = `https://${subdomain}.airbrake.io`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return requestConfig;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default setBaseUrl;
|
3
packages/backend/src/apps/airbrake/dynamic-data/index.js
Normal file
3
packages/backend/src/apps/airbrake/dynamic-data/index.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import listProjects from './list-projects/index.js';
|
||||||
|
|
||||||
|
export default [listProjects];
|
@@ -0,0 +1,23 @@
|
|||||||
|
export default {
|
||||||
|
name: 'List projects',
|
||||||
|
key: 'listProjects',
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const projects = {
|
||||||
|
data: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
const { data } = await $.http.get('/api/v4/projects');
|
||||||
|
|
||||||
|
if (data.projects.length) {
|
||||||
|
for (const project of data.projects) {
|
||||||
|
projects.data.push({
|
||||||
|
value: project.id,
|
||||||
|
name: project.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return projects;
|
||||||
|
},
|
||||||
|
};
|
21
packages/backend/src/apps/airbrake/index.js
Normal file
21
packages/backend/src/apps/airbrake/index.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import defineApp from '../../helpers/define-app.js';
|
||||||
|
import setBaseUrl from './common/set-base-url.js';
|
||||||
|
import auth from './auth/index.js';
|
||||||
|
import addAuthToken from './common/add-auth-token.js';
|
||||||
|
import triggers from './triggers/index.js';
|
||||||
|
import dynamicData from './dynamic-data/index.js';
|
||||||
|
|
||||||
|
export default defineApp({
|
||||||
|
name: 'Airbrake',
|
||||||
|
key: 'airbrake',
|
||||||
|
iconUrl: '{BASE_URL}/apps/airbrake/assets/favicon.svg',
|
||||||
|
authDocUrl: 'https://automatisch.io/docs/apps/airbrake/connection',
|
||||||
|
supportsConnections: true,
|
||||||
|
baseUrl: 'https://www.airbrake.io',
|
||||||
|
apiBaseUrl: '',
|
||||||
|
primaryColor: 'f58c54',
|
||||||
|
beforeRequest: [setBaseUrl, addAuthToken],
|
||||||
|
auth,
|
||||||
|
triggers,
|
||||||
|
dynamicData,
|
||||||
|
});
|
3
packages/backend/src/apps/airbrake/triggers/index.js
Normal file
3
packages/backend/src/apps/airbrake/triggers/index.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import newErrors from './new-errors/index.js';
|
||||||
|
|
||||||
|
export default [newErrors];
|
@@ -0,0 +1,66 @@
|
|||||||
|
//import { URLSearchParams } from 'node:url';
|
||||||
|
import defineTrigger from '../../../../helpers/define-trigger.js';
|
||||||
|
|
||||||
|
export default defineTrigger({
|
||||||
|
name: 'New errors',
|
||||||
|
key: 'newErrors',
|
||||||
|
pollInterval: 15,
|
||||||
|
description: 'Triggers when a new error occurs.',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
label: 'Project',
|
||||||
|
key: 'projectId',
|
||||||
|
type: 'dropdown',
|
||||||
|
required: true,
|
||||||
|
description: '',
|
||||||
|
variables: true,
|
||||||
|
source: {
|
||||||
|
type: 'query',
|
||||||
|
name: 'getDynamicData',
|
||||||
|
arguments: [
|
||||||
|
{
|
||||||
|
name: 'key',
|
||||||
|
value: 'listProjects',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
async run($) {
|
||||||
|
const projectId = $.step.parameters.projectId;
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
limit: 100,
|
||||||
|
page: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let next = false;
|
||||||
|
do {
|
||||||
|
const { data } = await $.http.get(
|
||||||
|
`/api/v4/projects/${projectId}/groups`,
|
||||||
|
{ params }
|
||||||
|
);
|
||||||
|
|
||||||
|
if (data.count > params.limit) {
|
||||||
|
params.page = params.page + 1;
|
||||||
|
next = true;
|
||||||
|
} else {
|
||||||
|
next = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data?.groups?.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const group of data.groups) {
|
||||||
|
$.pushTriggerItem({
|
||||||
|
raw: group,
|
||||||
|
meta: {
|
||||||
|
internalId: group.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} while (next);
|
||||||
|
},
|
||||||
|
});
|
@@ -1,241 +0,0 @@
|
|||||||
import defineAction from '../../../../helpers/define-action.js';
|
|
||||||
|
|
||||||
export default defineAction({
|
|
||||||
name: 'Generate document',
|
|
||||||
key: 'generateDocument',
|
|
||||||
description: 'Creates a new document.',
|
|
||||||
arguments: [
|
|
||||||
{
|
|
||||||
label: 'Workspace',
|
|
||||||
key: 'workspaceId',
|
|
||||||
type: 'dropdown',
|
|
||||||
required: true,
|
|
||||||
description: '',
|
|
||||||
variables: true,
|
|
||||||
source: {
|
|
||||||
type: 'query',
|
|
||||||
name: 'getDynamicData',
|
|
||||||
arguments: [
|
|
||||||
{
|
|
||||||
name: 'key',
|
|
||||||
value: 'listWorkspaces',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Template',
|
|
||||||
key: 'templateId',
|
|
||||||
type: 'dropdown',
|
|
||||||
required: false,
|
|
||||||
depensOn: ['parameters.workspaceId'],
|
|
||||||
description: '',
|
|
||||||
variables: true,
|
|
||||||
source: {
|
|
||||||
type: 'query',
|
|
||||||
name: 'getDynamicData',
|
|
||||||
arguments: [
|
|
||||||
{
|
|
||||||
name: 'key',
|
|
||||||
value: 'listTemplates',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'parameters.workspaceId',
|
|
||||||
value: '{parameters.workspaceId}',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Use a Custom Json Structure?',
|
|
||||||
key: 'useCustomJsonStructure',
|
|
||||||
type: 'dropdown',
|
|
||||||
required: true,
|
|
||||||
description:
|
|
||||||
'Please indicate "yes" if you would rather create a full JSON payload instead of relying on Automatisch mapping for the Document data.',
|
|
||||||
variables: true,
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: 'Yes',
|
|
||||||
value: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'No',
|
|
||||||
value: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
additionalFields: {
|
|
||||||
type: 'query',
|
|
||||||
name: 'getDynamicFields',
|
|
||||||
arguments: [
|
|
||||||
{
|
|
||||||
name: 'key',
|
|
||||||
value: 'listDocumentData',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'parameters.useCustomJsonStructure',
|
|
||||||
value: '{parameters.useCustomJsonStructure}',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Add Line Items?',
|
|
||||||
key: 'addLineItems',
|
|
||||||
type: 'dropdown',
|
|
||||||
required: true,
|
|
||||||
description:
|
|
||||||
'Choose "yes" to include information for Line Items (such as in an invoice).',
|
|
||||||
variables: true,
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: 'Yes',
|
|
||||||
value: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'No',
|
|
||||||
value: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
additionalFields: {
|
|
||||||
type: 'query',
|
|
||||||
name: 'getDynamicFields',
|
|
||||||
arguments: [
|
|
||||||
{
|
|
||||||
name: 'key',
|
|
||||||
value: 'listLineItems',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'parameters.addLineItems',
|
|
||||||
value: '{parameters.addLineItems}',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Custom Filename',
|
|
||||||
key: 'customFilename',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
description:
|
|
||||||
'You have the option to define a custom filename for generated documents. If left blank, a random value will be assigned.',
|
|
||||||
variables: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Meta Data',
|
|
||||||
key: 'metaData',
|
|
||||||
type: 'dynamic',
|
|
||||||
required: false,
|
|
||||||
description:
|
|
||||||
'Extra information appended to the generated Document but not accessible within its Template.',
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
label: 'Key',
|
|
||||||
key: 'metaDataKey',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
description: '',
|
|
||||||
variables: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Value',
|
|
||||||
key: 'metaDataValue',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
description: '',
|
|
||||||
variables: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
async run($) {
|
|
||||||
const {
|
|
||||||
templateId,
|
|
||||||
useCustomJsonStructure,
|
|
||||||
customJsonPayload,
|
|
||||||
customFilename,
|
|
||||||
addLineItems,
|
|
||||||
lineItems,
|
|
||||||
documentData,
|
|
||||||
metaData,
|
|
||||||
} = $.step.parameters;
|
|
||||||
let payload = {};
|
|
||||||
let meta = {};
|
|
||||||
|
|
||||||
const documentDataObject = documentData.reduce((result, entry) => {
|
|
||||||
const key = entry.documentDataKey?.toLowerCase();
|
|
||||||
const value = entry.documentDataValue;
|
|
||||||
|
|
||||||
if (key && value) {
|
|
||||||
return {
|
|
||||||
...result,
|
|
||||||
[entry.documentDataKey?.toLowerCase()]: entry.documentDataValue,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
const lineItemsObject = lineItems.reduce((result, entry) => {
|
|
||||||
const key = entry.lineItemKey?.toLowerCase();
|
|
||||||
const value = entry.lineItemValue;
|
|
||||||
|
|
||||||
if (key && value) {
|
|
||||||
return {
|
|
||||||
...result,
|
|
||||||
[entry.lineItemKey?.toLowerCase()]: entry.lineItemValue,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
const metaDataObject = metaData.reduce((result, entry) => {
|
|
||||||
const key = entry.metaDataKey?.toLowerCase();
|
|
||||||
const value = entry.metaDataValue;
|
|
||||||
|
|
||||||
if (key && value) {
|
|
||||||
return {
|
|
||||||
...result,
|
|
||||||
[entry.metaDataKey?.toLowerCase()]: entry.metaDataValue,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
if (metaDataObject) {
|
|
||||||
meta = metaDataObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (customFilename) {
|
|
||||||
meta._filename = customFilename;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (useCustomJsonStructure) {
|
|
||||||
payload = JSON.parse(customJsonPayload);
|
|
||||||
} else {
|
|
||||||
payload = documentDataObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addLineItems) {
|
|
||||||
payload.lineItems = [lineItemsObject];
|
|
||||||
}
|
|
||||||
|
|
||||||
const body = {
|
|
||||||
document: {
|
|
||||||
document_template_id: templateId,
|
|
||||||
meta: JSON.stringify(meta),
|
|
||||||
payload: JSON.stringify(payload),
|
|
||||||
status: 'pending',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const { data } = await $.http.post('/v1/documents', body);
|
|
||||||
|
|
||||||
$.setActionItem({
|
|
||||||
raw: data,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
@@ -1,3 +0,0 @@
|
|||||||
import generateDocument from './generate-document/index.js';
|
|
||||||
|
|
||||||
export default [generateDocument];
|
|
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 112 KiB |
@@ -1,21 +0,0 @@
|
|||||||
import verifyCredentials from './verify-credentials.js';
|
|
||||||
import isStillVerified from './is-still-verified.js';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
key: 'apiKey',
|
|
||||||
label: 'API Key',
|
|
||||||
type: 'string',
|
|
||||||
required: true,
|
|
||||||
readOnly: false,
|
|
||||||
value: null,
|
|
||||||
placeholder: null,
|
|
||||||
description: 'PDFMonkey API secret key of your account.',
|
|
||||||
clickToCopy: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
verifyCredentials,
|
|
||||||
isStillVerified,
|
|
||||||
};
|
|
@@ -1,8 +0,0 @@
|
|||||||
import getCurrentUser from '../common/get-current-user.js';
|
|
||||||
|
|
||||||
const isStillVerified = async ($) => {
|
|
||||||
const currentUser = await getCurrentUser($);
|
|
||||||
return !!currentUser.id;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default isStillVerified;
|
|
@@ -1,15 +0,0 @@
|
|||||||
import getCurrentUser from '../common/get-current-user.js';
|
|
||||||
|
|
||||||
const verifyCredentials = async ($) => {
|
|
||||||
const currentUser = await getCurrentUser($);
|
|
||||||
const screenName = [currentUser.desired_name, currentUser.email]
|
|
||||||
.filter(Boolean)
|
|
||||||
.join(' @ ');
|
|
||||||
|
|
||||||
await $.auth.set({
|
|
||||||
screenName,
|
|
||||||
apiKey: $.auth.data.apiKey,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
export default verifyCredentials;
|
|
@@ -1,9 +0,0 @@
|
|||||||
const addAuthHeader = ($, requestConfig) => {
|
|
||||||
if ($.auth.data?.apiKey) {
|
|
||||||
requestConfig.headers.Authorization = `Bearer ${$.auth.data.apiKey}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return requestConfig;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default addAuthHeader;
|
|
@@ -1,8 +0,0 @@
|
|||||||
const getCurrentUser = async ($) => {
|
|
||||||
const response = await $.http.get('/v1/current_user');
|
|
||||||
const currentUser = response.data.current_user;
|
|
||||||
|
|
||||||
return currentUser;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default getCurrentUser;
|
|
@@ -1,4 +0,0 @@
|
|||||||
import listTemplates from './list-templates/index.js';
|
|
||||||
import listWorkspaces from './list-workspaces/index.js';
|
|
||||||
|
|
||||||
export default [listTemplates, listWorkspaces];
|
|
@@ -1,39 +0,0 @@
|
|||||||
export default {
|
|
||||||
name: 'List templates',
|
|
||||||
key: 'listTemplates',
|
|
||||||
|
|
||||||
async run($) {
|
|
||||||
const templates = {
|
|
||||||
data: [],
|
|
||||||
};
|
|
||||||
const workspaceId = $.step.parameters.workspaceId;
|
|
||||||
let next = false;
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
page: 'all',
|
|
||||||
'q[workspace_id]': workspaceId,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!workspaceId) {
|
|
||||||
return templates;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
const { data } = await $.http.get('/v1/document_template_cards', params);
|
|
||||||
next = data.meta.next_page;
|
|
||||||
|
|
||||||
if (!data?.document_template_cards?.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const template of data.document_template_cards) {
|
|
||||||
templates.data.push({
|
|
||||||
value: template.id,
|
|
||||||
name: template.identifier,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} while (next);
|
|
||||||
|
|
||||||
return templates;
|
|
||||||
},
|
|
||||||
};
|
|
@@ -1,29 +0,0 @@
|
|||||||
export default {
|
|
||||||
name: 'List workspaces',
|
|
||||||
key: 'listWorkspaces',
|
|
||||||
|
|
||||||
async run($) {
|
|
||||||
const workspaces = {
|
|
||||||
data: [],
|
|
||||||
};
|
|
||||||
let next = false;
|
|
||||||
|
|
||||||
do {
|
|
||||||
const { data } = await $.http.get('/v1/workspace_cards');
|
|
||||||
next = data.meta.next_page;
|
|
||||||
|
|
||||||
if (!data?.workspace_cards?.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const workspace of data.workspace_cards) {
|
|
||||||
workspaces.data.push({
|
|
||||||
value: workspace.id,
|
|
||||||
name: workspace.identifier,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} while (next);
|
|
||||||
|
|
||||||
return workspaces;
|
|
||||||
},
|
|
||||||
};
|
|
@@ -1,4 +0,0 @@
|
|||||||
import listDocumentData from './list-document-data/index.js';
|
|
||||||
import listLineItems from './list-line-items/index.js';
|
|
||||||
|
|
||||||
export default [listDocumentData, listLineItems];
|
|
@@ -1,48 +0,0 @@
|
|||||||
export default {
|
|
||||||
name: 'List document data',
|
|
||||||
key: 'listDocumentData',
|
|
||||||
|
|
||||||
async run($) {
|
|
||||||
if ($.step.parameters.useCustomJsonStructure) {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
label: 'Data for the Document (JSON Payload)',
|
|
||||||
key: 'customJsonPayload',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
description:
|
|
||||||
'Use the JSON format { "firstname": "John", "lastname": "Doe" }.',
|
|
||||||
variables: true,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
label: 'Data for the Document',
|
|
||||||
key: 'documentData',
|
|
||||||
type: 'dynamic',
|
|
||||||
required: false,
|
|
||||||
description: '',
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
label: 'Key',
|
|
||||||
key: 'documentDataKey',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
description: '',
|
|
||||||
variables: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Value',
|
|
||||||
key: 'documentDataValue',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
description: '',
|
|
||||||
variables: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
@@ -1,37 +0,0 @@
|
|||||||
export default {
|
|
||||||
name: 'List line items',
|
|
||||||
key: 'listLineItems',
|
|
||||||
|
|
||||||
async run($) {
|
|
||||||
if ($.step.parameters.addLineItems) {
|
|
||||||
return [
|
|
||||||
{
|
|
||||||
label: 'Line Items',
|
|
||||||
key: 'lineItems',
|
|
||||||
type: 'dynamic',
|
|
||||||
required: false,
|
|
||||||
description:
|
|
||||||
'Data for a single item. Available as "lineItems" in your PDFMonkey Template.',
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
label: 'Key',
|
|
||||||
key: 'lineItemKey',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
description: '',
|
|
||||||
variables: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Value',
|
|
||||||
key: 'lineItemValue',
|
|
||||||
type: 'string',
|
|
||||||
required: false,
|
|
||||||
description: '',
|
|
||||||
variables: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
};
|
|
@@ -1,24 +0,0 @@
|
|||||||
import defineApp from '../../helpers/define-app.js';
|
|
||||||
import addAuthHeader from './common/add-auth-header.js';
|
|
||||||
import auth from './auth/index.js';
|
|
||||||
import triggers from './triggers/index.js';
|
|
||||||
import dynamicData from './dynamic-data/index.js';
|
|
||||||
import actions from './actions/index.js';
|
|
||||||
import dynamicFields from './dynamic-fields/index.js';
|
|
||||||
|
|
||||||
export default defineApp({
|
|
||||||
name: 'PDFMonkey',
|
|
||||||
key: 'pdf-monkey',
|
|
||||||
iconUrl: '{BASE_URL}/apps/pdf-monkey/assets/favicon.svg',
|
|
||||||
authDocUrl: 'https://automatisch.io/docs/apps/pdf-monkey/connection',
|
|
||||||
supportsConnections: true,
|
|
||||||
baseUrl: 'https://pdfmonkey.io',
|
|
||||||
apiBaseUrl: 'https://api.pdfmonkey.io/api',
|
|
||||||
primaryColor: '376794',
|
|
||||||
beforeRequest: [addAuthHeader],
|
|
||||||
auth,
|
|
||||||
triggers,
|
|
||||||
dynamicData,
|
|
||||||
actions,
|
|
||||||
dynamicFields,
|
|
||||||
});
|
|
@@ -1,99 +0,0 @@
|
|||||||
import defineTrigger from '../../../../helpers/define-trigger.js';
|
|
||||||
|
|
||||||
export default defineTrigger({
|
|
||||||
name: 'Documents Generated',
|
|
||||||
key: 'documentsGenerated',
|
|
||||||
pollInterval: 15,
|
|
||||||
description:
|
|
||||||
'Triggers upon the successful completion of document generation.',
|
|
||||||
arguments: [
|
|
||||||
{
|
|
||||||
label: 'Workspace',
|
|
||||||
key: 'workspaceId',
|
|
||||||
type: 'dropdown',
|
|
||||||
required: true,
|
|
||||||
description: '',
|
|
||||||
variables: true,
|
|
||||||
source: {
|
|
||||||
type: 'query',
|
|
||||||
name: 'getDynamicData',
|
|
||||||
arguments: [
|
|
||||||
{
|
|
||||||
name: 'key',
|
|
||||||
value: 'listWorkspaces',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Templates',
|
|
||||||
key: 'templateIds',
|
|
||||||
type: 'dynamic',
|
|
||||||
required: false,
|
|
||||||
description: 'Apply this trigger exclusively for particular templates.',
|
|
||||||
fields: [
|
|
||||||
{
|
|
||||||
label: 'Template',
|
|
||||||
key: 'templateId',
|
|
||||||
type: 'dropdown',
|
|
||||||
required: false,
|
|
||||||
depensOn: ['parameters.workspaceId'],
|
|
||||||
description: '',
|
|
||||||
variables: true,
|
|
||||||
source: {
|
|
||||||
type: 'query',
|
|
||||||
name: 'getDynamicData',
|
|
||||||
arguments: [
|
|
||||||
{
|
|
||||||
name: 'key',
|
|
||||||
value: 'listTemplates',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'parameters.workspaceId',
|
|
||||||
value: '{parameters.workspaceId}',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
async run($) {
|
|
||||||
const workspaceId = $.step.parameters.workspaceId;
|
|
||||||
const templateIds = $.step.parameters.templateIds;
|
|
||||||
const allTemplates = templateIds
|
|
||||||
.map((templateId) => templateId.templateId)
|
|
||||||
.join(',');
|
|
||||||
|
|
||||||
const params = {
|
|
||||||
'page[size]': 100,
|
|
||||||
'q[workspace_id]': workspaceId,
|
|
||||||
'q[status]': 'success',
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!templateIds.length) {
|
|
||||||
params['q[document_template_id]'] = allTemplates;
|
|
||||||
}
|
|
||||||
|
|
||||||
let next = false;
|
|
||||||
do {
|
|
||||||
const { data } = await $.http.get('/v1/document_cards', { params });
|
|
||||||
|
|
||||||
if (!data?.document_cards?.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
next = data.meta.next_page;
|
|
||||||
|
|
||||||
for (const document of data.document_cards) {
|
|
||||||
$.pushTriggerItem({
|
|
||||||
raw: document,
|
|
||||||
meta: {
|
|
||||||
internalId: document.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} while (next);
|
|
||||||
},
|
|
||||||
});
|
|
@@ -1,3 +0,0 @@
|
|||||||
import documentsGenerated from './documents-generated/index.js';
|
|
||||||
|
|
||||||
export default [documentsGenerated];
|
|
@@ -1,10 +0,0 @@
|
|||||||
import { renderObject } from '../../../../../helpers/renderer.js';
|
|
||||||
import SamlAuthProvider from '../../../../../models/saml-auth-provider.ee.js';
|
|
||||||
|
|
||||||
export default async (request, response) => {
|
|
||||||
const samlAuthProvider = await SamlAuthProvider.query()
|
|
||||||
.findById(request.params.samlAuthProviderId)
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
renderObject(response, samlAuthProvider);
|
|
||||||
};
|
|
@@ -1,34 +0,0 @@
|
|||||||
import { vi, describe, it, expect, beforeEach } from 'vitest';
|
|
||||||
import request from 'supertest';
|
|
||||||
import app from '../../../../../app.js';
|
|
||||||
import createAuthTokenByUserId from '../../../../../helpers/create-auth-token-by-user-id.js';
|
|
||||||
import { createRole } from '../../../../../../test/factories/role.js';
|
|
||||||
import { createUser } from '../../../../../../test/factories/user.js';
|
|
||||||
import { createSamlAuthProvider } from '../../../../../../test/factories/saml-auth-provider.ee.js';
|
|
||||||
import getSamlAuthProviderMock from '../../../../../../test/mocks/rest/api/v1/saml-auth-providers/get-saml-auth-provider.ee.js';
|
|
||||||
import * as license from '../../../../../helpers/license.ee.js';
|
|
||||||
|
|
||||||
describe('GET /api/v1/admin/saml-auth-provider/:samlAuthProviderId', () => {
|
|
||||||
let samlAuthProvider, currentUser, token;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
const role = await createRole({ key: 'admin' });
|
|
||||||
currentUser = await createUser({ roleId: role.id });
|
|
||||||
samlAuthProvider = await createSamlAuthProvider();
|
|
||||||
|
|
||||||
token = createAuthTokenByUserId(currentUser.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return saml auth provider with specified id', async () => {
|
|
||||||
vi.spyOn(license, 'hasValidLicense').mockResolvedValue(true);
|
|
||||||
|
|
||||||
const response = await request(app)
|
|
||||||
.get(`/api/v1/admin/saml-auth-providers/${samlAuthProvider.id}`)
|
|
||||||
.set('Authorization', token)
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
const expectedPayload = await getSamlAuthProviderMock(samlAuthProvider);
|
|
||||||
|
|
||||||
expect(response.body).toEqual(expectedPayload);
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,11 +0,0 @@
|
|||||||
import { renderObject } from '../../../../../helpers/renderer.js';
|
|
||||||
import SamlAuthProvider from '../../../../../models/saml-auth-provider.ee.js';
|
|
||||||
|
|
||||||
export default async (request, response) => {
|
|
||||||
const samlAuthProviders = await SamlAuthProvider.query().orderBy(
|
|
||||||
'created_at',
|
|
||||||
'desc'
|
|
||||||
);
|
|
||||||
|
|
||||||
renderObject(response, samlAuthProviders);
|
|
||||||
};
|
|
@@ -1,39 +0,0 @@
|
|||||||
import { vi, describe, it, expect, beforeEach } from 'vitest';
|
|
||||||
import request from 'supertest';
|
|
||||||
import app from '../../../../../app.js';
|
|
||||||
import createAuthTokenByUserId from '../../../../../helpers/create-auth-token-by-user-id.js';
|
|
||||||
import { createRole } from '../../../../../../test/factories/role.js';
|
|
||||||
import { createUser } from '../../../../../../test/factories/user.js';
|
|
||||||
import { createSamlAuthProvider } from '../../../../../../test/factories/saml-auth-provider.ee.js';
|
|
||||||
import getSamlAuthProvidersMock from '../../../../../../test/mocks/rest/api/v1/saml-auth-providers/get-saml-auth-providers.ee.js';
|
|
||||||
import * as license from '../../../../../helpers/license.ee.js';
|
|
||||||
|
|
||||||
describe('GET /api/v1/admin/saml-auth-providers', () => {
|
|
||||||
let samlAuthProviderOne, samlAuthProviderTwo, currentUser, token;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
const role = await createRole({ key: 'admin' });
|
|
||||||
currentUser = await createUser({ roleId: role.id });
|
|
||||||
|
|
||||||
samlAuthProviderOne = await createSamlAuthProvider();
|
|
||||||
samlAuthProviderTwo = await createSamlAuthProvider();
|
|
||||||
|
|
||||||
token = createAuthTokenByUserId(currentUser.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return saml auth providers', async () => {
|
|
||||||
vi.spyOn(license, 'hasValidLicense').mockResolvedValue(true);
|
|
||||||
|
|
||||||
const response = await request(app)
|
|
||||||
.get('/api/v1/admin/saml-auth-providers')
|
|
||||||
.set('Authorization', token)
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
const expectedPayload = await getSamlAuthProvidersMock([
|
|
||||||
samlAuthProviderTwo,
|
|
||||||
samlAuthProviderOne,
|
|
||||||
]);
|
|
||||||
|
|
||||||
expect(response.body).toEqual(expectedPayload);
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,6 +0,0 @@
|
|||||||
import appConfig from '../../../../config/app.js';
|
|
||||||
import { renderObject } from '../../../../helpers/renderer.js';
|
|
||||||
|
|
||||||
export default async (request, response) => {
|
|
||||||
renderObject(response, { version: appConfig.version });
|
|
||||||
};
|
|
@@ -1,26 +0,0 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
|
||||||
import request from 'supertest';
|
|
||||||
import app from '../../../../app.js';
|
|
||||||
|
|
||||||
describe('GET /api/v1/automatisch/version', () => {
|
|
||||||
it('should return Automatisch version', async () => {
|
|
||||||
const response = await request(app)
|
|
||||||
.get('/api/v1/automatisch/version')
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
const expectedPayload = {
|
|
||||||
data: {
|
|
||||||
version: '0.10.0',
|
|
||||||
},
|
|
||||||
meta: {
|
|
||||||
count: 1,
|
|
||||||
currentPage: null,
|
|
||||||
isArray: false,
|
|
||||||
totalPages: null,
|
|
||||||
type: 'Object',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(response.body).toEqual(expectedPayload);
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,5 +0,0 @@
|
|||||||
import { renderObject } from '../../../../helpers/renderer.js';
|
|
||||||
|
|
||||||
export default async (request, response) => {
|
|
||||||
renderObject(response, request.currentUser);
|
|
||||||
};
|
|
@@ -1,26 +0,0 @@
|
|||||||
import { describe, it, expect, beforeEach } from 'vitest';
|
|
||||||
import request from 'supertest';
|
|
||||||
import app from '../../../../app.js';
|
|
||||||
import createAuthTokenByUserId from '../../../../helpers/create-auth-token-by-user-id';
|
|
||||||
import { createUser } from '../../../../../test/factories/user';
|
|
||||||
import getCurrentUserMock from '../../../../../test/mocks/rest/api/v1/users/get-current-user';
|
|
||||||
|
|
||||||
describe('GET /api/v1/users/me', () => {
|
|
||||||
let role, currentUser, token;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
currentUser = await createUser();
|
|
||||||
role = await currentUser.$relatedQuery('role');
|
|
||||||
token = createAuthTokenByUserId(currentUser.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return current user info', async () => {
|
|
||||||
const response = await request(app)
|
|
||||||
.get('/api/v1/users/me')
|
|
||||||
.set('Authorization', token)
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
const expectedPayload = getCurrentUserMock(currentUser, role);
|
|
||||||
expect(response.body).toEqual(expectedPayload);
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,12 +0,0 @@
|
|||||||
import { renderObject } from '../../../../helpers/renderer.js';
|
|
||||||
|
|
||||||
export default async (request, response) => {
|
|
||||||
const inTrial = await request.currentUser.inTrial();
|
|
||||||
|
|
||||||
const trialInfo = {
|
|
||||||
inTrial,
|
|
||||||
expireAt: request.currentUser.trialExpiryDate,
|
|
||||||
};
|
|
||||||
|
|
||||||
renderObject(response, trialInfo);
|
|
||||||
};
|
|
@@ -1,38 +0,0 @@
|
|||||||
import { vi, describe, it, expect, beforeEach } from 'vitest';
|
|
||||||
import request from 'supertest';
|
|
||||||
import app from '../../../../app.js';
|
|
||||||
import createAuthTokenByUserId from '../../../../helpers/create-auth-token-by-user-id.js';
|
|
||||||
import { createUser } from '../../../../../test/factories/user.js';
|
|
||||||
import getUserTrialMock from '../../../../../test/mocks/rest/api/v1/users/get-user-trial.js';
|
|
||||||
import appConfig from '../../../../config/app.js';
|
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import User from '../../../../models/user.js';
|
|
||||||
|
|
||||||
describe('GET /api/v1/users/:userId/trial', () => {
|
|
||||||
let user, token;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
const trialExpiryDate = DateTime.now().plus({ days: 30 }).toISODate();
|
|
||||||
user = await createUser({ trialExpiryDate });
|
|
||||||
token = createAuthTokenByUserId(user.id);
|
|
||||||
|
|
||||||
vi.spyOn(appConfig, 'isCloud', 'get').mockReturnValue(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('should return in trial, active subscription and expire at info', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
vi.spyOn(User.prototype, 'inTrial').mockResolvedValue(false);
|
|
||||||
vi.spyOn(User.prototype, 'hasActiveSubscription').mockResolvedValue(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return null', async () => {
|
|
||||||
const response = await request(app)
|
|
||||||
.get(`/api/v1/users/${user.id}/trial`)
|
|
||||||
.set('Authorization', token)
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
const expectedResponsePayload = await getUserTrialMock(user);
|
|
||||||
expect(response.body).toEqual(expectedResponsePayload);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,16 +0,0 @@
|
|||||||
import { renderObject } from '../../../../helpers/renderer.js';
|
|
||||||
import User from '../../../../models/user.js';
|
|
||||||
|
|
||||||
export default async (request, response) => {
|
|
||||||
const user = await User.query()
|
|
||||||
.leftJoinRelated({
|
|
||||||
role: true,
|
|
||||||
})
|
|
||||||
.withGraphFetched({
|
|
||||||
role: true,
|
|
||||||
})
|
|
||||||
.findById(request.params.userId)
|
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
renderObject(response, user);
|
|
||||||
};
|
|
@@ -1,36 +0,0 @@
|
|||||||
import { describe, it, expect, beforeEach } from 'vitest';
|
|
||||||
import request from 'supertest';
|
|
||||||
import app from '../../../../app.js';
|
|
||||||
import createAuthTokenByUserId from '../../../../helpers/create-auth-token-by-user-id';
|
|
||||||
import { createUser } from '../../../../../test/factories/user';
|
|
||||||
import { createPermission } from '../../../../../test/factories/permission';
|
|
||||||
import getUserMock from '../../../../../test/mocks/rest/api/v1/users/get-user';
|
|
||||||
|
|
||||||
describe('GET /api/v1/users/:userId', () => {
|
|
||||||
let currentUser, currentUserRole, anotherUser, anotherUserRole, token;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
currentUser = await createUser();
|
|
||||||
anotherUser = await createUser();
|
|
||||||
currentUserRole = await currentUser.$relatedQuery('role');
|
|
||||||
anotherUserRole = await anotherUser.$relatedQuery('role');
|
|
||||||
|
|
||||||
await createPermission({
|
|
||||||
roleId: currentUserRole.id,
|
|
||||||
action: 'read',
|
|
||||||
subject: 'User',
|
|
||||||
});
|
|
||||||
|
|
||||||
token = createAuthTokenByUserId(currentUser.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return specified user info', async () => {
|
|
||||||
const response = await request(app)
|
|
||||||
.get(`/api/v1/users/${anotherUser.id}`)
|
|
||||||
.set('Authorization', token)
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
const expectedPayload = getUserMock(anotherUser, anotherUserRole);
|
|
||||||
expect(response.body).toEqual(expectedPayload);
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,18 +0,0 @@
|
|||||||
import { renderObject } from '../../../../helpers/renderer.js';
|
|
||||||
import User from '../../../../models/user.js';
|
|
||||||
import paginateRest from '../../../../helpers/pagination-rest.js';
|
|
||||||
|
|
||||||
export default async (request, response) => {
|
|
||||||
const usersQuery = User.query()
|
|
||||||
.leftJoinRelated({
|
|
||||||
role: true,
|
|
||||||
})
|
|
||||||
.withGraphFetched({
|
|
||||||
role: true,
|
|
||||||
})
|
|
||||||
.orderBy('full_name', 'asc');
|
|
||||||
|
|
||||||
const users = await paginateRest(usersQuery, request.query.page);
|
|
||||||
|
|
||||||
renderObject(response, users);
|
|
||||||
};
|
|
@@ -1,56 +0,0 @@
|
|||||||
import { describe, it, expect, beforeEach } from 'vitest';
|
|
||||||
import request from 'supertest';
|
|
||||||
import app from '../../../../app';
|
|
||||||
import createAuthTokenByUserId from '../../../../helpers/create-auth-token-by-user-id';
|
|
||||||
import { createRole } from '../../../../../test/factories/role';
|
|
||||||
import { createPermission } from '../../../../../test/factories/permission';
|
|
||||||
import { createUser } from '../../../../../test/factories/user';
|
|
||||||
import getUsersMock from '../../../../../test/mocks/rest/api/v1/users/get-users';
|
|
||||||
|
|
||||||
describe('GET /api/v1/users', () => {
|
|
||||||
let currentUser, currentUserRole, anotherUser, anotherUserRole, token;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
currentUserRole = await createRole({
|
|
||||||
key: 'currentUser',
|
|
||||||
name: 'Current user role',
|
|
||||||
});
|
|
||||||
|
|
||||||
await createPermission({
|
|
||||||
action: 'read',
|
|
||||||
subject: 'User',
|
|
||||||
roleId: currentUserRole.id,
|
|
||||||
});
|
|
||||||
|
|
||||||
currentUser = await createUser({
|
|
||||||
roleId: currentUserRole.id,
|
|
||||||
fullName: 'Current User',
|
|
||||||
});
|
|
||||||
|
|
||||||
anotherUserRole = await createRole({
|
|
||||||
key: 'anotherUser',
|
|
||||||
name: 'Another user role',
|
|
||||||
});
|
|
||||||
|
|
||||||
anotherUser = await createUser({
|
|
||||||
roleId: anotherUserRole.id,
|
|
||||||
fullName: 'Another User',
|
|
||||||
});
|
|
||||||
|
|
||||||
token = createAuthTokenByUserId(currentUser.id);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return users data', async () => {
|
|
||||||
const response = await request(app)
|
|
||||||
.get('/api/v1/users')
|
|
||||||
.set('Authorization', token)
|
|
||||||
.expect(200);
|
|
||||||
|
|
||||||
const expectedResponsePayload = await getUsersMock(
|
|
||||||
[anotherUser, currentUser],
|
|
||||||
[anotherUserRole, currentUserRole]
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(response.body).toEqual(expectedResponsePayload);
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,3 +0,0 @@
|
|||||||
export default async (request, response) => {
|
|
||||||
response.status(200).end();
|
|
||||||
};
|
|
@@ -1,9 +0,0 @@
|
|||||||
import { describe, it } from 'vitest';
|
|
||||||
import request from 'supertest';
|
|
||||||
import app from '../../app.js';
|
|
||||||
|
|
||||||
describe('GET /healthcheck', () => {
|
|
||||||
it('should return 200 response with version data', async () => {
|
|
||||||
await request(app).get('/healthcheck').expect(200);
|
|
||||||
});
|
|
||||||
});
|
|
@@ -20,8 +20,7 @@ export const isAuthenticated = async (_parent, _args, req) => {
|
|||||||
.withGraphFetched({
|
.withGraphFetched({
|
||||||
role: true,
|
role: true,
|
||||||
permissions: true,
|
permissions: true,
|
||||||
})
|
});
|
||||||
.throwIfNotFound();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -29,14 +28,6 @@ export const isAuthenticated = async (_parent, _args, req) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const authenticateUser = async (request, response, next) => {
|
|
||||||
if (await isAuthenticated(null, null, request)) {
|
|
||||||
next();
|
|
||||||
} else {
|
|
||||||
return response.status(401).end();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const isAuthenticatedRule = rule()(isAuthenticated);
|
const isAuthenticatedRule = rule()(isAuthenticated);
|
||||||
|
|
||||||
export const authenticationRules = {
|
export const authenticationRules = {
|
||||||
|
@@ -1,8 +1,11 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect, vi } from 'vitest';
|
||||||
import { allow } from 'graphql-shield';
|
import { allow } from 'graphql-shield';
|
||||||
|
import jwt from 'jsonwebtoken';
|
||||||
|
import User from '../models/user.js';
|
||||||
import { isAuthenticated, authenticationRules } from './authentication.js';
|
import { isAuthenticated, authenticationRules } from './authentication.js';
|
||||||
import { createUser } from '../../test/factories/user.js';
|
|
||||||
import createAuthTokenByUserId from '../helpers/create-auth-token-by-user-id.js';
|
vi.mock('jsonwebtoken');
|
||||||
|
vi.mock('../models/user.js');
|
||||||
|
|
||||||
describe('isAuthenticated', () => {
|
describe('isAuthenticated', () => {
|
||||||
it('should return false if no token is provided', async () => {
|
it('should return false if no token is provided', async () => {
|
||||||
@@ -11,26 +14,29 @@ describe('isAuthenticated', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should return false if token is invalid', async () => {
|
it('should return false if token is invalid', async () => {
|
||||||
|
jwt.verify.mockImplementation(() => {
|
||||||
|
throw new Error('invalid token');
|
||||||
|
});
|
||||||
|
|
||||||
const req = { headers: { authorization: 'invalidToken' } };
|
const req = { headers: { authorization: 'invalidToken' } };
|
||||||
expect(await isAuthenticated(null, null, req)).toBe(false);
|
expect(await isAuthenticated(null, null, req)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return true if token is valid and there is a user', async () => {
|
it('should return true if token is valid', async () => {
|
||||||
const user = await createUser();
|
jwt.verify.mockReturnValue({ userId: '123' });
|
||||||
const token = createAuthTokenByUserId(user.id);
|
|
||||||
|
|
||||||
const req = { headers: { authorization: token } };
|
User.query.mockReturnValue({
|
||||||
|
findById: vi.fn().mockReturnValue({
|
||||||
|
leftJoinRelated: vi.fn().mockReturnThis(),
|
||||||
|
withGraphFetched: vi
|
||||||
|
.fn()
|
||||||
|
.mockResolvedValue({ id: '123', role: {}, permissions: {} }),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const req = { headers: { authorization: 'validToken' } };
|
||||||
expect(await isAuthenticated(null, null, req)).toBe(true);
|
expect(await isAuthenticated(null, null, req)).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return false if token is valid and but there is no user', async () => {
|
|
||||||
const user = await createUser();
|
|
||||||
const token = createAuthTokenByUserId(user.id);
|
|
||||||
await user.$query().delete();
|
|
||||||
|
|
||||||
const req = { headers: { authorization: token } };
|
|
||||||
expect(await isAuthenticated(null, null, req)).toBe(false);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('authentication rules', () => {
|
describe('authentication rules', () => {
|
||||||
|
@@ -1,33 +0,0 @@
|
|||||||
const authorizationList = {
|
|
||||||
'GET /api/v1/users/:userId': {
|
|
||||||
action: 'read',
|
|
||||||
subject: 'User',
|
|
||||||
},
|
|
||||||
'GET /api/v1/users/': {
|
|
||||||
action: 'read',
|
|
||||||
subject: 'User',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export const authorizeUser = async (request, response, next) => {
|
|
||||||
const currentRoute =
|
|
||||||
request.method + ' ' + request.baseUrl + request.route.path;
|
|
||||||
const currentRouteRule = authorizationList[currentRoute];
|
|
||||||
|
|
||||||
try {
|
|
||||||
request.currentUser.can(currentRouteRule.action, currentRouteRule.subject);
|
|
||||||
next();
|
|
||||||
} catch (error) {
|
|
||||||
return response.status(403).end();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export const authorizeAdmin = async (request, response, next) => {
|
|
||||||
const role = await request.currentUser.$relatedQuery('role');
|
|
||||||
|
|
||||||
if (role?.isAdmin) {
|
|
||||||
next();
|
|
||||||
} else {
|
|
||||||
return response.status(403).end();
|
|
||||||
}
|
|
||||||
};
|
|
@@ -1,11 +0,0 @@
|
|||||||
import appConfig from '../config/app.js';
|
|
||||||
|
|
||||||
export const checkIsCloud = async (request, response, next) => {
|
|
||||||
if (appConfig.isCloud) {
|
|
||||||
next();
|
|
||||||
} else {
|
|
||||||
return response.status(404).end();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default checkIsCloud;
|
|
@@ -1,9 +0,0 @@
|
|||||||
import { hasValidLicense } from './license.ee.js';
|
|
||||||
|
|
||||||
export const checkIsEnterprise = async (request, response, next) => {
|
|
||||||
if (await hasValidLicense()) {
|
|
||||||
next();
|
|
||||||
} else {
|
|
||||||
return response.status(404).end();
|
|
||||||
}
|
|
||||||
};
|
|
@@ -4,8 +4,8 @@ import appConfig from '../config/app.js';
|
|||||||
const levels = {
|
const levels = {
|
||||||
error: 0,
|
error: 0,
|
||||||
warn: 1,
|
warn: 1,
|
||||||
http: 2,
|
info: 2,
|
||||||
info: 3,
|
http: 3,
|
||||||
debug: 4,
|
debug: 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,25 +0,0 @@
|
|||||||
const paginateRest = async (query, page) => {
|
|
||||||
const pageSize = 10;
|
|
||||||
|
|
||||||
page = parseInt(page, 10);
|
|
||||||
|
|
||||||
if (isNaN(page) || page < 1) {
|
|
||||||
page = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const [records, count] = await Promise.all([
|
|
||||||
query.limit(pageSize).offset((page - 1) * pageSize),
|
|
||||||
query.resultSize(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
pageInfo: {
|
|
||||||
currentPage: page,
|
|
||||||
totalPages: Math.ceil(count / pageSize),
|
|
||||||
},
|
|
||||||
totalCount: count,
|
|
||||||
records,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default paginateRest;
|
|
@@ -1,44 +0,0 @@
|
|||||||
import serializers from '../serializers/index.js';
|
|
||||||
|
|
||||||
const isPaginated = (object) =>
|
|
||||||
object?.pageInfo &&
|
|
||||||
object?.totalCount !== undefined &&
|
|
||||||
Array.isArray(object?.records);
|
|
||||||
|
|
||||||
const isArray = (object) =>
|
|
||||||
Array.isArray(object) || Array.isArray(object?.records);
|
|
||||||
|
|
||||||
const totalCount = (object) =>
|
|
||||||
isPaginated(object) ? object.totalCount : isArray(object) ? object.length : 1;
|
|
||||||
|
|
||||||
const renderObject = (response, object) => {
|
|
||||||
let data = isPaginated(object) ? object.records : object;
|
|
||||||
const type = isPaginated(object)
|
|
||||||
? object.records[0].constructor.name
|
|
||||||
: Array.isArray(object)
|
|
||||||
? object[0].constructor.name
|
|
||||||
: object.constructor.name;
|
|
||||||
|
|
||||||
const serializer = serializers[type];
|
|
||||||
|
|
||||||
if (serializer) {
|
|
||||||
data = Array.isArray(data)
|
|
||||||
? data.map((item) => serializer(item))
|
|
||||||
: serializer(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
const computedPayload = {
|
|
||||||
data,
|
|
||||||
meta: {
|
|
||||||
type,
|
|
||||||
count: totalCount(object),
|
|
||||||
isArray: isArray(object),
|
|
||||||
currentPage: isPaginated(object) ? object.pageInfo.currentPage : null,
|
|
||||||
totalPages: isPaginated(object) ? object.pageInfo.totalPages : null,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return response.json(computedPayload);
|
|
||||||
};
|
|
||||||
|
|
||||||
export { renderObject };
|
|
@@ -1,8 +0,0 @@
|
|||||||
import { Router } from 'express';
|
|
||||||
import versionAction from '../../../controllers/api/v1/automatisch/version.js';
|
|
||||||
|
|
||||||
const router = Router();
|
|
||||||
|
|
||||||
router.get('/version', versionAction);
|
|
||||||
|
|
||||||
export default router;
|
|
@@ -1,26 +0,0 @@
|
|||||||
import { Router } from 'express';
|
|
||||||
import { authenticateUser } from '../../../helpers/authentication.js';
|
|
||||||
import { authorizeAdmin } from '../../../helpers/authorization.js';
|
|
||||||
import { checkIsEnterprise } from '../../../helpers/check-is-enterprise.js';
|
|
||||||
import getSamlAuthProvidersAction from '../../../controllers/api/v1/admin/saml-auth-providers/get-saml-auth-providers.ee.js';
|
|
||||||
import getSamlAuthProviderAction from '../../../controllers/api/v1/admin/saml-auth-providers/get-saml-auth-provider.ee.js';
|
|
||||||
|
|
||||||
const router = Router();
|
|
||||||
|
|
||||||
router.get(
|
|
||||||
'/',
|
|
||||||
authenticateUser,
|
|
||||||
authorizeAdmin,
|
|
||||||
checkIsEnterprise,
|
|
||||||
getSamlAuthProvidersAction
|
|
||||||
);
|
|
||||||
|
|
||||||
router.get(
|
|
||||||
'/:samlAuthProviderId',
|
|
||||||
authenticateUser,
|
|
||||||
authorizeAdmin,
|
|
||||||
checkIsEnterprise,
|
|
||||||
getSamlAuthProviderAction
|
|
||||||
);
|
|
||||||
|
|
||||||
export default router;
|
|
@@ -1,22 +0,0 @@
|
|||||||
import { Router } from 'express';
|
|
||||||
import { authenticateUser } from '../../../helpers/authentication.js';
|
|
||||||
import { authorizeUser } from '../../../helpers/authorization.js';
|
|
||||||
import checkIsCloud from '../../../helpers/check-is-cloud.js';
|
|
||||||
import getCurrentUserAction from '../../../controllers/api/v1/users/get-current-user.js';
|
|
||||||
import getUserAction from '../../../controllers/api/v1/users/get-user.js';
|
|
||||||
import getUsersAction from '../../../controllers/api/v1/users/get-users.js';
|
|
||||||
import getUserTrialAction from '../../../controllers/api/v1/users/get-user-trial.ee.js';
|
|
||||||
|
|
||||||
const router = Router();
|
|
||||||
|
|
||||||
router.get('/', authenticateUser, authorizeUser, getUsersAction);
|
|
||||||
router.get('/me', authenticateUser, getCurrentUserAction);
|
|
||||||
router.get('/:userId', authenticateUser, authorizeUser, getUserAction);
|
|
||||||
router.get(
|
|
||||||
'/:userId/trial',
|
|
||||||
authenticateUser,
|
|
||||||
checkIsCloud,
|
|
||||||
getUserTrialAction
|
|
||||||
);
|
|
||||||
|
|
||||||
export default router;
|
|
@@ -1,8 +0,0 @@
|
|||||||
import { Router } from 'express';
|
|
||||||
import indexAction from '../controllers/healthcheck/index.js';
|
|
||||||
|
|
||||||
const router = Router();
|
|
||||||
|
|
||||||
router.get('/', indexAction);
|
|
||||||
|
|
||||||
export default router;
|
|
@@ -2,19 +2,11 @@ import { Router } from 'express';
|
|||||||
import graphQLInstance from '../helpers/graphql-instance.js';
|
import graphQLInstance from '../helpers/graphql-instance.js';
|
||||||
import webhooksRouter from './webhooks.js';
|
import webhooksRouter from './webhooks.js';
|
||||||
import paddleRouter from './paddle.ee.js';
|
import paddleRouter from './paddle.ee.js';
|
||||||
import healthcheckRouter from './healthcheck.js';
|
|
||||||
import automatischRouter from './api/v1/automatisch.js';
|
|
||||||
import usersRouter from './api/v1/users.js';
|
|
||||||
import samlAuthProvidersRouter from './api/v1/saml-auth-providers.ee.js';
|
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
router.use('/graphql', graphQLInstance);
|
router.use('/graphql', graphQLInstance);
|
||||||
router.use('/webhooks', webhooksRouter);
|
router.use('/webhooks', webhooksRouter);
|
||||||
router.use('/paddle', paddleRouter);
|
router.use('/paddle', paddleRouter);
|
||||||
router.use('/healthcheck', healthcheckRouter);
|
|
||||||
router.use('/api/v1/automatisch', automatischRouter);
|
|
||||||
router.use('/api/v1/users', usersRouter);
|
|
||||||
router.use('/api/v1/admin/saml-auth-providers', samlAuthProvidersRouter);
|
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
@@ -1,13 +0,0 @@
|
|||||||
import userSerializer from './user.js';
|
|
||||||
import roleSerializer from './role.js';
|
|
||||||
import permissionSerializer from './permission.js';
|
|
||||||
import samlAuthProviderSerializer from './saml-auth-provider.ee.js';
|
|
||||||
|
|
||||||
const serializers = {
|
|
||||||
User: userSerializer,
|
|
||||||
Role: roleSerializer,
|
|
||||||
Permission: permissionSerializer,
|
|
||||||
SamlAuthProvider: samlAuthProviderSerializer,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default serializers;
|
|
@@ -1,13 +0,0 @@
|
|||||||
const permissionSerializer = (permission) => {
|
|
||||||
return {
|
|
||||||
id: permission.id,
|
|
||||||
roleId: permission.roleId,
|
|
||||||
action: permission.action,
|
|
||||||
subject: permission.subject,
|
|
||||||
conditions: permission.conditions,
|
|
||||||
createdAt: permission.createdAt,
|
|
||||||
updatedAt: permission.updatedAt,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default permissionSerializer;
|
|
@@ -1,25 +0,0 @@
|
|||||||
import { describe, it, expect, beforeEach } from 'vitest';
|
|
||||||
import { createPermission } from '../../test/factories/permission';
|
|
||||||
import permissionSerializer from './permission';
|
|
||||||
|
|
||||||
describe('permissionSerializer', () => {
|
|
||||||
let permission;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
permission = await createPermission();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return permission data', async () => {
|
|
||||||
const expectedPayload = {
|
|
||||||
id: permission.id,
|
|
||||||
roleId: permission.roleId,
|
|
||||||
action: permission.action,
|
|
||||||
subject: permission.subject,
|
|
||||||
conditions: permission.conditions,
|
|
||||||
createdAt: permission.createdAt,
|
|
||||||
updatedAt: permission.updatedAt,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(permissionSerializer(permission)).toEqual(expectedPayload);
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,13 +0,0 @@
|
|||||||
const roleSerializer = (role) => {
|
|
||||||
return {
|
|
||||||
id: role.id,
|
|
||||||
name: role.name,
|
|
||||||
key: role.key,
|
|
||||||
description: role.description,
|
|
||||||
createdAt: role.createdAt,
|
|
||||||
updatedAt: role.updatedAt,
|
|
||||||
isAdmin: role.isAdmin,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default roleSerializer;
|
|
@@ -1,25 +0,0 @@
|
|||||||
import { describe, it, expect, beforeEach } from 'vitest';
|
|
||||||
import { createRole } from '../../test/factories/role';
|
|
||||||
import roleSerializer from './role';
|
|
||||||
|
|
||||||
describe('roleSerializer', () => {
|
|
||||||
let role;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
role = await createRole();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return role data', async () => {
|
|
||||||
const expectedPayload = {
|
|
||||||
id: role.id,
|
|
||||||
name: role.name,
|
|
||||||
key: role.key,
|
|
||||||
description: role.description,
|
|
||||||
createdAt: role.createdAt,
|
|
||||||
updatedAt: role.updatedAt,
|
|
||||||
isAdmin: role.isAdmin,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(roleSerializer(role)).toEqual(expectedPayload);
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,18 +0,0 @@
|
|||||||
const samlAuthProviderSerializer = (samlAuthProvider) => {
|
|
||||||
return {
|
|
||||||
id: samlAuthProvider.id,
|
|
||||||
name: samlAuthProvider.name,
|
|
||||||
certificate: samlAuthProvider.certificate,
|
|
||||||
signatureAlgorithm: samlAuthProvider.signatureAlgorithm,
|
|
||||||
issuer: samlAuthProvider.issuer,
|
|
||||||
entryPoint: samlAuthProvider.entryPoint,
|
|
||||||
firstnameAttributeName: samlAuthProvider.firstnameAttributeName,
|
|
||||||
surnameAttributeName: samlAuthProvider.surnameAttributeName,
|
|
||||||
emailAttributeName: samlAuthProvider.emailAttributeName,
|
|
||||||
roleAttributeName: samlAuthProvider.roleAttributeName,
|
|
||||||
active: samlAuthProvider.active,
|
|
||||||
defaultRoleId: samlAuthProvider.defaultRoleId,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default samlAuthProviderSerializer;
|
|
@@ -1,32 +0,0 @@
|
|||||||
import { describe, it, expect, beforeEach } from 'vitest';
|
|
||||||
import { createSamlAuthProvider } from '../../test/factories/saml-auth-provider.ee.js';
|
|
||||||
import samlAuthProviderSerializer from './saml-auth-provider.ee.js';
|
|
||||||
|
|
||||||
describe('samlAuthProviderSerializer', () => {
|
|
||||||
let samlAuthProvider;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
samlAuthProvider = await createSamlAuthProvider();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return saml auth provider data', async () => {
|
|
||||||
const expectedPayload = {
|
|
||||||
id: samlAuthProvider.id,
|
|
||||||
name: samlAuthProvider.name,
|
|
||||||
certificate: samlAuthProvider.certificate,
|
|
||||||
signatureAlgorithm: samlAuthProvider.signatureAlgorithm,
|
|
||||||
issuer: samlAuthProvider.issuer,
|
|
||||||
entryPoint: samlAuthProvider.entryPoint,
|
|
||||||
firstnameAttributeName: samlAuthProvider.firstnameAttributeName,
|
|
||||||
surnameAttributeName: samlAuthProvider.surnameAttributeName,
|
|
||||||
emailAttributeName: samlAuthProvider.emailAttributeName,
|
|
||||||
roleAttributeName: samlAuthProvider.roleAttributeName,
|
|
||||||
active: samlAuthProvider.active,
|
|
||||||
defaultRoleId: samlAuthProvider.defaultRoleId,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(samlAuthProviderSerializer(samlAuthProvider)).toEqual(
|
|
||||||
expectedPayload
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,32 +0,0 @@
|
|||||||
import roleSerializer from './role.js';
|
|
||||||
import permissionSerializer from './permission.js';
|
|
||||||
import appConfig from '../config/app.js';
|
|
||||||
|
|
||||||
const userSerializer = (user) => {
|
|
||||||
let userData = {
|
|
||||||
id: user.id,
|
|
||||||
email: user.email,
|
|
||||||
createdAt: user.createdAt,
|
|
||||||
updatedAt: user.updatedAt,
|
|
||||||
fullName: user.fullName,
|
|
||||||
roleId: user.roleId,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (user.role) {
|
|
||||||
userData.role = roleSerializer(user.role);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user.permissions) {
|
|
||||||
userData.permissions = user.permissions.map((permission) =>
|
|
||||||
permissionSerializer(permission)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (appConfig.isCloud && user.trialExpiryDate) {
|
|
||||||
userData.trialExpiryDate = user.trialExpiryDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
return userData;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default userSerializer;
|
|
@@ -1,76 +0,0 @@
|
|||||||
import { vi, describe, it, expect, beforeEach } from 'vitest';
|
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import appConfig from '../config/app';
|
|
||||||
import { createUser } from '../../test/factories/user';
|
|
||||||
import { createPermission } from '../../test/factories/permission';
|
|
||||||
import userSerializer from './user';
|
|
||||||
|
|
||||||
describe('userSerializer', () => {
|
|
||||||
let user, role, permissionOne, permissionTwo;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
|
||||||
user = await createUser();
|
|
||||||
role = await user.$relatedQuery('role');
|
|
||||||
|
|
||||||
permissionOne = await createPermission({
|
|
||||||
roleId: role.id,
|
|
||||||
action: 'read',
|
|
||||||
subject: 'User',
|
|
||||||
});
|
|
||||||
|
|
||||||
permissionTwo = await createPermission({
|
|
||||||
roleId: role.id,
|
|
||||||
action: 'read',
|
|
||||||
subject: 'Role',
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return user data', async () => {
|
|
||||||
vi.spyOn(appConfig, 'isCloud', 'get').mockReturnValue(false);
|
|
||||||
|
|
||||||
const expectedPayload = {
|
|
||||||
createdAt: user.createdAt,
|
|
||||||
email: user.email,
|
|
||||||
fullName: user.fullName,
|
|
||||||
id: user.id,
|
|
||||||
roleId: user.roleId,
|
|
||||||
updatedAt: user.updatedAt,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(userSerializer(user)).toEqual(expectedPayload);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return user data with the role', async () => {
|
|
||||||
user.role = role;
|
|
||||||
|
|
||||||
const expectedPayload = {
|
|
||||||
role,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(userSerializer(user)).toMatchObject(expectedPayload);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return user data with the permissions', async () => {
|
|
||||||
user.permissions = [permissionOne, permissionTwo];
|
|
||||||
|
|
||||||
const expectedPayload = {
|
|
||||||
permissions: [permissionOne, permissionTwo],
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(userSerializer(user)).toMatchObject(expectedPayload);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return user data with trial expiry date', async () => {
|
|
||||||
vi.spyOn(appConfig, 'isCloud', 'get').mockReturnValue(true);
|
|
||||||
|
|
||||||
await user.$query().patch({
|
|
||||||
trialExpiryDate: DateTime.now().plus({ days: 30 }).toISODate(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const expectedPayload = {
|
|
||||||
trialExpiryDate: user.trialExpiryDate,
|
|
||||||
};
|
|
||||||
|
|
||||||
expect(userSerializer(user)).toMatchObject(expectedPayload);
|
|
||||||
});
|
|
||||||
});
|
|
@@ -1,5 +1,4 @@
|
|||||||
import { faker } from '@faker-js/faker';
|
import { faker } from '@faker-js/faker';
|
||||||
import Config from '../../src/models/config';
|
|
||||||
|
|
||||||
export const createConfig = async (params = {}) => {
|
export const createConfig = async (params = {}) => {
|
||||||
const configData = {
|
const configData = {
|
||||||
@@ -7,7 +6,10 @@ export const createConfig = async (params = {}) => {
|
|||||||
value: params?.value || { data: 'sampleConfig' },
|
value: params?.value || { data: 'sampleConfig' },
|
||||||
};
|
};
|
||||||
|
|
||||||
const config = await Config.query().insert(configData).returning('*');
|
const [config] = await global.knex
|
||||||
|
.table('config')
|
||||||
|
.insert(configData)
|
||||||
|
.returning('*');
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
};
|
};
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import appConfig from '../../src/config/app';
|
import appConfig from '../../src/config/app';
|
||||||
import { AES } from 'crypto-js';
|
import { AES } from 'crypto-js';
|
||||||
import Connection from '../../src/models/connection';
|
|
||||||
|
|
||||||
export const createConnection = async (params = {}) => {
|
export const createConnection = async (params = {}) => {
|
||||||
params.key = params?.key || 'deepl';
|
params.key = params?.key || 'deepl';
|
||||||
@@ -17,7 +16,10 @@ export const createConnection = async (params = {}) => {
|
|||||||
appConfig.encryptionKey
|
appConfig.encryptionKey
|
||||||
).toString();
|
).toString();
|
||||||
|
|
||||||
const connection = await Connection.query().insert(params).returning('*');
|
const [connection] = await global.knex
|
||||||
|
.table('connections')
|
||||||
|
.insert(params)
|
||||||
|
.returning('*');
|
||||||
|
|
||||||
return connection;
|
return connection;
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
import ExecutionStep from '../../src/models/execution-step';
|
|
||||||
import { createExecution } from './execution';
|
import { createExecution } from './execution';
|
||||||
import { createStep } from './step';
|
import { createStep } from './step';
|
||||||
|
|
||||||
@@ -9,7 +8,8 @@ export const createExecutionStep = async (params = {}) => {
|
|||||||
params.dataIn = params?.dataIn || { dataIn: 'dataIn' };
|
params.dataIn = params?.dataIn || { dataIn: 'dataIn' };
|
||||||
params.dataOut = params?.dataOut || { dataOut: 'dataOut' };
|
params.dataOut = params?.dataOut || { dataOut: 'dataOut' };
|
||||||
|
|
||||||
const executionStep = await ExecutionStep.query()
|
const [executionStep] = await global.knex
|
||||||
|
.table('executionSteps')
|
||||||
.insert(params)
|
.insert(params)
|
||||||
.returning('*');
|
.returning('*');
|
||||||
|
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
import Execution from '../../src/models/execution';
|
|
||||||
import { createFlow } from './flow';
|
import { createFlow } from './flow';
|
||||||
|
|
||||||
export const createExecution = async (params = {}) => {
|
export const createExecution = async (params = {}) => {
|
||||||
@@ -7,7 +6,10 @@ export const createExecution = async (params = {}) => {
|
|||||||
params.createdAt = params?.createdAt || new Date().toISOString();
|
params.createdAt = params?.createdAt || new Date().toISOString();
|
||||||
params.updatedAt = params?.updatedAt || new Date().toISOString();
|
params.updatedAt = params?.updatedAt || new Date().toISOString();
|
||||||
|
|
||||||
const execution = await Execution.query().insert(params).returning('*');
|
const [execution] = await global.knex
|
||||||
|
.table('executions')
|
||||||
|
.insert(params)
|
||||||
|
.returning('*');
|
||||||
|
|
||||||
return execution;
|
return execution;
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
import Flow from '../../src/models/flow';
|
|
||||||
import { createUser } from './user';
|
import { createUser } from './user';
|
||||||
|
|
||||||
export const createFlow = async (params = {}) => {
|
export const createFlow = async (params = {}) => {
|
||||||
@@ -7,7 +6,7 @@ export const createFlow = async (params = {}) => {
|
|||||||
params.createdAt = params?.createdAt || new Date().toISOString();
|
params.createdAt = params?.createdAt || new Date().toISOString();
|
||||||
params.updatedAt = params?.updatedAt || new Date().toISOString();
|
params.updatedAt = params?.updatedAt || new Date().toISOString();
|
||||||
|
|
||||||
const flow = await Flow.query().insert(params).returning('*');
|
const [flow] = await global.knex.table('flows').insert(params).returning('*');
|
||||||
|
|
||||||
return flow;
|
return flow;
|
||||||
};
|
};
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
import Permission from '../../src/models/permission';
|
|
||||||
import { createRole } from './role';
|
import { createRole } from './role';
|
||||||
|
|
||||||
export const createPermission = async (params = {}) => {
|
export const createPermission = async (params = {}) => {
|
||||||
@@ -7,7 +6,10 @@ export const createPermission = async (params = {}) => {
|
|||||||
params.subject = params?.subject || 'User';
|
params.subject = params?.subject || 'User';
|
||||||
params.conditions = params?.conditions || ['isCreator'];
|
params.conditions = params?.conditions || ['isCreator'];
|
||||||
|
|
||||||
const permission = await Permission.query().insert(params).returning('*');
|
const [permission] = await global.knex
|
||||||
|
.table('permissions')
|
||||||
|
.insert(params)
|
||||||
|
.returning('*');
|
||||||
|
|
||||||
return permission;
|
return permission;
|
||||||
};
|
};
|
||||||
|
@@ -1,10 +1,8 @@
|
|||||||
import Role from '../../src/models/role';
|
|
||||||
|
|
||||||
export const createRole = async (params = {}) => {
|
export const createRole = async (params = {}) => {
|
||||||
params.name = params?.name || 'Viewer';
|
params.name = params?.name || 'Viewer';
|
||||||
params.key = params?.key || 'viewer';
|
params.key = params?.key || 'viewer';
|
||||||
|
|
||||||
const role = await Role.query().insert(params).returning('*');
|
const [role] = await global.knex.table('roles').insert(params).returning('*');
|
||||||
|
|
||||||
return role;
|
return role;
|
||||||
};
|
};
|
||||||
|
@@ -1,33 +0,0 @@
|
|||||||
import { createRole } from './role';
|
|
||||||
import SamlAuthProvider from '../../src/models/saml-auth-provider.ee.js';
|
|
||||||
|
|
||||||
export const createSamlAuthProvider = async (params = {}) => {
|
|
||||||
params.name = params?.name || 'Keycloak SAML';
|
|
||||||
params.certificate = params?.certificate || 'certificate';
|
|
||||||
params.signatureAlgorithm = params?.signatureAlgorithm || 'sha512';
|
|
||||||
|
|
||||||
params.entryPoint =
|
|
||||||
params?.entryPoint ||
|
|
||||||
'https://example.com/auth/realms/automatisch/protocol/saml';
|
|
||||||
|
|
||||||
params.issuer = params?.issuer || 'automatisch-client';
|
|
||||||
|
|
||||||
params.firstnameAttributeName =
|
|
||||||
params?.firstnameAttributeName || 'urn:oid:2.1.1.42';
|
|
||||||
|
|
||||||
params.surnameAttributeName =
|
|
||||||
params?.surnameAttributeName || 'urn:oid:2.1.1.4';
|
|
||||||
|
|
||||||
params.emailAttributeName =
|
|
||||||
params?.emailAttributeName || 'urn:oid:1.1.2342.19200300.100.1.1';
|
|
||||||
|
|
||||||
params.roleAttributeName = params?.roleAttributeName || 'Role';
|
|
||||||
params.defaultRoleId = params?.defaultRoleId || (await createRole()).id;
|
|
||||||
params.active = params?.active || true;
|
|
||||||
|
|
||||||
const samlAuthProvider = await SamlAuthProvider.query()
|
|
||||||
.insert(params)
|
|
||||||
.returning('*');
|
|
||||||
|
|
||||||
return samlAuthProvider;
|
|
||||||
};
|
|
@@ -1,4 +1,3 @@
|
|||||||
import Step from '../../src/models/step';
|
|
||||||
import { createFlow } from './flow';
|
import { createFlow } from './flow';
|
||||||
|
|
||||||
export const createStep = async (params = {}) => {
|
export const createStep = async (params = {}) => {
|
||||||
@@ -17,7 +16,7 @@ export const createStep = async (params = {}) => {
|
|||||||
params.appKey =
|
params.appKey =
|
||||||
params?.appKey || (params.type === 'action' ? 'deepl' : 'webhook');
|
params?.appKey || (params.type === 'action' ? 'deepl' : 'webhook');
|
||||||
|
|
||||||
const step = await Step.query().insert(params).returning('*');
|
const [step] = await global.knex.table('steps').insert(params).returning('*');
|
||||||
|
|
||||||
return step;
|
return step;
|
||||||
};
|
};
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import { createRole } from './role';
|
import { createRole } from './role';
|
||||||
import { faker } from '@faker-js/faker';
|
import { faker } from '@faker-js/faker';
|
||||||
import User from '../../src/models/user';
|
|
||||||
|
|
||||||
export const createUser = async (params = {}) => {
|
export const createUser = async (params = {}) => {
|
||||||
params.roleId = params?.roleId || (await createRole()).id;
|
params.roleId = params?.roleId || (await createRole()).id;
|
||||||
@@ -8,7 +7,7 @@ export const createUser = async (params = {}) => {
|
|||||||
params.email = params?.email || faker.internet.email();
|
params.email = params?.email || faker.internet.email();
|
||||||
params.password = params?.password || faker.internet.password();
|
params.password = params?.password || faker.internet.password();
|
||||||
|
|
||||||
const user = await User.query().insert(params).returning('*');
|
const [user] = await global.knex.table('users').insert(params).returning('*');
|
||||||
|
|
||||||
return user;
|
return user;
|
||||||
};
|
};
|
||||||
|
@@ -1,29 +0,0 @@
|
|||||||
const getSamlAuthProvidersMock = async (samlAuthProvider) => {
|
|
||||||
const data = {
|
|
||||||
active: samlAuthProvider.active,
|
|
||||||
certificate: samlAuthProvider.certificate,
|
|
||||||
defaultRoleId: samlAuthProvider.defaultRoleId,
|
|
||||||
emailAttributeName: samlAuthProvider.emailAttributeName,
|
|
||||||
entryPoint: samlAuthProvider.entryPoint,
|
|
||||||
firstnameAttributeName: samlAuthProvider.firstnameAttributeName,
|
|
||||||
id: samlAuthProvider.id,
|
|
||||||
issuer: samlAuthProvider.issuer,
|
|
||||||
name: samlAuthProvider.name,
|
|
||||||
roleAttributeName: samlAuthProvider.roleAttributeName,
|
|
||||||
signatureAlgorithm: samlAuthProvider.signatureAlgorithm,
|
|
||||||
surnameAttributeName: samlAuthProvider.surnameAttributeName,
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
data: data,
|
|
||||||
meta: {
|
|
||||||
count: 1,
|
|
||||||
currentPage: null,
|
|
||||||
isArray: false,
|
|
||||||
totalPages: null,
|
|
||||||
type: 'SamlAuthProvider',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default getSamlAuthProvidersMock;
|
|
@@ -1,31 +0,0 @@
|
|||||||
const getSamlAuthProvidersMock = async (samlAuthProviders) => {
|
|
||||||
const data = samlAuthProviders.map((samlAuthProvider) => {
|
|
||||||
return {
|
|
||||||
active: samlAuthProvider.active,
|
|
||||||
certificate: samlAuthProvider.certificate,
|
|
||||||
defaultRoleId: samlAuthProvider.defaultRoleId,
|
|
||||||
emailAttributeName: samlAuthProvider.emailAttributeName,
|
|
||||||
entryPoint: samlAuthProvider.entryPoint,
|
|
||||||
firstnameAttributeName: samlAuthProvider.firstnameAttributeName,
|
|
||||||
id: samlAuthProvider.id,
|
|
||||||
issuer: samlAuthProvider.issuer,
|
|
||||||
name: samlAuthProvider.name,
|
|
||||||
roleAttributeName: samlAuthProvider.roleAttributeName,
|
|
||||||
signatureAlgorithm: samlAuthProvider.signatureAlgorithm,
|
|
||||||
surnameAttributeName: samlAuthProvider.surnameAttributeName,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
data: data,
|
|
||||||
meta: {
|
|
||||||
count: data.length,
|
|
||||||
currentPage: null,
|
|
||||||
isArray: true,
|
|
||||||
totalPages: null,
|
|
||||||
type: 'SamlAuthProvider',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default getSamlAuthProvidersMock;
|
|
@@ -1,32 +0,0 @@
|
|||||||
const getCurrentUserMock = (currentUser, role) => {
|
|
||||||
return {
|
|
||||||
data: {
|
|
||||||
createdAt: currentUser.createdAt.toISOString(),
|
|
||||||
email: currentUser.email,
|
|
||||||
fullName: currentUser.fullName,
|
|
||||||
id: currentUser.id,
|
|
||||||
permissions: [],
|
|
||||||
role: {
|
|
||||||
createdAt: role.createdAt.toISOString(),
|
|
||||||
description: null,
|
|
||||||
id: role.id,
|
|
||||||
isAdmin: role.isAdmin,
|
|
||||||
key: role.key,
|
|
||||||
name: role.name,
|
|
||||||
updatedAt: role.updatedAt.toISOString(),
|
|
||||||
},
|
|
||||||
roleId: role.id,
|
|
||||||
trialExpiryDate: currentUser.trialExpiryDate.toISOString(),
|
|
||||||
updatedAt: currentUser.updatedAt.toISOString(),
|
|
||||||
},
|
|
||||||
meta: {
|
|
||||||
count: 1,
|
|
||||||
currentPage: null,
|
|
||||||
isArray: false,
|
|
||||||
totalPages: null,
|
|
||||||
type: 'User',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default getCurrentUserMock;
|
|
@@ -1,17 +0,0 @@
|
|||||||
const getUserTrialMock = async (currentUser) => {
|
|
||||||
return {
|
|
||||||
data: {
|
|
||||||
inTrial: await currentUser.inTrial(),
|
|
||||||
expireAt: currentUser.trialExpiryDate.toISOString(),
|
|
||||||
},
|
|
||||||
meta: {
|
|
||||||
count: 1,
|
|
||||||
currentPage: null,
|
|
||||||
isArray: false,
|
|
||||||
totalPages: null,
|
|
||||||
type: 'Object',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default getUserTrialMock;
|
|
@@ -1,31 +0,0 @@
|
|||||||
const getUserMock = (currentUser, role) => {
|
|
||||||
return {
|
|
||||||
data: {
|
|
||||||
createdAt: currentUser.createdAt.toISOString(),
|
|
||||||
email: currentUser.email,
|
|
||||||
fullName: currentUser.fullName,
|
|
||||||
id: currentUser.id,
|
|
||||||
role: {
|
|
||||||
createdAt: role.createdAt.toISOString(),
|
|
||||||
description: null,
|
|
||||||
id: role.id,
|
|
||||||
isAdmin: role.isAdmin,
|
|
||||||
key: role.key,
|
|
||||||
name: role.name,
|
|
||||||
updatedAt: role.updatedAt.toISOString(),
|
|
||||||
},
|
|
||||||
roleId: role.id,
|
|
||||||
trialExpiryDate: currentUser.trialExpiryDate.toISOString(),
|
|
||||||
updatedAt: currentUser.updatedAt.toISOString(),
|
|
||||||
},
|
|
||||||
meta: {
|
|
||||||
count: 1,
|
|
||||||
currentPage: null,
|
|
||||||
isArray: false,
|
|
||||||
totalPages: null,
|
|
||||||
type: 'User',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default getUserMock;
|
|
@@ -1,38 +0,0 @@
|
|||||||
const getUsersMock = async (users, roles) => {
|
|
||||||
const data = users.map((user) => {
|
|
||||||
const role = roles.find((r) => r.id === user.roleId);
|
|
||||||
return {
|
|
||||||
createdAt: user.createdAt.toISOString(),
|
|
||||||
email: user.email,
|
|
||||||
fullName: user.fullName,
|
|
||||||
id: user.id,
|
|
||||||
role: role
|
|
||||||
? {
|
|
||||||
createdAt: role.createdAt.toISOString(),
|
|
||||||
description: role.description,
|
|
||||||
id: role.id,
|
|
||||||
isAdmin: role.isAdmin,
|
|
||||||
key: role.key,
|
|
||||||
name: role.name,
|
|
||||||
updatedAt: role.updatedAt.toISOString(),
|
|
||||||
}
|
|
||||||
: null, // Fallback to null if role not found
|
|
||||||
roleId: user.roleId,
|
|
||||||
trialExpiryDate: user.trialExpiryDate.toISOString(),
|
|
||||||
updatedAt: user.updatedAt.toISOString(),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
data: data,
|
|
||||||
meta: {
|
|
||||||
count: data.length,
|
|
||||||
currentPage: 1,
|
|
||||||
isArray: true,
|
|
||||||
totalPages: 1,
|
|
||||||
type: 'User',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default getUsersMock;
|
|
@@ -32,6 +32,15 @@ export default defineConfig({
|
|||||||
],
|
],
|
||||||
sidebar: {
|
sidebar: {
|
||||||
'/apps/': [
|
'/apps/': [
|
||||||
|
{
|
||||||
|
text: 'Airbrake',
|
||||||
|
collapsible: true,
|
||||||
|
collapsed: true,
|
||||||
|
items: [
|
||||||
|
{ text: 'Triggers', link: '/apps/airbrake/triggers' },
|
||||||
|
{ text: 'Connection', link: '/apps/airbrake/connection' },
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
text: 'Carbone',
|
text: 'Carbone',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
@@ -252,16 +261,6 @@ export default defineConfig({
|
|||||||
{ text: 'Connection', link: '/apps/openai/connection' },
|
{ text: 'Connection', link: '/apps/openai/connection' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
|
||||||
text: 'PDFMonkey',
|
|
||||||
collapsible: true,
|
|
||||||
collapsed: true,
|
|
||||||
items: [
|
|
||||||
{ text: 'Triggers', link: '/apps/pdf-monkey/triggers' },
|
|
||||||
{ text: 'Actions', link: '/apps/pdf-monkey/actions' },
|
|
||||||
{ text: 'Connection', link: '/apps/pdf-monkey/connection' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
text: 'Pipedrive',
|
text: 'Pipedrive',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
|
13
packages/docs/pages/apps/airbrake/connection.md
Normal file
13
packages/docs/pages/apps/airbrake/connection.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Airbrake
|
||||||
|
|
||||||
|
:::info
|
||||||
|
This page explains the steps you need to follow to set up the Airbrake
|
||||||
|
connection in Automatisch. If any of the steps are outdated, please let us know!
|
||||||
|
:::
|
||||||
|
|
||||||
|
1. Login to your Airbrake account: [https://www.airbrake.io/](https://www.airbrake.io/).
|
||||||
|
2. Go to your profile & notifications page.
|
||||||
|
3. Copy `Auth Token` from the page to the `Auth Token` field on Automatisch.
|
||||||
|
4. Fill the instance URL field with your subdomain. (https://{yoursubdomain}.airbrake.io)
|
||||||
|
5. Write any screen name to be displayed in Automatisch.
|
||||||
|
6. Now, you can start using the Airbrake connection with Automatisch.
|
@@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
favicon: /favicons/pdf-monkey.svg
|
favicon: /favicons/airbrake.svg
|
||||||
items:
|
items:
|
||||||
- name: Generate documents
|
- name: New errors
|
||||||
desc: Creates a new document.
|
desc: Triggers when a new error occurs.
|
||||||
---
|
---
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
@@ -1,11 +0,0 @@
|
|||||||
# PDFMonkey
|
|
||||||
|
|
||||||
:::info
|
|
||||||
This page explains the steps you need to follow to set up the PDFMonkey
|
|
||||||
connection in Automatisch. If any of the steps are outdated, please let us know!
|
|
||||||
:::
|
|
||||||
|
|
||||||
1. Login to your PDFMonkey account: [https://dashboard.pdfmonkey.io/login](https://dashboard.pdfmonkey.io/login).
|
|
||||||
2. Go to **My Account** section from your profile.
|
|
||||||
3. Copy `API SECRET KEY` from the page to the `API Key` field on Automatisch.
|
|
||||||
4. Now, you can start using the PDFMonkey connection with Automatisch.
|
|
@@ -1,12 +0,0 @@
|
|||||||
---
|
|
||||||
favicon: /favicons/pdf-monkey.svg
|
|
||||||
items:
|
|
||||||
- name: Documents Generated
|
|
||||||
desc: Triggers upon the successful completion of document generation.
|
|
||||||
---
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import CustomListing from '../../components/CustomListing.vue'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<CustomListing />
|
|
@@ -3,6 +3,7 @@
|
|||||||
The following integrations are currently supported by Automatisch.
|
The following integrations are currently supported by Automatisch.
|
||||||
|
|
||||||
- [Carbone](/apps/carbone/actions)
|
- [Carbone](/apps/carbone/actions)
|
||||||
|
- [Airbrake](/apps/airbrake/triggers)
|
||||||
- [DeepL](/apps/deepl/actions)
|
- [DeepL](/apps/deepl/actions)
|
||||||
- [Delay](/apps/delay/actions)
|
- [Delay](/apps/delay/actions)
|
||||||
- [Discord](/apps/discord/actions)
|
- [Discord](/apps/discord/actions)
|
||||||
@@ -26,7 +27,6 @@ The following integrations are currently supported by Automatisch.
|
|||||||
- [Ntfy](/apps/ntfy/actions)
|
- [Ntfy](/apps/ntfy/actions)
|
||||||
- [Odoo](/apps/odoo/actions)
|
- [Odoo](/apps/odoo/actions)
|
||||||
- [OpenAI](/apps/openai/actions)
|
- [OpenAI](/apps/openai/actions)
|
||||||
- [PDFMonkey](/apps/pdf-monkey/actions)
|
|
||||||
- [Pipedrive](/apps/pipedrive/triggers)
|
- [Pipedrive](/apps/pipedrive/triggers)
|
||||||
- [Placetel](/apps/placetel/triggers)
|
- [Placetel](/apps/placetel/triggers)
|
||||||
- [PostgreSQL](/apps/postgresql/actions)
|
- [PostgreSQL](/apps/postgresql/actions)
|
||||||
|
1
packages/docs/pages/public/favicons/airbrake.svg
Normal file
1
packages/docs/pages/public/favicons/airbrake.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg height="255" preserveAspectRatio="xMidYMid" viewBox="0 0 256 255" width="256" xmlns="http://www.w3.org/2000/svg"><path d="m128.636514 155.746615v-155.23361889h-3.522242v.06873152l-124.60824865 64.03287157v60.8642488h.00597665v3.234366h-.00597665v60.868233l124.60824865 64.747082h3.842989v-98.581914z" fill="#ff8e4a"/><path d="m129.941416 254.328529 125.568498-64.747082v-124.9668478l-125.887253-64.10160309h-2.243237v253.81055289h2.243237" fill="#f48746"/><path d="m109.097837 87.2551595h36.19561v59.2077195h-36.19561z" fill="#ff8e4a"/><path d="m66.1735097 188.397074h14.8639378c9.4102412 0 12.6087471-2.238257 15.6189883-9.988981l8.2796572-21.353587h45.159596l8.280653 21.353587c3.011238 7.750724 6.396016 9.988981 15.805261 9.988981h14.677665v-19.114335h-3.011237c-3.19751 0-4.704622-.689307-5.831222-3.790194l-39.516638-99.3658524h-25.779299l-39.703907 99.3658524c-1.1285915 3.100887-2.632716 3.790194-5.833214 3.790194h-3.0102413zm44.4075333-49.939922 11.478163-30.655253c2.445448-6.714771 5.269417-18.2556889 5.269417-18.2556889h.375533s2.822972 11.5409179 5.269416 18.2556889l11.478163 30.655253z" fill="#fff"/><path d="m231.204856 150.082739v-51.8086223c.235082 4.5233303 2.970397 16.8432063 24.305058 27.8512063v11.653479zm0-53.1623343v1.353712c-.029883-.5926848-.01793-1.0479066 0-1.353712zm.041837-.4392841s-.022911.1534008-.041837.4392841v-.4392841z" fill="#d4763c"/><path d="m231.155051 94.3016342c-.013946.9931207.05877 1.8945993.049805 2.0460078-.01793.2480312-2.220327 16.094132 24.305058 29.777681v-60.863253c-23.325883 12.0349884-24.449494 25.7414475-24.354863 29.0395642" fill="#ff8e4a"/></svg>
|
After Width: | Height: | Size: 1.6 KiB |
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 112 KiB |
@@ -3,7 +3,6 @@ import Box from '@mui/material/Box';
|
|||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
import { useTheme } from '@mui/material/styles';
|
import { useTheme } from '@mui/material/styles';
|
||||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||||
import Stack from '@mui/material/Stack';
|
|
||||||
import AppsIcon from '@mui/icons-material/Apps';
|
import AppsIcon from '@mui/icons-material/Apps';
|
||||||
import SwapCallsIcon from '@mui/icons-material/SwapCalls';
|
import SwapCallsIcon from '@mui/icons-material/SwapCalls';
|
||||||
import HistoryIcon from '@mui/icons-material/History';
|
import HistoryIcon from '@mui/icons-material/History';
|
||||||
@@ -140,7 +139,7 @@ export default function PublicLayout({
|
|||||||
onDrawerClose={closeDrawer}
|
onDrawerClose={closeDrawer}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Box sx={{ display: 'flex', height: '100%' }}>
|
<Box sx={{ display: 'flex' }}>
|
||||||
<Drawer
|
<Drawer
|
||||||
links={drawerLinks}
|
links={drawerLinks}
|
||||||
bottomLinks={bottomLinks}
|
bottomLinks={bottomLinks}
|
||||||
@@ -149,10 +148,11 @@ export default function PublicLayout({
|
|||||||
onClose={closeDrawer}
|
onClose={closeDrawer}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Stack flex={1}>
|
<Box sx={{ flex: 1 }}>
|
||||||
<Toolbar />
|
<Toolbar />
|
||||||
|
|
||||||
{children}
|
{children}
|
||||||
</Stack>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@@ -1,44 +0,0 @@
|
|||||||
import { Link } from 'react-router-dom';
|
|
||||||
import Button from '@mui/material/Button';
|
|
||||||
import Stack from '@mui/material/Stack';
|
|
||||||
import Typography from '@mui/material/Typography';
|
|
||||||
|
|
||||||
import * as URLS from 'config/urls';
|
|
||||||
import useFormatMessage from 'hooks/useFormatMessage';
|
|
||||||
import useAuthentication from 'hooks/useAuthentication';
|
|
||||||
import Layout from 'components/Layout';
|
|
||||||
import PublicLayout from 'components/PublicLayout';
|
|
||||||
|
|
||||||
export default function NoResultFound(): React.ReactElement {
|
|
||||||
const formatMessage = useFormatMessage();
|
|
||||||
const { isAuthenticated } = useAuthentication();
|
|
||||||
|
|
||||||
const pageContent = (
|
|
||||||
<Stack
|
|
||||||
justifyContent="center"
|
|
||||||
alignItems="center"
|
|
||||||
flex={1}
|
|
||||||
spacing={1}
|
|
||||||
p={2}
|
|
||||||
mb={11}
|
|
||||||
>
|
|
||||||
<Typography variant="h1" color="primary" textAlign="center">
|
|
||||||
404
|
|
||||||
</Typography>
|
|
||||||
<Typography variant="body1" textAlign="center">
|
|
||||||
{formatMessage('notFoundPage.title')}
|
|
||||||
</Typography>
|
|
||||||
<Link to={isAuthenticated ? URLS.FLOWS : URLS.LOGIN}>
|
|
||||||
<Button variant="contained" sx={{ mt: 3 }} component="div">
|
|
||||||
{formatMessage('notFoundPage.button')}
|
|
||||||
</Button>
|
|
||||||
</Link>
|
|
||||||
</Stack>
|
|
||||||
);
|
|
||||||
|
|
||||||
return isAuthenticated ? (
|
|
||||||
<Layout>{pageContent}</Layout>
|
|
||||||
) : (
|
|
||||||
<PublicLayout>{pageContent}</PublicLayout>
|
|
||||||
);
|
|
||||||
}
|
|
@@ -265,7 +265,5 @@
|
|||||||
"authClient.buttonSubmit": "Submit",
|
"authClient.buttonSubmit": "Submit",
|
||||||
"authClient.inputName": "Name",
|
"authClient.inputName": "Name",
|
||||||
"authClient.inputActive": "Active",
|
"authClient.inputActive": "Active",
|
||||||
"updateAuthClient.title": "Update auth client",
|
"updateAuthClient.title": "Update auth client"
|
||||||
"notFoundPage.title": "We can't seem to find a page you're looking for.",
|
|
||||||
"notFoundPage.button": "Back to home page"
|
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import { Route, Routes as ReactRouterRoutes, Navigate } from 'react-router-dom';
|
import { Route, Routes, Navigate } from 'react-router-dom';
|
||||||
import Layout from 'components/Layout';
|
import Layout from 'components/Layout';
|
||||||
import NoResultFound from 'components/NotFound';
|
|
||||||
import PublicLayout from 'components/PublicLayout';
|
import PublicLayout from 'components/PublicLayout';
|
||||||
import Applications from 'pages/Applications';
|
import Applications from 'pages/Applications';
|
||||||
import Application from 'pages/Application';
|
import Application from 'pages/Application';
|
||||||
@@ -18,134 +17,127 @@ import * as URLS from 'config/urls';
|
|||||||
import settingsRoutes from './settingsRoutes';
|
import settingsRoutes from './settingsRoutes';
|
||||||
import adminSettingsRoutes from './adminSettingsRoutes';
|
import adminSettingsRoutes from './adminSettingsRoutes';
|
||||||
import Notifications from 'pages/Notifications';
|
import Notifications from 'pages/Notifications';
|
||||||
import useConfig from 'hooks/useConfig';
|
|
||||||
import useAuthentication from 'hooks/useAuthentication';
|
|
||||||
|
|
||||||
function Routes() {
|
export default (
|
||||||
const { config } = useConfig();
|
<Routes>
|
||||||
const { isAuthenticated } = useAuthentication();
|
<Route
|
||||||
|
path={URLS.EXECUTIONS}
|
||||||
|
element={
|
||||||
|
<Layout>
|
||||||
|
<Executions />
|
||||||
|
</Layout>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
return (
|
<Route
|
||||||
<ReactRouterRoutes>
|
path={URLS.EXECUTION_PATTERN}
|
||||||
<Route
|
element={
|
||||||
path={URLS.EXECUTIONS}
|
<Layout>
|
||||||
element={
|
<Execution />
|
||||||
<Layout>
|
</Layout>
|
||||||
<Executions />
|
}
|
||||||
</Layout>
|
/>
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={URLS.EXECUTION_PATTERN}
|
path={URLS.FLOWS}
|
||||||
element={
|
element={
|
||||||
<Layout>
|
<Layout>
|
||||||
<Execution />
|
<Flows />
|
||||||
</Layout>
|
</Layout>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={URLS.FLOWS}
|
path={URLS.FLOW_PATTERN}
|
||||||
element={
|
element={
|
||||||
<Layout>
|
<Layout>
|
||||||
<Flows />
|
<Flow />
|
||||||
</Layout>
|
</Layout>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={URLS.FLOW_PATTERN}
|
path={`${URLS.APPS}/*`}
|
||||||
element={
|
element={
|
||||||
<Layout>
|
<Layout>
|
||||||
<Flow />
|
<Applications />
|
||||||
</Layout>
|
</Layout>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={`${URLS.APPS}/*`}
|
path={`${URLS.APP_PATTERN}/*`}
|
||||||
element={
|
element={
|
||||||
<Layout>
|
<Layout>
|
||||||
<Applications />
|
<Application />
|
||||||
</Layout>
|
</Layout>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route path={`${URLS.EDITOR}/*`} element={<EditorRoutes />} />
|
||||||
path={`${URLS.APP_PATTERN}/*`}
|
|
||||||
element={
|
|
||||||
<Layout>
|
|
||||||
<Application />
|
|
||||||
</Layout>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Route path={`${URLS.EDITOR}/*`} element={<EditorRoutes />} />
|
<Route
|
||||||
|
path={URLS.LOGIN}
|
||||||
|
element={
|
||||||
|
<PublicLayout>
|
||||||
|
<Login />
|
||||||
|
</PublicLayout>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={URLS.LOGIN}
|
path={URLS.LOGIN_CALLBACK}
|
||||||
element={
|
element={<LoginCallback />}
|
||||||
<PublicLayout>
|
/>
|
||||||
<Login />
|
|
||||||
</PublicLayout>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Route path={URLS.LOGIN_CALLBACK} element={<LoginCallback />} />
|
<Route
|
||||||
|
path={URLS.SIGNUP}
|
||||||
|
element={
|
||||||
|
<PublicLayout>
|
||||||
|
<SignUp />
|
||||||
|
</PublicLayout>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={URLS.SIGNUP}
|
path={URLS.FORGOT_PASSWORD}
|
||||||
element={
|
element={
|
||||||
<PublicLayout>
|
<PublicLayout>
|
||||||
<SignUp />
|
<ForgotPassword />
|
||||||
</PublicLayout>
|
</PublicLayout>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={URLS.FORGOT_PASSWORD}
|
path={URLS.RESET_PASSWORD}
|
||||||
element={
|
element={
|
||||||
<PublicLayout>
|
<PublicLayout>
|
||||||
<ForgotPassword />
|
<ResetPassword />
|
||||||
</PublicLayout>
|
</PublicLayout>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Route
|
<Route
|
||||||
path={URLS.RESET_PASSWORD}
|
path={URLS.UPDATES}
|
||||||
element={
|
element={
|
||||||
<PublicLayout>
|
<Layout>
|
||||||
<ResetPassword />
|
<Notifications />
|
||||||
</PublicLayout>
|
</Layout>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{!config?.disableNotificationsPage && (
|
<Route path="/" element={<Navigate to={URLS.FLOWS} replace />} />
|
||||||
<Route
|
|
||||||
path={URLS.UPDATES}
|
|
||||||
element={
|
|
||||||
<Layout>
|
|
||||||
<Notifications />
|
|
||||||
</Layout>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Route
|
<Route path={URLS.SETTINGS}>{settingsRoutes}</Route>
|
||||||
path="/"
|
|
||||||
element={
|
|
||||||
<Navigate to={isAuthenticated ? URLS.FLOWS : URLS.LOGIN} replace />
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Route path={URLS.SETTINGS}>{settingsRoutes}</Route>
|
<Route path={URLS.ADMIN_SETTINGS}>{adminSettingsRoutes}</Route>
|
||||||
|
|
||||||
<Route path={URLS.ADMIN_SETTINGS}>{adminSettingsRoutes}</Route>
|
<Route
|
||||||
|
element={
|
||||||
<Route path="*" element={<NoResultFound />} />
|
<Layout>
|
||||||
</ReactRouterRoutes>
|
<div>404</div>
|
||||||
);
|
</Layout>
|
||||||
}
|
}
|
||||||
|
/>
|
||||||
export default <Routes />;
|
</Routes>
|
||||||
|
);
|
||||||
|
79
yarn.lock
79
yarn.lock
@@ -3952,6 +3952,11 @@
|
|||||||
resolved "https://registry.npmjs.org/@types/node/-/node-17.0.10.tgz"
|
resolved "https://registry.npmjs.org/@types/node/-/node-17.0.10.tgz"
|
||||||
integrity sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog==
|
integrity sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog==
|
||||||
|
|
||||||
|
"@types/node@>=8.1.0":
|
||||||
|
version "18.14.5"
|
||||||
|
resolved "https://registry.npmjs.org/@types/node/-/node-18.14.5.tgz"
|
||||||
|
integrity sha512-CRT4tMK/DHYhw1fcCEBwME9CSaZNclxfzVMe7GsO6ULSwsttbj70wSiX6rZdIjGblu93sTJxLdhNIT85KKI7Qw==
|
||||||
|
|
||||||
"@types/node@^12.0.0":
|
"@types/node@^12.0.0":
|
||||||
version "12.20.42"
|
version "12.20.42"
|
||||||
resolved "https://registry.npmjs.org/@types/node/-/node-12.20.42.tgz"
|
resolved "https://registry.npmjs.org/@types/node/-/node-12.20.42.tgz"
|
||||||
@@ -6367,6 +6372,19 @@ cookiejar@^2.1.4:
|
|||||||
resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b"
|
resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.4.tgz#ee669c1fea2cf42dc31585469d193fef0d65771b"
|
||||||
integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==
|
integrity sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==
|
||||||
|
|
||||||
|
copyfiles@^2.4.1:
|
||||||
|
version "2.4.1"
|
||||||
|
resolved "https://registry.npmjs.org/copyfiles/-/copyfiles-2.4.1.tgz"
|
||||||
|
integrity sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==
|
||||||
|
dependencies:
|
||||||
|
glob "^7.0.5"
|
||||||
|
minimatch "^3.0.3"
|
||||||
|
mkdirp "^1.0.4"
|
||||||
|
noms "0.0.0"
|
||||||
|
through2 "^2.0.1"
|
||||||
|
untildify "^4.0.0"
|
||||||
|
yargs "^16.1.0"
|
||||||
|
|
||||||
core-js-compat@^3.20.0, core-js-compat@^3.20.2:
|
core-js-compat@^3.20.0, core-js-compat@^3.20.2:
|
||||||
version "3.20.3"
|
version "3.20.3"
|
||||||
resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.20.3.tgz"
|
resolved "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.20.3.tgz"
|
||||||
@@ -8637,7 +8655,7 @@ glob-to-regexp@^0.4.1:
|
|||||||
resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz"
|
resolved "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz"
|
||||||
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
|
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
|
||||||
|
|
||||||
glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
|
glob@^7.0.5, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
|
||||||
version "7.2.0"
|
version "7.2.0"
|
||||||
resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz"
|
resolved "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz"
|
||||||
integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
|
integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==
|
||||||
@@ -8773,6 +8791,11 @@ graphql-tools@^8.2.0:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
"@apollo/client" "~3.2.5 || ~3.3.0 || ~3.4.0"
|
"@apollo/client" "~3.2.5 || ~3.3.0 || ~3.4.0"
|
||||||
|
|
||||||
|
graphql-type-json@^0.3.2:
|
||||||
|
version "0.3.2"
|
||||||
|
resolved "https://registry.npmjs.org/graphql-type-json/-/graphql-type-json-0.3.2.tgz"
|
||||||
|
integrity sha512-J+vjof74oMlCWXSvt0DOf2APEdZOCdubEvGDUAlqH//VBYcOYsGgRW7Xzorr44LvkjiuvecWc8fChxuZZbChtg==
|
||||||
|
|
||||||
graphql@^15.6.0:
|
graphql@^15.6.0:
|
||||||
version "15.8.0"
|
version "15.8.0"
|
||||||
resolved "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz"
|
resolved "https://registry.npmjs.org/graphql/-/graphql-15.8.0.tgz"
|
||||||
@@ -9226,7 +9249,7 @@ inflight@^1.0.4:
|
|||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
|
inherits@2, inherits@2.0.4, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, inherits@~2.0.3:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
|
resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz"
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
@@ -9648,6 +9671,11 @@ is-yarn-global@^0.3.0:
|
|||||||
resolved "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz"
|
resolved "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz"
|
||||||
integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==
|
integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==
|
||||||
|
|
||||||
|
isarray@0.0.1:
|
||||||
|
version "0.0.1"
|
||||||
|
resolved "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz"
|
||||||
|
integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
|
||||||
|
|
||||||
isarray@~1.0.0:
|
isarray@~1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
|
resolved "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
|
||||||
@@ -11032,6 +11060,13 @@ minimatch@3.0.4, minimatch@^3.0.4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion "^1.1.7"
|
brace-expansion "^1.1.7"
|
||||||
|
|
||||||
|
minimatch@^3.0.3:
|
||||||
|
version "3.1.2"
|
||||||
|
resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
|
||||||
|
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
|
||||||
|
dependencies:
|
||||||
|
brace-expansion "^1.1.7"
|
||||||
|
|
||||||
minimatch@^5.0.1:
|
minimatch@^5.0.1:
|
||||||
version "5.1.0"
|
version "5.1.0"
|
||||||
resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz"
|
resolved "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz"
|
||||||
@@ -11479,6 +11514,14 @@ nodemon@^2.0.13:
|
|||||||
undefsafe "^2.0.5"
|
undefsafe "^2.0.5"
|
||||||
update-notifier "^5.1.0"
|
update-notifier "^5.1.0"
|
||||||
|
|
||||||
|
noms@0.0.0:
|
||||||
|
version "0.0.0"
|
||||||
|
resolved "https://registry.npmjs.org/noms/-/noms-0.0.0.tgz"
|
||||||
|
integrity sha1-2o69nzr51nYJGbJ9nNyAkqczKFk=
|
||||||
|
dependencies:
|
||||||
|
inherits "^2.0.1"
|
||||||
|
readable-stream "~1.0.31"
|
||||||
|
|
||||||
nopt@^4.0.1:
|
nopt@^4.0.1:
|
||||||
version "4.0.3"
|
version "4.0.3"
|
||||||
resolved "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz"
|
resolved "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz"
|
||||||
@@ -13592,6 +13635,16 @@ readable-stream@^2.0.1, readable-stream@^2.0.6, readable-stream@^2.2.2, readable
|
|||||||
string_decoder "~1.1.1"
|
string_decoder "~1.1.1"
|
||||||
util-deprecate "~1.0.1"
|
util-deprecate "~1.0.1"
|
||||||
|
|
||||||
|
readable-stream@~1.0.31:
|
||||||
|
version "1.0.34"
|
||||||
|
resolved "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz"
|
||||||
|
integrity sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=
|
||||||
|
dependencies:
|
||||||
|
core-util-is "~1.0.0"
|
||||||
|
inherits "~2.0.1"
|
||||||
|
isarray "0.0.1"
|
||||||
|
string_decoder "~0.10.x"
|
||||||
|
|
||||||
readdir-scoped-modules@^1.0.0:
|
readdir-scoped-modules@^1.0.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz"
|
resolved "https://registry.npmjs.org/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz"
|
||||||
@@ -14718,6 +14771,11 @@ string_decoder@^1.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "~5.2.0"
|
safe-buffer "~5.2.0"
|
||||||
|
|
||||||
|
string_decoder@~0.10.x:
|
||||||
|
version "0.10.31"
|
||||||
|
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz"
|
||||||
|
integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
|
||||||
|
|
||||||
string_decoder@~1.1.1:
|
string_decoder@~1.1.1:
|
||||||
version "1.1.1"
|
version "1.1.1"
|
||||||
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz"
|
resolved "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz"
|
||||||
@@ -14804,6 +14862,14 @@ strip-literal@^1.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
acorn "^8.10.0"
|
acorn "^8.10.0"
|
||||||
|
|
||||||
|
stripe@^11.13.0:
|
||||||
|
version "11.13.0"
|
||||||
|
resolved "https://registry.npmjs.org/stripe/-/stripe-11.13.0.tgz"
|
||||||
|
integrity sha512-Jx0nDbdvRsTtDSX5OFQ+4rLmYIftoiOE9HAXWIgyhAz1QjRFI3UIiJ/kCyhkdJBoHu019O5Ya6EmQ5Zf635XDw==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" ">=8.1.0"
|
||||||
|
qs "^6.11.0"
|
||||||
|
|
||||||
strnum@^1.0.5:
|
strnum@^1.0.5:
|
||||||
version "1.0.5"
|
version "1.0.5"
|
||||||
resolved "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz"
|
resolved "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz"
|
||||||
@@ -15101,7 +15167,7 @@ throat@^6.0.1:
|
|||||||
resolved "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz"
|
resolved "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz"
|
||||||
integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==
|
integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==
|
||||||
|
|
||||||
through2@^2.0.0:
|
through2@^2.0.0, through2@^2.0.1:
|
||||||
version "2.0.5"
|
version "2.0.5"
|
||||||
resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz"
|
resolved "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz"
|
||||||
integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
|
integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==
|
||||||
@@ -15506,6 +15572,11 @@ unquote@~1.1.1:
|
|||||||
resolved "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz"
|
resolved "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz"
|
||||||
integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=
|
integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=
|
||||||
|
|
||||||
|
untildify@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz"
|
||||||
|
integrity sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==
|
||||||
|
|
||||||
upath@^1.2.0:
|
upath@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz"
|
resolved "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz"
|
||||||
@@ -16425,7 +16496,7 @@ yargs-parser@^20.2.2, yargs-parser@^20.2.3:
|
|||||||
resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz"
|
resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz"
|
||||||
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
|
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==
|
||||||
|
|
||||||
yargs@^16.2.0:
|
yargs@^16.1.0, yargs@^16.2.0:
|
||||||
version "16.2.0"
|
version "16.2.0"
|
||||||
resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz"
|
resolved "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz"
|
||||||
integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
|
integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
|
||||||
|
Reference in New Issue
Block a user