@budibase/server 0.9.185-alpha.1 → 0.9.185-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Dockerfile +1 -1
- package/builder/assets/bb-space-man.5be51a45.svg +290 -0
- package/builder/assets/index.4a7c5636.css +1 -0
- package/builder/assets/index.dc495306.js +1317 -0
- package/builder/assets/vendor.470042a4.js +152 -0
- package/builder/assets/vendor.5e1fe644.css +1 -0
- package/builder/index.html +4 -4
- package/coverage/clover.xml +689 -598
- package/coverage/coverage-final.json +89 -87
- package/coverage/lcov-report/api/controllers/analytics.js.html +2 -2
- package/coverage/lcov-report/api/controllers/apikeys.js.html +2 -2
- package/coverage/lcov-report/api/controllers/application.js.html +43 -13
- package/coverage/lcov-report/api/controllers/auth.js.html +7 -7
- package/coverage/lcov-report/api/controllers/automation.js.html +3 -3
- package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
- package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
- package/coverage/lcov-report/api/controllers/component.js.html +4 -4
- package/coverage/lcov-report/api/controllers/datasource.js.html +129 -21
- package/coverage/lcov-report/api/controllers/dev.js.html +16 -7
- package/coverage/lcov-report/api/controllers/hosting.js.html +10 -10
- package/coverage/lcov-report/api/controllers/index.html +83 -83
- package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
- package/coverage/lcov-report/api/controllers/layout.js.html +3 -3
- package/coverage/lcov-report/api/controllers/metadata.js.html +3 -3
- package/coverage/lcov-report/api/controllers/permission.js.html +3 -3
- package/coverage/lcov-report/api/controllers/query.js.html +48 -210
- package/coverage/lcov-report/api/controllers/role.js.html +9 -9
- package/coverage/lcov-report/api/controllers/routing.js.html +3 -3
- package/coverage/lcov-report/api/controllers/row/external.js.html +2 -2
- package/coverage/lcov-report/api/controllers/row/index.html +10 -10
- package/coverage/lcov-report/api/controllers/row/index.js.html +2 -2
- package/coverage/lcov-report/api/controllers/row/internal.js.html +9 -9
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +2 -2
- package/coverage/lcov-report/api/controllers/row/utils.js.html +2 -2
- package/coverage/lcov-report/api/controllers/screen.js.html +2 -2
- package/coverage/lcov-report/api/controllers/script.js.html +3 -3
- package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.html +11 -11
- package/coverage/lcov-report/api/controllers/table/index.js.html +3 -3
- package/coverage/lcov-report/api/controllers/table/internal.js.html +2 -2
- package/coverage/lcov-report/api/controllers/table/utils.js.html +8 -8
- package/coverage/lcov-report/api/controllers/templates.js.html +4 -4
- package/coverage/lcov-report/api/controllers/user.js.html +33 -18
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.html +9 -9
- package/coverage/lcov-report/api/controllers/view/index.js.html +5 -5
- package/coverage/lcov-report/api/controllers/view/utils.js.html +11 -11
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +3 -3
- package/coverage/lcov-report/api/controllers/webhook.js.html +4 -4
- package/coverage/lcov-report/api/index.html +1 -1
- package/coverage/lcov-report/api/index.js.html +1 -1
- package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
- package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/routes/application.js.html +1 -1
- package/coverage/lcov-report/api/routes/auth.js.html +1 -1
- package/coverage/lcov-report/api/routes/automation.js.html +1 -1
- package/coverage/lcov-report/api/routes/backup.js.html +1 -1
- package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
- package/coverage/lcov-report/api/routes/component.js.html +1 -1
- package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
- package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
- package/coverage/lcov-report/api/routes/dev.js.html +2 -2
- package/coverage/lcov-report/api/routes/hosting.js.html +1 -1
- package/coverage/lcov-report/api/routes/index.html +4 -4
- package/coverage/lcov-report/api/routes/index.js.html +1 -1
- package/coverage/lcov-report/api/routes/integration.js.html +1 -1
- package/coverage/lcov-report/api/routes/layout.js.html +1 -1
- package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
- package/coverage/lcov-report/api/routes/permission.js.html +1 -1
- package/coverage/lcov-report/api/routes/query.js.html +5 -2
- package/coverage/lcov-report/api/routes/role.js.html +1 -1
- package/coverage/lcov-report/api/routes/routing.js.html +1 -1
- package/coverage/lcov-report/api/routes/row.js.html +1 -1
- package/coverage/lcov-report/api/routes/screen.js.html +1 -1
- package/coverage/lcov-report/api/routes/script.js.html +1 -1
- package/coverage/lcov-report/api/routes/static.js.html +2 -2
- package/coverage/lcov-report/api/routes/table.js.html +1 -1
- package/coverage/lcov-report/api/routes/templates.js.html +1 -1
- package/coverage/lcov-report/api/routes/user.js.html +1 -1
- package/coverage/lcov-report/api/routes/view.js.html +1 -1
- package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/actions.js.html +2 -2
- package/coverage/lcov-report/automations/automationUtils.js.html +3 -3
- package/coverage/lcov-report/automations/bullboard.js.html +71 -20
- package/coverage/lcov-report/automations/index.html +33 -48
- package/coverage/lcov-report/automations/index.js.html +2 -2
- package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
- package/coverage/lcov-report/automations/steps/createRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
- package/coverage/lcov-report/automations/steps/deleteRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/discord.js.html +3 -3
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeScript.js.html +3 -3
- package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
- package/coverage/lcov-report/automations/steps/index.html +14 -14
- package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +3 -3
- package/coverage/lcov-report/automations/steps/queryRows.js.html +3 -3
- package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
- package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
- package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
- package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/utils.js.html +7 -7
- package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/app.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/cron.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.js.html +8 -8
- package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +2 -2
- package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +2 -2
- package/coverage/lcov-report/automations/triggers.js.html +22 -10
- package/coverage/lcov-report/automations/utils.js.html +42 -12
- package/coverage/lcov-report/constants/index.html +5 -5
- package/coverage/lcov-report/constants/index.js.html +25 -4
- package/coverage/lcov-report/constants/layouts.js.html +1 -1
- package/coverage/lcov-report/constants/screens.js.html +1 -1
- package/coverage/lcov-report/db/client.js.html +2 -2
- package/coverage/lcov-report/db/inMemoryView.js.html +2 -2
- package/coverage/lcov-report/db/index.html +2 -2
- package/coverage/lcov-report/db/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +6 -6
- package/coverage/lcov-report/db/linkedRows/index.html +10 -10
- package/coverage/lcov-report/db/linkedRows/index.js.html +5 -5
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +6 -6
- package/coverage/lcov-report/db/newid.js.html +1 -1
- package/coverage/lcov-report/db/utils.js.html +1 -1
- package/coverage/lcov-report/events/AutomationEmitter.js.html +6 -6
- package/coverage/lcov-report/events/index.html +6 -6
- package/coverage/lcov-report/events/index.js.html +1 -1
- package/coverage/lcov-report/events/utils.js.html +5 -5
- package/coverage/lcov-report/index.html +83 -68
- package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
- package/coverage/lcov-report/integrations/tests/index.html +1 -1
- package/coverage/lcov-report/middleware/appInfo.js.html +2 -2
- package/coverage/lcov-report/middleware/authorized.js.html +4 -4
- package/coverage/lcov-report/middleware/builder.js.html +16 -7
- package/coverage/lcov-report/middleware/currentapp.js.html +6 -6
- package/coverage/lcov-report/middleware/index.html +21 -21
- package/coverage/lcov-report/middleware/joi-validator.js.html +2 -2
- package/coverage/lcov-report/middleware/resourceId.js.html +18 -18
- package/coverage/lcov-report/middleware/selfhost.js.html +2 -2
- package/coverage/lcov-report/middleware/usageQuota.js.html +4 -4
- package/coverage/lcov-report/middleware/utils.js.html +1 -1
- package/coverage/lcov-report/{automations/thread.js.html → threads/automation.js.html} +83 -32
- package/coverage/lcov-report/threads/index.html +141 -0
- package/coverage/lcov-report/threads/index.js.html +260 -0
- package/coverage/lcov-report/threads/query.js.html +269 -0
- package/coverage/lcov-report/utilities/bcrypt.js.html +1 -1
- package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
- package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
- package/coverage/lcov-report/utilities/csvParser.js.html +2 -2
- package/coverage/lcov-report/utilities/global.js.html +2 -2
- package/coverage/lcov-report/utilities/index.html +21 -21
- package/coverage/lcov-report/utilities/index.js.html +12 -9
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +30 -9
- package/coverage/lcov-report/utilities/queue/index.html +14 -14
- package/coverage/lcov-report/utilities/routing/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.html +4 -4
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +2 -2
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +3 -3
- package/coverage/lcov-report/utilities/scriptRunner.js.html +16 -7
- package/coverage/lcov-report/utilities/security.js.html +3 -3
- package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
- package/coverage/lcov-report/utilities/users.js.html +1 -1
- package/coverage/lcov-report/utilities/workerRequests.js.html +5 -5
- package/coverage/lcov.info +1136 -972
- package/dist/api/controllers/application.js +11 -1
- package/dist/api/controllers/datasource.js +31 -7
- package/dist/api/controllers/deploy/index.js +2 -0
- package/dist/api/controllers/dev.js +4 -1
- package/dist/api/controllers/query.js +27 -57
- package/dist/api/controllers/user.js +10 -6
- package/dist/api/routes/query.js +1 -1
- package/dist/app.js +2 -11
- package/dist/automations/bullboard.js +37 -10
- package/dist/automations/triggers.js +7 -3
- package/dist/automations/utils.js +11 -2
- package/dist/constants/index.js +6 -0
- package/dist/integrations/base/IntegrationBase.js +2 -0
- package/dist/integrations/base/sql.js +36 -8
- package/dist/integrations/mysql.js +3 -1
- package/dist/integrations/utils.js +7 -1
- package/dist/middleware/builder.js +4 -1
- package/dist/package.json +7 -6
- package/dist/{automations/thread.js → threads/automation.js} +23 -7
- package/dist/threads/index.js +58 -0
- package/dist/threads/query.js +61 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/utilities/index.js +1 -0
- package/dist/utilities/queue/inMemoryQueue.js +8 -0
- package/dist/utilities/scriptRunner.js +4 -1
- package/package.json +8 -7
- package/scripts/likeCypress.ts +33 -0
- package/src/api/controllers/application.js +11 -1
- package/src/api/controllers/datasource.js +45 -9
- package/src/api/controllers/deploy/index.js +2 -0
- package/src/api/controllers/dev.js +4 -1
- package/src/api/controllers/query.js +26 -80
- package/src/api/controllers/user.js +15 -10
- package/src/api/routes/query.js +1 -0
- package/src/app.ts +2 -10
- package/src/automations/bullboard.js +28 -11
- package/src/automations/tests/automation.spec.js +3 -4
- package/src/automations/triggers.js +7 -3
- package/src/automations/utils.js +12 -2
- package/src/constants/index.js +7 -0
- package/src/integrations/airtable.ts +2 -1
- package/src/integrations/arangodb.ts +2 -1
- package/src/integrations/base/IntegrationBase.ts +6 -0
- package/src/integrations/base/datasourcePlus.ts +2 -1
- package/src/integrations/base/sql.ts +38 -9
- package/src/integrations/couchdb.ts +2 -1
- package/src/integrations/dynamodb.ts +2 -1
- package/src/integrations/elasticsearch.ts +2 -1
- package/src/integrations/mongodb.ts +2 -1
- package/src/integrations/mysql.ts +1 -1
- package/src/integrations/rest.ts +2 -1
- package/src/integrations/s3.ts +2 -1
- package/src/integrations/utils.ts +6 -1
- package/src/middleware/builder.js +4 -1
- package/src/{automations/thread.js → threads/automation.js} +24 -7
- package/src/threads/index.js +60 -0
- package/src/threads/query.js +63 -0
- package/src/utilities/index.js +1 -0
- package/src/utilities/queue/inMemoryQueue.js +7 -0
- package/src/utilities/scriptRunner.js +4 -1
- package/tsconfig.json +1 -1
- package/builder/assets/index.4feb6e69.js +0 -201
- package/builder/assets/index.a79ec0ef.css +0 -29
- package/builder/assets/vendor.278a305c.js +0 -9
- package/builder/assets/vendor.d75d5eb7.css +0 -1
|
@@ -27,6 +27,8 @@ const { getAllLocks } = require("../../utilities/redis");
|
|
|
27
27
|
const { updateClientLibrary, backupClientLibrary, revertClientLibrary, } = require("../../utilities/fileSystem/clientLibrary");
|
|
28
28
|
const { getTenantId, isMultiTenant } = require("@budibase/auth/tenancy");
|
|
29
29
|
const { syncGlobalUsers } = require("./user");
|
|
30
|
+
const { app: appCache } = require("@budibase/auth/cache");
|
|
31
|
+
const { cleanupAutomations } = require("../../automations/utils");
|
|
30
32
|
const URL_REGEX_SLASH = /\/|\\/g;
|
|
31
33
|
// utility function, need to do away with this
|
|
32
34
|
function getLayouts(db) {
|
|
@@ -214,6 +216,7 @@ exports.create = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
214
216
|
if (!env.isTest()) {
|
|
215
217
|
yield createApp(appId);
|
|
216
218
|
}
|
|
219
|
+
yield appCache.invalidateAppMetadata(appId, newApplication);
|
|
217
220
|
ctx.status = 200;
|
|
218
221
|
ctx.body = newApplication;
|
|
219
222
|
});
|
|
@@ -268,8 +271,12 @@ exports.delete = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
268
271
|
if (!env.isTest() && !ctx.query.unpublish) {
|
|
269
272
|
yield deleteApp(ctx.params.appId);
|
|
270
273
|
}
|
|
274
|
+
if (ctx.query && ctx.query.unpublish) {
|
|
275
|
+
yield cleanupAutomations(ctx.params.appId);
|
|
276
|
+
}
|
|
271
277
|
// make sure the app/role doesn't stick around after the app has been deleted
|
|
272
278
|
yield removeAppFromUserRoles(ctx, ctx.params.appId);
|
|
279
|
+
yield appCache.invalidateAppMetadata(ctx.params.appId);
|
|
273
280
|
ctx.status = 200;
|
|
274
281
|
ctx.body = result;
|
|
275
282
|
});
|
|
@@ -331,7 +338,10 @@ const updateAppPackage = (ctx, appPackage, appId) => __awaiter(void 0, void 0, v
|
|
|
331
338
|
// the locked by property is attached by server but generated from
|
|
332
339
|
// Redis, shouldn't ever store it
|
|
333
340
|
delete newAppPackage.lockedBy;
|
|
334
|
-
|
|
341
|
+
const response = yield db.put(newAppPackage);
|
|
342
|
+
// remove any cached metadata, so that it will be updated
|
|
343
|
+
yield appCache.invalidateAppMetadata(appId);
|
|
344
|
+
return response;
|
|
335
345
|
});
|
|
336
346
|
const createEmptyAppPackage = (ctx, app) => __awaiter(void 0, void 0, void 0, function* () {
|
|
337
347
|
const db = new CouchDB(app.appId);
|
|
@@ -10,7 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
const CouchDB = require("../../db");
|
|
12
12
|
const { generateDatasourceID, getDatasourceParams, getQueryParams, DocumentTypes, BudibaseInternalDB, getTableParams, } = require("../../db/utils");
|
|
13
|
-
const { BuildSchemaErrors } = require("../../constants");
|
|
13
|
+
const { BuildSchemaErrors, InvalidColumns } = require("../../constants");
|
|
14
14
|
const { integrations } = require("../../integrations");
|
|
15
15
|
const { getDatasourceAndQuery } = require("./row/utils");
|
|
16
16
|
exports.fetch = function (ctx) {
|
|
@@ -97,8 +97,12 @@ exports.destroy = function (ctx) {
|
|
|
97
97
|
return __awaiter(this, void 0, void 0, function* () {
|
|
98
98
|
const db = new CouchDB(ctx.appId);
|
|
99
99
|
// Delete all queries for the datasource
|
|
100
|
-
const
|
|
101
|
-
yield db.bulkDocs(
|
|
100
|
+
const queries = yield db.allDocs(getQueryParams(ctx.params.datasourceId, null));
|
|
101
|
+
yield db.bulkDocs(queries.rows.map(row => ({
|
|
102
|
+
_id: row.id,
|
|
103
|
+
_rev: row.value.rev,
|
|
104
|
+
_deleted: true,
|
|
105
|
+
})));
|
|
102
106
|
// delete the datasource
|
|
103
107
|
yield db.remove(ctx.params.datasourceId, ctx.params.revId);
|
|
104
108
|
ctx.message = `Datasource deleted.`;
|
|
@@ -123,6 +127,21 @@ exports.query = function (ctx) {
|
|
|
123
127
|
}
|
|
124
128
|
});
|
|
125
129
|
};
|
|
130
|
+
function getErrorTables(errors, errorType) {
|
|
131
|
+
return Object.entries(errors)
|
|
132
|
+
.filter(entry => entry[1] === errorType)
|
|
133
|
+
.map(([name]) => name);
|
|
134
|
+
}
|
|
135
|
+
function updateError(error, newError, tables) {
|
|
136
|
+
if (!error) {
|
|
137
|
+
error = "";
|
|
138
|
+
}
|
|
139
|
+
if (error.length > 0) {
|
|
140
|
+
error += "\n";
|
|
141
|
+
}
|
|
142
|
+
error += `${newError} ${tables.join(", ")}`;
|
|
143
|
+
return error;
|
|
144
|
+
}
|
|
126
145
|
const buildSchemaHelper = (datasource) => __awaiter(void 0, void 0, void 0, function* () {
|
|
127
146
|
const Connector = integrations[datasource.source];
|
|
128
147
|
// Connect to the DB and build the schema
|
|
@@ -142,10 +161,15 @@ const buildSchemaHelper = (datasource) => __awaiter(void 0, void 0, void 0, func
|
|
|
142
161
|
const errors = connector.schemaErrors;
|
|
143
162
|
let error = null;
|
|
144
163
|
if (errors && Object.keys(errors).length > 0) {
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
164
|
+
const noKey = getErrorTables(errors, BuildSchemaErrors.NO_KEY);
|
|
165
|
+
const invalidCol = getErrorTables(errors, BuildSchemaErrors.INVALID_COLUMN);
|
|
166
|
+
if (noKey.length) {
|
|
167
|
+
error = updateError(error, "No primary key constraint found for the following:", noKey);
|
|
168
|
+
}
|
|
169
|
+
if (invalidCol.length) {
|
|
170
|
+
const invalidCols = Object.values(InvalidColumns).join(", ");
|
|
171
|
+
error = updateError(error, `Cannot use columns ${invalidCols} found in following:`, invalidCol);
|
|
172
|
+
}
|
|
149
173
|
}
|
|
150
174
|
return { tables: connector.tables, error };
|
|
151
175
|
});
|
|
@@ -13,6 +13,7 @@ const Deployment = require("./Deployment");
|
|
|
13
13
|
const { Replication, getDeployedAppID } = require("@budibase/auth/db");
|
|
14
14
|
const { DocumentTypes, getAutomationParams } = require("../../../db/utils");
|
|
15
15
|
const { disableAllCrons, enableCronTrigger, } = require("../../../automations/utils");
|
|
16
|
+
const { app: appCache } = require("@budibase/auth/cache");
|
|
16
17
|
// the max time we can wait for an invalidation to complete before considering it failed
|
|
17
18
|
const MAX_PENDING_TIME_MS = 30 * 60000;
|
|
18
19
|
const DeploymentStatus = {
|
|
@@ -95,6 +96,7 @@ function deployApp(deployment) {
|
|
|
95
96
|
appDoc.appId = productionAppId;
|
|
96
97
|
appDoc.instance._id = productionAppId;
|
|
97
98
|
yield db.put(appDoc);
|
|
99
|
+
yield appCache.invalidateAppMetadata(productionAppId);
|
|
98
100
|
console.log("New app doc written successfully.");
|
|
99
101
|
yield initDeployedApp(productionAppId);
|
|
100
102
|
console.log("Deployed app initialised, setting deployment to successful");
|
|
@@ -16,6 +16,7 @@ const { request } = require("../../utilities/workerRequests");
|
|
|
16
16
|
const { clearLock } = require("../../utilities/redis");
|
|
17
17
|
const { Replication } = require("@budibase/auth").db;
|
|
18
18
|
const { DocumentTypes } = require("../../db/utils");
|
|
19
|
+
const { app: appCache } = require("@budibase/auth/cache");
|
|
19
20
|
function redirect(ctx, method, path = "global") {
|
|
20
21
|
return __awaiter(this, void 0, void 0, function* () {
|
|
21
22
|
const { devPath } = ctx.params;
|
|
@@ -25,7 +26,8 @@ function redirect(ctx, method, path = "global") {
|
|
|
25
26
|
body: ctx.request.body,
|
|
26
27
|
}, true));
|
|
27
28
|
if (response.status !== 200) {
|
|
28
|
-
|
|
29
|
+
const err = yield response.text();
|
|
30
|
+
ctx.throw(400, err);
|
|
29
31
|
}
|
|
30
32
|
const cookie = response.headers.get("set-cookie");
|
|
31
33
|
if (cookie) {
|
|
@@ -102,6 +104,7 @@ exports.revert = (ctx) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
102
104
|
appDoc.appId = appId;
|
|
103
105
|
appDoc.instance._id = appId;
|
|
104
106
|
yield db.put(appDoc);
|
|
107
|
+
yield appCache.invalidateAppMetadata(appId);
|
|
105
108
|
ctx.body = {
|
|
106
109
|
message: "Reverted changes successfully.",
|
|
107
110
|
};
|
|
@@ -11,10 +11,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
const { processString } = require("@budibase/string-templates");
|
|
12
12
|
const CouchDB = require("../../db");
|
|
13
13
|
const { generateQueryID, getQueryParams } = require("../../db/utils");
|
|
14
|
-
const { integrations } = require("../../integrations");
|
|
15
14
|
const { BaseQueryVerbs } = require("../../constants");
|
|
16
15
|
const env = require("../../environment");
|
|
17
|
-
const
|
|
16
|
+
const { Thread, ThreadType } = require("../../threads");
|
|
17
|
+
const Runner = new Thread(ThreadType.QUERY, { timeoutMs: 10000 });
|
|
18
18
|
// simple function to append "readable" to all read queries
|
|
19
19
|
function enrichQueries(input) {
|
|
20
20
|
const wasArray = Array.isArray(input);
|
|
@@ -26,38 +26,6 @@ function enrichQueries(input) {
|
|
|
26
26
|
}
|
|
27
27
|
return wasArray ? queries : queries[0];
|
|
28
28
|
}
|
|
29
|
-
function formatResponse(resp) {
|
|
30
|
-
if (typeof resp === "string") {
|
|
31
|
-
try {
|
|
32
|
-
resp = JSON.parse(resp);
|
|
33
|
-
}
|
|
34
|
-
catch (err) {
|
|
35
|
-
resp = { response: resp };
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
return resp;
|
|
39
|
-
}
|
|
40
|
-
function runAndTransform(integration, queryVerb, enrichedQuery, transformer) {
|
|
41
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
-
let rows = formatResponse(yield integration[queryVerb](enrichedQuery));
|
|
43
|
-
// transform as required
|
|
44
|
-
if (transformer) {
|
|
45
|
-
const runner = new ScriptRunner(transformer, { data: rows });
|
|
46
|
-
rows = runner.execute();
|
|
47
|
-
}
|
|
48
|
-
// needs to an array for next step
|
|
49
|
-
if (!Array.isArray(rows)) {
|
|
50
|
-
rows = [rows];
|
|
51
|
-
}
|
|
52
|
-
// map into JSON if just raw primitive here
|
|
53
|
-
if (rows.find(row => typeof row !== "object")) {
|
|
54
|
-
rows = rows.map(value => ({ value }));
|
|
55
|
-
}
|
|
56
|
-
// get all the potential fields in the schema
|
|
57
|
-
let keys = rows.flatMap(Object.keys);
|
|
58
|
-
return { rows, keys };
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
29
|
exports.fetch = function (ctx) {
|
|
62
30
|
return __awaiter(this, void 0, void 0, function* () {
|
|
63
31
|
const db = new CouchDB(ctx.appId);
|
|
@@ -135,21 +103,22 @@ exports.preview = function (ctx) {
|
|
|
135
103
|
return __awaiter(this, void 0, void 0, function* () {
|
|
136
104
|
const db = new CouchDB(ctx.appId);
|
|
137
105
|
const datasource = yield db.get(ctx.request.body.datasourceId);
|
|
138
|
-
const Integration = integrations[datasource.source];
|
|
139
|
-
if (!Integration) {
|
|
140
|
-
ctx.throw(400, "Integration type does not exist.");
|
|
141
|
-
}
|
|
142
106
|
const { fields, parameters, queryVerb, transformer } = ctx.request.body;
|
|
143
107
|
const enrichedQuery = yield enrichQueryFields(fields, parameters);
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
108
|
+
try {
|
|
109
|
+
const { rows, keys } = yield Runner.run({
|
|
110
|
+
datasource,
|
|
111
|
+
queryVerb,
|
|
112
|
+
query: enrichedQuery,
|
|
113
|
+
transformer,
|
|
114
|
+
});
|
|
115
|
+
ctx.body = {
|
|
116
|
+
rows,
|
|
117
|
+
schemaFields: [...new Set(keys)],
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
ctx.throw(400, err);
|
|
153
122
|
}
|
|
154
123
|
});
|
|
155
124
|
};
|
|
@@ -158,18 +127,19 @@ exports.execute = function (ctx) {
|
|
|
158
127
|
const db = new CouchDB(ctx.appId);
|
|
159
128
|
const query = yield db.get(ctx.params.queryId);
|
|
160
129
|
const datasource = yield db.get(query.datasourceId);
|
|
161
|
-
const Integration = integrations[datasource.source];
|
|
162
|
-
if (!Integration) {
|
|
163
|
-
ctx.throw(400, "Integration type does not exist.");
|
|
164
|
-
}
|
|
165
130
|
const enrichedQuery = yield enrichQueryFields(query.fields, ctx.request.body.parameters);
|
|
166
|
-
const integration = new Integration(datasource.config);
|
|
167
131
|
// call the relevant CRUD method on the integration class
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
132
|
+
try {
|
|
133
|
+
const { rows } = yield Runner.run({
|
|
134
|
+
datasource,
|
|
135
|
+
queryVerb: query.queryVerb,
|
|
136
|
+
query: enrichedQuery,
|
|
137
|
+
transformer: query.transformer,
|
|
138
|
+
});
|
|
139
|
+
ctx.body = rows;
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
ctx.throw(400, err);
|
|
173
143
|
}
|
|
174
144
|
});
|
|
175
145
|
};
|
|
@@ -94,6 +94,7 @@ exports.syncUser = function (ctx) {
|
|
|
94
94
|
.map(([appId]) => appId);
|
|
95
95
|
}
|
|
96
96
|
for (let prodAppId of prodAppIds) {
|
|
97
|
+
const roleId = roles[prodAppId];
|
|
97
98
|
const devAppId = getDevelopmentAppID(prodAppId);
|
|
98
99
|
for (let appId of [prodAppId, devAppId]) {
|
|
99
100
|
if (!(yield doesDatabaseExist(appId))) {
|
|
@@ -113,14 +114,17 @@ exports.syncUser = function (ctx) {
|
|
|
113
114
|
tableId: InternalTables.USER_METADATA,
|
|
114
115
|
};
|
|
115
116
|
}
|
|
116
|
-
|
|
117
|
-
if (
|
|
118
|
-
|
|
117
|
+
// assign the roleId for the metadata doc
|
|
118
|
+
if (roleId) {
|
|
119
|
+
metadata.roleId = roleId;
|
|
119
120
|
}
|
|
120
|
-
|
|
121
|
-
|
|
121
|
+
let combined = !deleting
|
|
122
|
+
? combineMetadataAndUser(user, metadata)
|
|
123
|
+
: Object.assign(Object.assign({}, metadata), { status: UserStatus.INACTIVE, metadata: BUILTIN_ROLE_IDS.PUBLIC });
|
|
124
|
+
// if its null then there was no updates required
|
|
125
|
+
if (combined) {
|
|
126
|
+
yield db.put(combined);
|
|
122
127
|
}
|
|
123
|
-
yield db.put(combined);
|
|
124
128
|
}
|
|
125
129
|
}
|
|
126
130
|
ctx.body = {
|
package/dist/api/routes/query.js
CHANGED
|
@@ -41,7 +41,7 @@ router
|
|
|
41
41
|
.get("/api/queries", authorized(BUILDER), queryController.fetch)
|
|
42
42
|
.post("/api/queries", bodySubResource("datasourceId", "_id"), authorized(BUILDER), generateQueryValidation(), queryController.save)
|
|
43
43
|
.post("/api/queries/preview", bodyResource("datasourceId"), authorized(BUILDER), generateQueryPreviewValidation(), queryController.preview)
|
|
44
|
-
.get("/api/queries/:queryId", authorized(PermissionTypes.QUERY, PermissionLevels.READ), queryController.find)
|
|
44
|
+
.get("/api/queries/:queryId", paramResource("queryId"), authorized(PermissionTypes.QUERY, PermissionLevels.READ), queryController.find)
|
|
45
45
|
.post("/api/queries/:queryId", paramResource("queryId"), authorized(PermissionTypes.QUERY, PermissionLevels.WRITE), queryController.execute)
|
|
46
46
|
.delete("/api/queries/:queryId/:revId", paramResource("queryId"), authorized(BUILDER), queryController.destroy);
|
|
47
47
|
module.exports = router;
|
package/dist/app.js
CHANGED
|
@@ -41,17 +41,8 @@ app.use(pino({
|
|
|
41
41
|
level: env.LOG_LEVEL || "error",
|
|
42
42
|
}));
|
|
43
43
|
if (!env.isTest()) {
|
|
44
|
-
const
|
|
45
|
-
app.use(
|
|
46
|
-
if (ctx.path.startsWith(bullboard.pathPrefix)) {
|
|
47
|
-
ctx.status = 200;
|
|
48
|
-
ctx.respond = false;
|
|
49
|
-
bullApp(ctx.req, ctx.res);
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
yield next();
|
|
53
|
-
}
|
|
54
|
-
}));
|
|
44
|
+
const plugin = bullboard.init();
|
|
45
|
+
app.use(plugin);
|
|
55
46
|
}
|
|
56
47
|
app.context.eventEmitter = eventEmitter;
|
|
57
48
|
app.context.auth = {};
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
const { createBullBoard } = require("@bull-board/api");
|
|
12
|
+
const { BullAdapter } = require("@bull-board/api/bullAdapter");
|
|
13
|
+
const { KoaAdapter } = require("@bull-board/koa");
|
|
5
14
|
const env = require("../environment");
|
|
6
15
|
const Queue = env.isTest()
|
|
7
16
|
? require("../utilities/queue/inMemoryQueue")
|
|
@@ -9,19 +18,37 @@ const Queue = env.isTest()
|
|
|
9
18
|
const { JobQueues } = require("../constants");
|
|
10
19
|
const { utils } = require("@budibase/auth/redis");
|
|
11
20
|
const { opts, redisProtocolUrl } = utils.getRedisOptions();
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
21
|
+
const CLEANUP_PERIOD_MS = 60 * 1000;
|
|
22
|
+
const queueConfig = redisProtocolUrl || { redis: opts };
|
|
23
|
+
let cleanupInternal = null;
|
|
24
|
+
let automationQueue = new Queue(JobQueues.AUTOMATIONS, queueConfig);
|
|
25
|
+
function cleanup() {
|
|
26
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
27
|
+
yield automationQueue.clean(CLEANUP_PERIOD_MS, "completed");
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
const PATH_PREFIX = "/bulladmin";
|
|
15
31
|
exports.init = () => {
|
|
16
|
-
|
|
32
|
+
// cleanup the events every 5 minutes
|
|
33
|
+
if (!cleanupInternal) {
|
|
34
|
+
cleanupInternal = setInterval(cleanup, CLEANUP_PERIOD_MS);
|
|
35
|
+
// fire off an initial cleanup
|
|
36
|
+
cleanup().catch(err => {
|
|
37
|
+
console.error(`Unable to cleanup automation queue initially - ${err}`);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
17
40
|
// Set up queues for bull board admin
|
|
18
41
|
const queues = [automationQueue];
|
|
19
42
|
const adapters = [];
|
|
43
|
+
const serverAdapter = new KoaAdapter();
|
|
20
44
|
for (let queue of queues) {
|
|
21
45
|
adapters.push(new BullAdapter(queue));
|
|
22
46
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
47
|
+
createBullBoard({
|
|
48
|
+
queues: adapters,
|
|
49
|
+
serverAdapter,
|
|
50
|
+
});
|
|
51
|
+
serverAdapter.setBasePath(PATH_PREFIX);
|
|
52
|
+
return serverAdapter.registerPlugin();
|
|
26
53
|
};
|
|
27
54
|
exports.queue = automationQueue;
|
|
@@ -20,6 +20,10 @@ const { checkTestFlag } = require("../utilities/redis");
|
|
|
20
20
|
const utils = require("./utils");
|
|
21
21
|
const env = require("../environment");
|
|
22
22
|
const TRIGGER_DEFINITIONS = definitions;
|
|
23
|
+
const JOB_OPTS = {
|
|
24
|
+
removeOnComplete: true,
|
|
25
|
+
removeOnFail: true,
|
|
26
|
+
};
|
|
23
27
|
function queueRelevantRowAutomations(event, eventType) {
|
|
24
28
|
return __awaiter(this, void 0, void 0, function* () {
|
|
25
29
|
if (event.appId == null) {
|
|
@@ -47,7 +51,7 @@ function queueRelevantRowAutomations(event, eventType) {
|
|
|
47
51
|
}
|
|
48
52
|
if (automationTrigger.inputs &&
|
|
49
53
|
automationTrigger.inputs.tableId === event.row.tableId) {
|
|
50
|
-
yield queue.add({ automation, event });
|
|
54
|
+
yield queue.add({ automation, event }, JOB_OPTS);
|
|
51
55
|
}
|
|
52
56
|
}
|
|
53
57
|
});
|
|
@@ -85,7 +89,7 @@ exports.externalTrigger = function (automation, params, { getResponses } = {}) {
|
|
|
85
89
|
automation.definition.trigger != null &&
|
|
86
90
|
automation.definition.trigger.stepId === definitions.APP.stepId &&
|
|
87
91
|
automation.definition.trigger.stepId === "APP" &&
|
|
88
|
-
!checkTestFlag(automation._id)) {
|
|
92
|
+
!(yield checkTestFlag(automation._id))) {
|
|
89
93
|
// values are likely to be submitted as strings, so we shall convert to correct type
|
|
90
94
|
const coercedFields = {};
|
|
91
95
|
const fields = automation.definition.trigger.inputs.fields;
|
|
@@ -99,7 +103,7 @@ exports.externalTrigger = function (automation, params, { getResponses } = {}) {
|
|
|
99
103
|
return utils.processEvent({ data });
|
|
100
104
|
}
|
|
101
105
|
else {
|
|
102
|
-
return queue.add(data);
|
|
106
|
+
return queue.add(data, JOB_OPTS);
|
|
103
107
|
}
|
|
104
108
|
});
|
|
105
109
|
};
|
|
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
-
const
|
|
11
|
+
const { Thread, ThreadType } = require("../threads");
|
|
12
12
|
const { definitions } = require("./triggerInfo");
|
|
13
13
|
const webhooks = require("../api/controllers/webhook");
|
|
14
14
|
const CouchDB = require("../db");
|
|
@@ -19,10 +19,11 @@ const { MetadataTypes } = require("../constants");
|
|
|
19
19
|
const { getDeployedAppID } = require("@budibase/auth/db");
|
|
20
20
|
const WH_STEP_ID = definitions.WEBHOOK.stepId;
|
|
21
21
|
const CRON_STEP_ID = definitions.CRON.stepId;
|
|
22
|
+
const Runner = new Thread(ThreadType.AUTOMATION);
|
|
22
23
|
exports.processEvent = (job) => __awaiter(void 0, void 0, void 0, function* () {
|
|
23
24
|
try {
|
|
24
25
|
// need to actually await these so that an error can be captured properly
|
|
25
|
-
return yield
|
|
26
|
+
return yield Runner.run(job);
|
|
26
27
|
}
|
|
27
28
|
catch (err) {
|
|
28
29
|
console.error(`${job.data.automation.appId} automation ${job.data.automation._id} was unable to run - ${err}`);
|
|
@@ -146,3 +147,11 @@ exports.checkForWebhooks = ({ appId, oldAuto, newAuto }) => __awaiter(void 0, vo
|
|
|
146
147
|
}
|
|
147
148
|
return newAuto;
|
|
148
149
|
});
|
|
150
|
+
/**
|
|
151
|
+
* When removing an app/unpublishing it need to make sure automations are cleaned up (cron).
|
|
152
|
+
* @param appId {string} the app that is being removed.
|
|
153
|
+
* @return {Promise<void>} clean is complete if this succeeds.
|
|
154
|
+
*/
|
|
155
|
+
exports.cleanupAutomations = (appId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
156
|
+
yield exports.disableAllCrons(appId);
|
|
157
|
+
});
|
package/dist/constants/index.js
CHANGED
|
@@ -150,8 +150,14 @@ exports.MetadataTypes = {
|
|
|
150
150
|
AUTOMATION_TEST_INPUT: "automationTestInput",
|
|
151
151
|
AUTOMATION_TEST_HISTORY: "automationTestHistory",
|
|
152
152
|
};
|
|
153
|
+
exports.InvalidColumns = {
|
|
154
|
+
ID: "_id",
|
|
155
|
+
REV: "_rev",
|
|
156
|
+
TABLE_ID: "tableId",
|
|
157
|
+
};
|
|
153
158
|
exports.BuildSchemaErrors = {
|
|
154
159
|
NO_KEY: "no_key",
|
|
160
|
+
INVALID_COLUMN: "invalid_column",
|
|
155
161
|
};
|
|
156
162
|
// pass through the list from the auth/core lib
|
|
157
163
|
exports.ObjectStoreBuckets = ObjectStoreBuckets;
|
|
@@ -17,19 +17,46 @@ const datasource_1 = require("../../definitions/datasource");
|
|
|
17
17
|
const utils_1 = require("../utils");
|
|
18
18
|
const sqlTable_1 = __importDefault(require("./sqlTable"));
|
|
19
19
|
const BASE_LIMIT = 5000;
|
|
20
|
+
// these are invalid dates sent by the client, need to convert them to a real max date
|
|
21
|
+
const MIN_ISO_DATE = "0000-00-00T00:00:00.000Z";
|
|
22
|
+
const MAX_ISO_DATE = "9999-00-00T00:00:00.000Z";
|
|
23
|
+
function parse(input) {
|
|
24
|
+
if (Array.isArray(input)) {
|
|
25
|
+
return JSON.stringify(input);
|
|
26
|
+
}
|
|
27
|
+
if (typeof input !== "string") {
|
|
28
|
+
return input;
|
|
29
|
+
}
|
|
30
|
+
if (input === MAX_ISO_DATE) {
|
|
31
|
+
return new Date(8640000000000000);
|
|
32
|
+
}
|
|
33
|
+
if (input === MIN_ISO_DATE) {
|
|
34
|
+
return new Date(-8640000000000000);
|
|
35
|
+
}
|
|
36
|
+
if (utils_1.isIsoDateString(input)) {
|
|
37
|
+
return new Date(input);
|
|
38
|
+
}
|
|
39
|
+
return input;
|
|
40
|
+
}
|
|
20
41
|
function parseBody(body) {
|
|
21
42
|
for (let [key, value] of Object.entries(body)) {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
43
|
+
body[key] = parse(value);
|
|
44
|
+
}
|
|
45
|
+
return body;
|
|
46
|
+
}
|
|
47
|
+
function parseFilters(filters) {
|
|
48
|
+
for (let [key, value] of Object.entries(filters)) {
|
|
49
|
+
let parsed;
|
|
50
|
+
if (typeof value === "object") {
|
|
51
|
+
parsed = parseFilters(value);
|
|
27
52
|
}
|
|
28
|
-
|
|
29
|
-
|
|
53
|
+
else {
|
|
54
|
+
parsed = parse(value);
|
|
30
55
|
}
|
|
56
|
+
// @ts-ignore
|
|
57
|
+
filters[key] = parsed;
|
|
31
58
|
}
|
|
32
|
-
return
|
|
59
|
+
return filters;
|
|
33
60
|
}
|
|
34
61
|
class InternalBuilder {
|
|
35
62
|
constructor(client) {
|
|
@@ -45,6 +72,7 @@ class InternalBuilder {
|
|
|
45
72
|
if (!filters) {
|
|
46
73
|
return query;
|
|
47
74
|
}
|
|
75
|
+
filters = parseFilters(filters);
|
|
48
76
|
// if all or specified in filters, then everything is an or
|
|
49
77
|
const allOr = filters.allOr;
|
|
50
78
|
if (filters.oneOf) {
|
|
@@ -147,7 +147,9 @@ var MySQLModule;
|
|
|
147
147
|
});
|
|
148
148
|
}
|
|
149
149
|
read(query) {
|
|
150
|
-
return
|
|
150
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
151
|
+
return internalQuery(this.client, utils_1.getSqlQuery(query));
|
|
152
|
+
});
|
|
151
153
|
}
|
|
152
154
|
update(query) {
|
|
153
155
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.finaliseExternalTables = exports.isIsoDateString = exports.isSQL = exports.getSqlQuery = exports.convertSqlType = exports.breakRowIdField = exports.convertRowId = exports.isRowId = exports.generateRowIdField = exports.breakExternalTableId = exports.buildExternalTableId = exports.isExternalTable = exports.SqlClients = void 0;
|
|
4
4
|
const datasource_1 = require("../definitions/datasource");
|
|
5
5
|
const { DocumentTypes, SEPARATOR } = require("../db/utils");
|
|
6
|
-
const { FieldTypes, BuildSchemaErrors } = require("../constants");
|
|
6
|
+
const { FieldTypes, BuildSchemaErrors, InvalidColumns } = require("../constants");
|
|
7
7
|
const DOUBLE_SEPARATOR = `${SEPARATOR}${SEPARATOR}`;
|
|
8
8
|
const ROW_ID_REGEX = /^\[.*]$/g;
|
|
9
9
|
const SQL_TYPE_MAP = {
|
|
@@ -151,14 +151,20 @@ function copyExistingPropsOver(tableName, table, entities) {
|
|
|
151
151
|
return table;
|
|
152
152
|
}
|
|
153
153
|
function finaliseExternalTables(tables, entities) {
|
|
154
|
+
const invalidColumns = Object.values(InvalidColumns);
|
|
154
155
|
const finalTables = {};
|
|
155
156
|
const errors = {};
|
|
156
157
|
for (let [name, table] of Object.entries(tables)) {
|
|
158
|
+
const schemaFields = Object.keys(table.schema);
|
|
157
159
|
// make sure every table has a key
|
|
158
160
|
if (table.primary == null || table.primary.length === 0) {
|
|
159
161
|
errors[name] = BuildSchemaErrors.NO_KEY;
|
|
160
162
|
continue;
|
|
161
163
|
}
|
|
164
|
+
else if (schemaFields.find(field => invalidColumns.includes(field))) {
|
|
165
|
+
errors[name] = BuildSchemaErrors.INVALID_COLUMN;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
162
168
|
// make sure all previous props have been added back
|
|
163
169
|
finalTables[name] = copyExistingPropsOver(name, table, entities);
|
|
164
170
|
}
|
|
@@ -13,6 +13,7 @@ const { doesUserHaveLock, updateLock, checkDebounce, setDebounce, } = require(".
|
|
|
13
13
|
const CouchDB = require("../db");
|
|
14
14
|
const { DocumentTypes } = require("../db/utils");
|
|
15
15
|
const { PermissionTypes } = require("@budibase/auth/permissions");
|
|
16
|
+
const { app: appCache } = require("@budibase/auth/cache");
|
|
16
17
|
const DEBOUNCE_TIME_SEC = 30;
|
|
17
18
|
/************************************************** *
|
|
18
19
|
* This middleware has been broken out of the *
|
|
@@ -51,7 +52,9 @@ function updateAppUpdatedAt(ctx) {
|
|
|
51
52
|
const db = new CouchDB(appId);
|
|
52
53
|
const metadata = yield db.get(DocumentTypes.APP_METADATA);
|
|
53
54
|
metadata.updatedAt = new Date().toISOString();
|
|
54
|
-
yield db.put(metadata);
|
|
55
|
+
const response = yield db.put(metadata);
|
|
56
|
+
metadata._rev = response.rev;
|
|
57
|
+
yield appCache.invalidateAppMetadata(appId, metadata);
|
|
55
58
|
// set a new debounce record with a short TTL
|
|
56
59
|
yield setDebounce(appId, DEBOUNCE_TIME_SEC);
|
|
57
60
|
});
|