@budibase/server 2.5.8 → 2.5.10-alpha.0
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/builder/assets/index.24635afb.js +1794 -0
- package/builder/assets/index.4eae16b2.css +6 -0
- package/builder/index.html +2 -2
- package/dist/api/controllers/application.js +3 -4
- package/dist/api/controllers/automation.js +13 -7
- package/dist/api/controllers/datasource.js +1 -1
- package/dist/api/controllers/dev.js +1 -1
- package/dist/api/controllers/ops.js +40 -0
- package/dist/api/controllers/plugin/index.js +6 -37
- package/dist/api/controllers/query/index.js +2 -2
- package/dist/api/controllers/row/ExternalRequest.js +21 -14
- package/dist/api/controllers/table/utils.js +9 -3
- package/dist/api/controllers/user.js +1 -83
- package/dist/api/index.js +1 -2
- package/dist/api/routes/index.js +2 -2
- package/dist/api/routes/{cloud.js → ops.js} +19 -6
- package/dist/api/routes/user.js +0 -1
- package/dist/app.js +4 -13
- package/dist/automations/actions.js +32 -6
- package/dist/automations/index.js +3 -2
- package/dist/automations/steps/bash.js +6 -6
- package/dist/automations/steps/createRow.js +11 -11
- package/dist/automations/steps/delay.js +3 -3
- package/dist/automations/steps/deleteRow.js +8 -8
- package/dist/automations/steps/discord.js +8 -8
- package/dist/automations/steps/executeQuery.js +9 -9
- package/dist/automations/steps/executeScript.js +6 -6
- package/dist/automations/steps/filter.js +6 -6
- package/dist/automations/steps/integromat.js +10 -10
- package/dist/automations/steps/loop.js +9 -9
- package/dist/automations/steps/outgoingWebhook.js +10 -10
- package/dist/automations/steps/queryRows.js +14 -14
- package/dist/automations/steps/sendSmtpEmail.js +9 -9
- package/dist/automations/steps/serverLog.js +4 -4
- package/dist/automations/steps/slack.js +6 -6
- package/dist/automations/steps/updateRow.js +11 -11
- package/dist/automations/steps/zapier.js +9 -9
- package/dist/automations/triggerInfo/app.js +5 -5
- package/dist/automations/triggerInfo/cron.js +4 -4
- package/dist/automations/triggerInfo/rowDeleted.js +5 -5
- package/dist/automations/triggerInfo/rowSaved.js +7 -7
- package/dist/automations/triggerInfo/rowUpdated.js +7 -7
- package/dist/automations/triggerInfo/webhook.js +6 -6
- package/dist/db/utils.js +3 -2
- package/dist/environment.js +0 -1
- package/dist/events/docUpdates/index.js +17 -0
- package/dist/events/docUpdates/processors.js +18 -0
- package/dist/events/docUpdates/syncUsers.js +49 -0
- package/dist/events/index.js +3 -0
- package/dist/integrations/base/sqlTable.js +9 -2
- package/dist/integrations/index.js +3 -3
- package/dist/integrations/microsoftSqlServer.js +5 -2
- package/dist/integrations/mysql.js +5 -3
- package/dist/integrations/postgres.js +7 -5
- package/dist/integrations/redis.js +7 -0
- package/dist/integrations/rest.js +4 -0
- package/dist/migrations/functions/syncQuotas.js +2 -0
- package/dist/migrations/functions/usageQuotas/syncApps.js +1 -2
- package/dist/migrations/functions/usageQuotas/syncRows.js +1 -2
- package/dist/migrations/functions/usageQuotas/syncUsers.js +21 -0
- package/dist/sdk/app/applications/sync.js +117 -23
- package/dist/sdk/app/backups/exports.js +14 -38
- package/dist/sdk/index.js +2 -0
- package/dist/sdk/plugins/index.js +27 -0
- package/dist/sdk/plugins/plugins.js +53 -0
- package/dist/sdk/users/utils.js +21 -4
- package/dist/startup.js +31 -28
- package/dist/threads/automation.js +16 -5
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utilities/fileSystem/plugin.js +33 -23
- package/dist/utilities/global.js +17 -12
- package/dist/utilities/rowProcessor/utils.js +4 -5
- package/dist/watch.js +2 -2
- package/dist/websockets/client.js +14 -0
- package/dist/websockets/grid.js +60 -0
- package/dist/websockets/index.js +17 -0
- package/dist/websockets/websocket.js +78 -0
- package/package.json +16 -16
- package/scripts/dev/manage.js +2 -0
- package/scripts/integrations/mssql/data/entrypoint.sh +1 -0
- package/scripts/integrations/mssql/data/setup.sql +17 -17
- package/scripts/integrations/mysql/init.sql +1 -1
- package/scripts/integrations/postgres/init.sql +1 -0
- package/src/api/controllers/application.ts +4 -4
- package/src/api/controllers/automation.ts +12 -6
- package/src/api/controllers/datasource.ts +15 -5
- package/src/api/controllers/dev.ts +2 -2
- package/src/api/controllers/ops.ts +32 -0
- package/src/api/controllers/plugin/index.ts +8 -45
- package/src/api/controllers/query/index.ts +2 -2
- package/src/api/controllers/row/ExternalRequest.ts +21 -12
- package/src/api/controllers/row/internal.ts +9 -10
- package/src/api/controllers/row/utils.ts +2 -2
- package/src/api/controllers/table/utils.ts +10 -3
- package/src/api/controllers/user.ts +10 -96
- package/src/api/index.ts +2 -4
- package/src/api/routes/index.ts +2 -2
- package/src/api/routes/ops.ts +30 -0
- package/src/api/routes/tests/automation.spec.js +7 -4
- package/src/api/routes/tests/internalSearch.spec.js +1 -1
- package/src/api/routes/tests/user.spec.js +48 -37
- package/src/api/routes/user.ts +0 -5
- package/src/app.ts +4 -15
- package/src/automations/actions.ts +56 -24
- package/src/automations/index.ts +1 -1
- package/src/automations/steps/bash.ts +10 -7
- package/src/automations/steps/createRow.ts +15 -12
- package/src/automations/steps/delay.ts +6 -4
- package/src/automations/steps/deleteRow.ts +12 -9
- package/src/automations/steps/discord.ts +10 -8
- package/src/automations/steps/executeQuery.ts +13 -10
- package/src/automations/steps/executeScript.ts +10 -7
- package/src/automations/steps/filter.ts +8 -6
- package/src/automations/steps/integromat.ts +12 -10
- package/src/automations/steps/loop.ts +16 -10
- package/src/automations/steps/outgoingWebhook.ts +14 -11
- package/src/automations/steps/queryRows.ts +18 -15
- package/src/automations/steps/sendSmtpEmail.ts +11 -9
- package/src/automations/steps/serverLog.ts +6 -4
- package/src/automations/steps/slack.ts +8 -6
- package/src/automations/steps/updateRow.ts +15 -12
- package/src/automations/steps/zapier.ts +11 -9
- package/src/automations/tests/utilities/index.ts +2 -2
- package/src/automations/triggerInfo/app.ts +8 -5
- package/src/automations/triggerInfo/cron.ts +7 -4
- package/src/automations/triggerInfo/rowDeleted.ts +8 -5
- package/src/automations/triggerInfo/rowSaved.ts +10 -7
- package/src/automations/triggerInfo/rowUpdated.ts +10 -7
- package/src/automations/triggerInfo/webhook.ts +9 -6
- package/src/db/utils.ts +1 -0
- package/src/environment.ts +0 -1
- package/src/events/docUpdates/index.ts +1 -0
- package/src/events/docUpdates/processors.ts +14 -0
- package/src/events/docUpdates/syncUsers.ts +35 -0
- package/src/events/index.ts +1 -0
- package/src/integration-test/postgres.spec.ts +3 -1
- package/src/integrations/base/sqlTable.ts +9 -2
- package/src/integrations/index.ts +3 -3
- package/src/integrations/microsoftSqlServer.ts +5 -2
- package/src/integrations/mysql.ts +5 -3
- package/src/integrations/postgres.ts +7 -5
- package/src/integrations/redis.ts +8 -0
- package/src/integrations/rest.ts +3 -0
- package/src/migrations/functions/syncQuotas.ts +2 -0
- package/src/migrations/functions/usageQuotas/syncApps.ts +2 -3
- package/src/migrations/functions/usageQuotas/syncRows.ts +2 -3
- package/src/migrations/functions/usageQuotas/syncUsers.ts +9 -0
- package/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts +2 -2
- package/src/migrations/functions/usageQuotas/tests/syncUsers.spec.ts +26 -0
- package/src/migrations/index.ts +1 -0
- package/src/sdk/app/applications/sync.ts +129 -22
- package/src/sdk/app/applications/tests/sync.spec.ts +137 -0
- package/src/sdk/app/backups/exports.ts +17 -41
- package/src/sdk/index.ts +2 -0
- package/src/sdk/plugins/index.ts +5 -0
- package/src/sdk/plugins/plugins.ts +41 -0
- package/src/sdk/users/tests/utils.spec.ts +1 -32
- package/src/sdk/users/utils.ts +23 -5
- package/src/startup.ts +36 -34
- package/src/tests/jestEnv.ts +0 -1
- package/src/tests/jestSetup.ts +0 -1
- package/src/tests/utilities/TestConfiguration.ts +28 -0
- package/src/tests/utilities/structures.ts +25 -17
- package/src/threads/automation.ts +18 -6
- package/src/utilities/fileSystem/plugin.ts +13 -4
- package/src/utilities/global.ts +21 -16
- package/src/utilities/rowProcessor/utils.ts +9 -10
- package/src/watch.ts +2 -2
- package/src/websockets/client.ts +11 -0
- package/src/websockets/grid.ts +55 -0
- package/src/websockets/index.ts +14 -0
- package/src/websockets/websocket.ts +83 -0
- package/tsconfig.build.json +3 -5
- package/tsconfig.json +2 -1
- package/builder/assets/index.4e1df157.js +0 -1817
- package/builder/assets/index.7f9a008b.css +0 -6
- package/dist/api/controllers/cloud.js +0 -130
- package/dist/elasticApm.js +0 -14
- package/dist/package.json +0 -180
- package/dist/websocket.js +0 -22
- package/scripts/likeCypress.ts +0 -35
- package/src/api/controllers/cloud.ts +0 -119
- package/src/api/routes/cloud.ts +0 -18
- package/src/api/routes/tests/cloud.spec.ts +0 -54
- package/src/elasticApm.ts +0 -10
- package/src/migrations/functions/tests/syncQuotas.spec.js +0 -26
- package/src/tests/logging.ts +0 -34
- package/src/websocket.ts +0 -26
|
@@ -69,10 +69,17 @@ function generateSchema(schema, table, tables, oldTable = null, renamed) {
|
|
|
69
69
|
if (!relatedTable) {
|
|
70
70
|
throw "Referenced table doesn't exist";
|
|
71
71
|
}
|
|
72
|
-
|
|
72
|
+
const relatedPrimary = relatedTable.primary[0];
|
|
73
|
+
const externalType = relatedTable.schema[relatedPrimary].externalType;
|
|
74
|
+
if (externalType) {
|
|
75
|
+
schema.specificType(column.foreignKey, externalType);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
schema.integer(column.foreignKey).unsigned();
|
|
79
|
+
}
|
|
73
80
|
schema
|
|
74
81
|
.foreign(column.foreignKey)
|
|
75
|
-
.references(`${tableName}.${
|
|
82
|
+
.references(`${tableName}.${relatedPrimary}`);
|
|
76
83
|
}
|
|
77
84
|
break;
|
|
78
85
|
}
|
|
@@ -29,11 +29,11 @@ const firebase_1 = __importDefault(require("./firebase"));
|
|
|
29
29
|
const redis_1 = __importDefault(require("./redis"));
|
|
30
30
|
const snowflake_1 = __importDefault(require("./snowflake"));
|
|
31
31
|
const oracle_1 = __importDefault(require("./oracle"));
|
|
32
|
-
const plugin_1 = require("../api/controllers/plugin");
|
|
33
32
|
const types_1 = require("@budibase/types");
|
|
34
33
|
const fileSystem_1 = require("../utilities/fileSystem");
|
|
35
34
|
const environment_1 = __importDefault(require("../environment"));
|
|
36
35
|
const lodash_1 = require("lodash");
|
|
36
|
+
const sdk_1 = __importDefault(require("../sdk"));
|
|
37
37
|
const DEFINITIONS = {
|
|
38
38
|
[types_1.SourceName.POSTGRES]: postgres_1.default.schema,
|
|
39
39
|
[types_1.SourceName.DYNAMODB]: dynamodb_1.default.schema,
|
|
@@ -91,7 +91,7 @@ function getDefinitions() {
|
|
|
91
91
|
return __awaiter(this, void 0, void 0, function* () {
|
|
92
92
|
const pluginSchemas = {};
|
|
93
93
|
if (environment_1.default.SELF_HOSTED) {
|
|
94
|
-
const plugins = yield
|
|
94
|
+
const plugins = yield sdk_1.default.plugins.fetch(types_1.PluginType.DATASOURCE);
|
|
95
95
|
// extract the actual schema from each custom
|
|
96
96
|
for (let plugin of plugins) {
|
|
97
97
|
const sourceId = plugin.name;
|
|
@@ -111,7 +111,7 @@ function getIntegration(integration) {
|
|
|
111
111
|
return INTEGRATIONS[integration];
|
|
112
112
|
}
|
|
113
113
|
if (environment_1.default.SELF_HOSTED) {
|
|
114
|
-
const plugins = yield
|
|
114
|
+
const plugins = yield sdk_1.default.plugins.fetch(types_1.PluginType.DATASOURCE);
|
|
115
115
|
for (let plugin of plugins) {
|
|
116
116
|
if (plugin.name === integration) {
|
|
117
117
|
// need to use commonJS require due to its dynamic runtime nature
|
|
@@ -206,8 +206,11 @@ class SqlServerIntegration extends sql_1.default {
|
|
|
206
206
|
if (typeof name !== "string") {
|
|
207
207
|
continue;
|
|
208
208
|
}
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
const hasDefault = def.COLUMN_DEFAULT;
|
|
210
|
+
const isAuto = !!autoColumns.find(col => col === name);
|
|
211
|
+
const required = !!requiredColumns.find(col => col === name);
|
|
212
|
+
schema[name] = Object.assign(Object.assign({ autocolumn: isAuto, name: name, constraints: {
|
|
213
|
+
presence: required && !isAuto && !hasDefault,
|
|
211
214
|
} }, (0, utils_1.convertSqlType)(def.DATA_TYPE)), { externalType: def.DATA_TYPE });
|
|
212
215
|
}
|
|
213
216
|
tables[tableName] = {
|
|
@@ -186,12 +186,14 @@ class MySQLIntegration extends sql_1.default {
|
|
|
186
186
|
if (column.Key === "PRI" && primaryKeys.indexOf(column.Key) === -1) {
|
|
187
187
|
primaryKeys.push(columnName);
|
|
188
188
|
}
|
|
189
|
-
const
|
|
190
|
-
presence: column.Null !== "YES",
|
|
191
|
-
};
|
|
189
|
+
const hasDefault = column.Default != null;
|
|
192
190
|
const isAuto = typeof column.Extra === "string" &&
|
|
193
191
|
(column.Extra === "auto_increment" ||
|
|
194
192
|
column.Extra.toLowerCase().includes("generated"));
|
|
193
|
+
const required = column.Null !== "YES";
|
|
194
|
+
const constraints = {
|
|
195
|
+
presence: required && !isAuto && !hasDefault,
|
|
196
|
+
};
|
|
195
197
|
schema[columnName] = Object.assign(Object.assign({ name: columnName, autocolumn: isAuto, constraints }, (0, utils_1.convertSqlType)(column.Type)), { externalType: column.Type });
|
|
196
198
|
}
|
|
197
199
|
if (!tables[tableName]) {
|
|
@@ -227,13 +227,15 @@ class PostgresIntegration extends sql_1.default {
|
|
|
227
227
|
const identity = !!(column.identity_generation ||
|
|
228
228
|
column.identity_start ||
|
|
229
229
|
column.identity_increment);
|
|
230
|
-
const
|
|
231
|
-
|
|
232
|
-
};
|
|
233
|
-
const hasDefault = typeof column.column_default === "string" &&
|
|
230
|
+
const hasDefault = column.column_default != null;
|
|
231
|
+
const hasNextVal = typeof column.column_default === "string" &&
|
|
234
232
|
column.column_default.startsWith("nextval");
|
|
235
233
|
const isGenerated = column.is_generated && column.is_generated !== "NEVER";
|
|
236
|
-
const isAuto =
|
|
234
|
+
const isAuto = hasNextVal || identity || isGenerated;
|
|
235
|
+
const required = column.is_nullable === "NO";
|
|
236
|
+
const constraints = {
|
|
237
|
+
presence: required && !hasDefault && !isGenerated,
|
|
238
|
+
};
|
|
237
239
|
tables[tableName].schema[columnName] = Object.assign(Object.assign({ autocolumn: isAuto, name: columnName, constraints }, (0, utils_1.convertSqlType)(column.data_type)), { externalType: column.data_type });
|
|
238
240
|
}
|
|
239
241
|
const final = (0, utils_1.finaliseExternalTables)(tables, entities);
|
|
@@ -38,6 +38,12 @@ const SCHEMA = {
|
|
|
38
38
|
type: "password",
|
|
39
39
|
required: false,
|
|
40
40
|
},
|
|
41
|
+
db: {
|
|
42
|
+
type: "number",
|
|
43
|
+
required: false,
|
|
44
|
+
display: "DB",
|
|
45
|
+
default: 0,
|
|
46
|
+
},
|
|
41
47
|
},
|
|
42
48
|
query: {
|
|
43
49
|
create: {
|
|
@@ -90,6 +96,7 @@ class RedisIntegration {
|
|
|
90
96
|
port: this.config.port,
|
|
91
97
|
username: this.config.username,
|
|
92
98
|
password: this.config.password,
|
|
99
|
+
db: this.config.db,
|
|
93
100
|
});
|
|
94
101
|
}
|
|
95
102
|
disconnect() {
|
|
@@ -166,6 +166,10 @@ class RestIntegration {
|
|
|
166
166
|
}
|
|
167
167
|
raw = rawXml;
|
|
168
168
|
}
|
|
169
|
+
else if (contentType.includes("application/pdf")) {
|
|
170
|
+
data = yield response.arrayBuffer(); // Save PDF as ArrayBuffer
|
|
171
|
+
raw = Buffer.from(data);
|
|
172
|
+
}
|
|
169
173
|
else {
|
|
170
174
|
data = yield response.text();
|
|
171
175
|
raw = data;
|
|
@@ -37,6 +37,7 @@ const usageQuotas_1 = require("./usageQuotas");
|
|
|
37
37
|
const syncApps = __importStar(require("./usageQuotas/syncApps"));
|
|
38
38
|
const syncRows = __importStar(require("./usageQuotas/syncRows"));
|
|
39
39
|
const syncPlugins = __importStar(require("./usageQuotas/syncPlugins"));
|
|
40
|
+
const syncUsers = __importStar(require("./usageQuotas/syncUsers"));
|
|
40
41
|
/**
|
|
41
42
|
* Synchronise quotas to the state of the db.
|
|
42
43
|
*/
|
|
@@ -45,6 +46,7 @@ const run = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
45
46
|
yield syncApps.run();
|
|
46
47
|
yield syncRows.run();
|
|
47
48
|
yield syncPlugins.run();
|
|
49
|
+
yield syncUsers.run();
|
|
48
50
|
}));
|
|
49
51
|
});
|
|
50
52
|
exports.run = run;
|
|
@@ -18,8 +18,7 @@ const run = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
18
18
|
const devApps = yield backend_core_1.db.getAllApps({ dev: true });
|
|
19
19
|
const appCount = devApps ? devApps.length : 0;
|
|
20
20
|
// sync app count
|
|
21
|
-
|
|
22
|
-
console.log(`[Tenant: ${tenantId}] Syncing app count: ${appCount}`);
|
|
21
|
+
console.log(`Syncing app count: ${appCount}`);
|
|
23
22
|
yield pro_1.quotas.setUsage(appCount, types_1.StaticQuotaName.APPS, types_1.QuotaUsageType.STATIC);
|
|
24
23
|
});
|
|
25
24
|
exports.run = run;
|
|
@@ -27,8 +27,7 @@ const run = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
27
27
|
rowCount += rows.length;
|
|
28
28
|
});
|
|
29
29
|
// sync row count
|
|
30
|
-
|
|
31
|
-
console.log(`[Tenant: ${tenantId}] Syncing row count: ${rowCount}`);
|
|
30
|
+
console.log(`Syncing row count: ${rowCount}`);
|
|
32
31
|
yield pro_1.quotas.setUsagePerApp(counts, types_1.StaticQuotaName.ROWS, types_1.QuotaUsageType.STATIC);
|
|
33
32
|
});
|
|
34
33
|
exports.run = run;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.run = void 0;
|
|
13
|
+
const backend_core_1 = require("@budibase/backend-core");
|
|
14
|
+
const pro_1 = require("@budibase/pro");
|
|
15
|
+
const types_1 = require("@budibase/types");
|
|
16
|
+
const run = () => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
|
+
const userCount = yield backend_core_1.users.getUserCount();
|
|
18
|
+
console.log(`Syncing user count: ${userCount}`);
|
|
19
|
+
yield pro_1.quotas.setUsage(userCount, types_1.StaticQuotaName.USERS, types_1.QuotaUsageType.STATIC);
|
|
20
|
+
});
|
|
21
|
+
exports.run = run;
|
|
@@ -12,10 +12,108 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.syncApp = void 0;
|
|
15
|
+
exports.syncApp = exports.syncUsersToAllApps = void 0;
|
|
16
16
|
const environment_1 = __importDefault(require("../../../environment"));
|
|
17
17
|
const backend_core_1 = require("@budibase/backend-core");
|
|
18
|
+
const pro_1 = require("@budibase/pro");
|
|
18
19
|
const __1 = __importDefault(require("../../"));
|
|
20
|
+
const global_1 = require("../../../utilities/global");
|
|
21
|
+
const utils_1 = require("../../../db/utils");
|
|
22
|
+
function syncUsersToApp(appId, users, groups) {
|
|
23
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
if (!(yield backend_core_1.db.dbExists(appId))) {
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
yield backend_core_1.context.doInAppContext(appId, () => __awaiter(this, void 0, void 0, function* () {
|
|
28
|
+
const db = backend_core_1.context.getAppDB();
|
|
29
|
+
for (let user of users) {
|
|
30
|
+
let ctxUser = user;
|
|
31
|
+
let deletedUser = false;
|
|
32
|
+
const metadataId = (0, utils_1.generateUserMetadataID)(user._id);
|
|
33
|
+
if (user.deleted) {
|
|
34
|
+
deletedUser = true;
|
|
35
|
+
}
|
|
36
|
+
// make sure role is correct
|
|
37
|
+
if (!deletedUser) {
|
|
38
|
+
ctxUser = yield (0, global_1.processUser)(ctxUser, { appId, groups });
|
|
39
|
+
}
|
|
40
|
+
let roleId = ctxUser.roleId;
|
|
41
|
+
if (roleId === backend_core_1.roles.BUILTIN_ROLE_IDS.PUBLIC) {
|
|
42
|
+
roleId = undefined;
|
|
43
|
+
}
|
|
44
|
+
let metadata;
|
|
45
|
+
try {
|
|
46
|
+
metadata = yield db.get(metadataId);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
if (err.status !== 404) {
|
|
50
|
+
throw err;
|
|
51
|
+
}
|
|
52
|
+
// no metadata and user is to be deleted, can skip
|
|
53
|
+
// no role - user isn't in app anyway
|
|
54
|
+
if (!roleId) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
else if (!deletedUser) {
|
|
58
|
+
// doesn't exist yet, creating it
|
|
59
|
+
metadata = {
|
|
60
|
+
tableId: utils_1.InternalTables.USER_METADATA,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// the user doesn't exist, or doesn't have a role anymore
|
|
65
|
+
// get rid of their metadata
|
|
66
|
+
if (deletedUser || !roleId) {
|
|
67
|
+
yield db.remove(metadata);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
// assign the roleId for the metadata doc
|
|
71
|
+
if (roleId) {
|
|
72
|
+
metadata.roleId = roleId;
|
|
73
|
+
}
|
|
74
|
+
let combined = __1.default.users.combineMetadataAndUser(ctxUser, metadata);
|
|
75
|
+
// if no combined returned, there are no updates to make
|
|
76
|
+
if (combined) {
|
|
77
|
+
yield db.put(combined);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}));
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function syncUsersToAllApps(userIds) {
|
|
84
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
85
|
+
// list of users, if one has been deleted it will be undefined in array
|
|
86
|
+
const users = (yield (0, global_1.getGlobalUsers)(userIds, {
|
|
87
|
+
noProcessing: true,
|
|
88
|
+
}));
|
|
89
|
+
const groups = yield pro_1.sdk.groups.fetch();
|
|
90
|
+
const finalUsers = [];
|
|
91
|
+
for (let userId of userIds) {
|
|
92
|
+
const user = users.find(user => user._id === userId);
|
|
93
|
+
if (!user) {
|
|
94
|
+
finalUsers.push({ _id: userId, deleted: true });
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
finalUsers.push(user);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
const devAppIds = yield backend_core_1.db.getDevAppIDs();
|
|
101
|
+
let promises = [];
|
|
102
|
+
for (let devAppId of devAppIds) {
|
|
103
|
+
const prodAppId = backend_core_1.db.getProdAppID(devAppId);
|
|
104
|
+
for (let appId of [prodAppId, devAppId]) {
|
|
105
|
+
promises.push(syncUsersToApp(appId, finalUsers, groups));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const resp = yield Promise.allSettled(promises);
|
|
109
|
+
const failed = resp.filter(promise => promise.status === "rejected");
|
|
110
|
+
if (failed.length > 0) {
|
|
111
|
+
const reasons = failed.map(fail => fail.reason);
|
|
112
|
+
backend_core_1.logging.logAlert("Failed to sync users to apps", reasons);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
exports.syncUsersToAllApps = syncUsersToAllApps;
|
|
19
117
|
function syncApp(appId, opts) {
|
|
20
118
|
return __awaiter(this, void 0, void 0, function* () {
|
|
21
119
|
if (environment_1.default.DISABLE_AUTO_PROD_APP_SYNC) {
|
|
@@ -31,31 +129,27 @@ function syncApp(appId, opts) {
|
|
|
31
129
|
// specific case, want to make sure setup is skipped
|
|
32
130
|
const prodDb = backend_core_1.context.getProdAppDB({ skip_setup: true });
|
|
33
131
|
const exists = yield prodDb.exists();
|
|
34
|
-
if (!exists) {
|
|
35
|
-
// the database doesn't exist. Don't replicate
|
|
36
|
-
return {
|
|
37
|
-
message: "App sync not required, app not deployed.",
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
const replication = new backend_core_1.db.Replication({
|
|
41
|
-
source: prodAppId,
|
|
42
|
-
target: appId,
|
|
43
|
-
});
|
|
44
132
|
let error;
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
133
|
+
if (exists) {
|
|
134
|
+
const replication = new backend_core_1.db.Replication({
|
|
135
|
+
source: prodAppId,
|
|
136
|
+
target: appId,
|
|
137
|
+
});
|
|
138
|
+
try {
|
|
139
|
+
const replOpts = replication.appReplicateOpts();
|
|
140
|
+
if (opts === null || opts === void 0 ? void 0 : opts.automationOnly) {
|
|
141
|
+
replOpts.filter = (doc) => doc._id.startsWith(backend_core_1.db.DocumentType.AUTOMATION);
|
|
142
|
+
}
|
|
143
|
+
yield replication.replicate(replOpts);
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
error = err;
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
yield replication.close();
|
|
49
150
|
}
|
|
50
|
-
yield replication.replicate(replOpts);
|
|
51
|
-
}
|
|
52
|
-
catch (err) {
|
|
53
|
-
error = err;
|
|
54
|
-
}
|
|
55
|
-
finally {
|
|
56
|
-
yield replication.close();
|
|
57
151
|
}
|
|
58
|
-
// sync the users
|
|
152
|
+
// sync the users - kept for safe keeping
|
|
59
153
|
yield __1.default.users.syncGlobalUsers();
|
|
60
154
|
if (error) {
|
|
61
155
|
throw error;
|
|
@@ -12,7 +12,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
12
12
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
13
|
};
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
-
exports.streamExportApp = exports.
|
|
15
|
+
exports.streamExportApp = exports.exportApp = exports.exportDB = void 0;
|
|
16
16
|
const backend_core_1 = require("@budibase/backend-core");
|
|
17
17
|
const budibaseDir_1 = require("../../../utilities/budibaseDir");
|
|
18
18
|
const fileSystem_1 = require("../../../utilities/fileSystem");
|
|
@@ -73,11 +73,14 @@ function exportDB(dbName, opts = {}) {
|
|
|
73
73
|
});
|
|
74
74
|
}
|
|
75
75
|
exports.exportDB = exportDB;
|
|
76
|
-
function defineFilter(excludeRows) {
|
|
76
|
+
function defineFilter(excludeRows, excludeLogs) {
|
|
77
77
|
const ids = [utils_1.USER_METDATA_PREFIX, utils_1.LINK_USER_METADATA_PREFIX];
|
|
78
78
|
if (excludeRows) {
|
|
79
79
|
ids.push(utils_1.TABLE_ROW_PREFIX);
|
|
80
80
|
}
|
|
81
|
+
if (excludeLogs) {
|
|
82
|
+
ids.push(utils_1.AUTOMATION_LOG_PREFIX);
|
|
83
|
+
}
|
|
81
84
|
return (doc) => !ids.map(key => doc._id.includes(key)).reduce((prev, curr) => prev || curr);
|
|
82
85
|
}
|
|
83
86
|
/**
|
|
@@ -119,7 +122,10 @@ function exportApp(appId, config) {
|
|
|
119
122
|
}
|
|
120
123
|
// enforce an export of app DB to the tmp path
|
|
121
124
|
const dbPath = (0, path_1.join)(tmpPath, constants_2.DB_EXPORT_FILE);
|
|
122
|
-
yield exportDB(appId,
|
|
125
|
+
yield exportDB(appId, {
|
|
126
|
+
filter: defineFilter(config === null || config === void 0 ? void 0 : config.excludeRows, config === null || config === void 0 ? void 0 : config.excludeLogs),
|
|
127
|
+
exportPath: dbPath,
|
|
128
|
+
});
|
|
123
129
|
// if tar requested, return where the tarball is
|
|
124
130
|
if (config === null || config === void 0 ? void 0 : config.tar) {
|
|
125
131
|
// now the tmpPath contains both the DB export and attachments, tar this
|
|
@@ -135,40 +141,6 @@ function exportApp(appId, config) {
|
|
|
135
141
|
});
|
|
136
142
|
}
|
|
137
143
|
exports.exportApp = exportApp;
|
|
138
|
-
/**
|
|
139
|
-
* Export all apps + global DB (if supplied) to a single tarball, this includes
|
|
140
|
-
* the attachments for each app as well.
|
|
141
|
-
* @param {object[]} appMetadata The IDs and names of apps to export.
|
|
142
|
-
* @param {string} globalDbContents The contents of the global DB to export as well.
|
|
143
|
-
* @return {string} The path to the tarball.
|
|
144
|
-
*/
|
|
145
|
-
function exportMultipleApps(appMetadata, globalDbContents) {
|
|
146
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
147
|
-
const tmpPath = (0, path_1.join)((0, budibaseDir_1.budibaseTempDir)(), uuid());
|
|
148
|
-
fs_1.default.mkdirSync(tmpPath);
|
|
149
|
-
let exportPromises = [];
|
|
150
|
-
// export each app to a directory, then move it into the complete export
|
|
151
|
-
const exportAndMove = (appId, appName) => __awaiter(this, void 0, void 0, function* () {
|
|
152
|
-
const path = yield exportApp(appId);
|
|
153
|
-
yield fs_1.default.promises.rename(path, (0, path_1.join)(tmpPath, appName));
|
|
154
|
-
});
|
|
155
|
-
for (let metadata of appMetadata) {
|
|
156
|
-
exportPromises.push(exportAndMove(metadata.appId, metadata.name));
|
|
157
|
-
}
|
|
158
|
-
// wait for all exports to finish
|
|
159
|
-
yield Promise.all(exportPromises);
|
|
160
|
-
// add the global DB contents
|
|
161
|
-
if (globalDbContents) {
|
|
162
|
-
fs_1.default.writeFileSync((0, path_1.join)(tmpPath, constants_2.GLOBAL_DB_EXPORT_FILE), globalDbContents);
|
|
163
|
-
}
|
|
164
|
-
const appNames = appMetadata.map(metadata => metadata.name);
|
|
165
|
-
const tarPath = tarFilesToTmp(tmpPath, [...appNames, constants_2.GLOBAL_DB_EXPORT_FILE]);
|
|
166
|
-
// clear up the tmp path now tarball generated
|
|
167
|
-
fs_1.default.rmSync(tmpPath, { recursive: true, force: true });
|
|
168
|
-
return tarPath;
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
exports.exportMultipleApps = exportMultipleApps;
|
|
172
144
|
/**
|
|
173
145
|
* Streams a backup of the database state for an app
|
|
174
146
|
* @param {string} appId The ID of the app which is to be backed up.
|
|
@@ -177,7 +149,11 @@ exports.exportMultipleApps = exportMultipleApps;
|
|
|
177
149
|
*/
|
|
178
150
|
function streamExportApp(appId, excludeRows) {
|
|
179
151
|
return __awaiter(this, void 0, void 0, function* () {
|
|
180
|
-
const tmpPath = yield exportApp(appId, {
|
|
152
|
+
const tmpPath = yield exportApp(appId, {
|
|
153
|
+
excludeRows,
|
|
154
|
+
excludeLogs: true,
|
|
155
|
+
tar: true,
|
|
156
|
+
});
|
|
181
157
|
return (0, fileSystem_1.streamFile)(tmpPath);
|
|
182
158
|
});
|
|
183
159
|
}
|
package/dist/sdk/index.js
CHANGED
|
@@ -11,6 +11,7 @@ const datasources_1 = __importDefault(require("./app/datasources"));
|
|
|
11
11
|
const queries_1 = __importDefault(require("./app/queries"));
|
|
12
12
|
const rows_1 = __importDefault(require("./app/rows"));
|
|
13
13
|
const users_1 = __importDefault(require("./users"));
|
|
14
|
+
const plugins_1 = __importDefault(require("./plugins"));
|
|
14
15
|
const sdk = {
|
|
15
16
|
backups: backups_1.default,
|
|
16
17
|
tables: tables_1.default,
|
|
@@ -20,6 +21,7 @@ const sdk = {
|
|
|
20
21
|
users: users_1.default,
|
|
21
22
|
datasources: datasources_1.default,
|
|
22
23
|
queries: queries_1.default,
|
|
24
|
+
plugins: plugins_1.default,
|
|
23
25
|
};
|
|
24
26
|
// default export for TS
|
|
25
27
|
exports.default = sdk;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
const plugins = __importStar(require("./plugins"));
|
|
27
|
+
exports.default = Object.assign({}, plugins);
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
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
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.processUploaded = exports.fetch = void 0;
|
|
16
|
+
const types_1 = require("@budibase/types");
|
|
17
|
+
const backend_core_1 = require("@budibase/backend-core");
|
|
18
|
+
const file_1 = require("../../api/controllers/plugin/file");
|
|
19
|
+
const environment_1 = __importDefault(require("../../environment"));
|
|
20
|
+
const websockets_1 = require("../../websockets");
|
|
21
|
+
const pro_1 = require("@budibase/pro");
|
|
22
|
+
function fetch(type) {
|
|
23
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
24
|
+
const db = backend_core_1.tenancy.getGlobalDB();
|
|
25
|
+
const response = yield db.allDocs(backend_core_1.db.getPluginParams(null, {
|
|
26
|
+
include_docs: true,
|
|
27
|
+
}));
|
|
28
|
+
let plugins = response.rows.map((row) => row.doc);
|
|
29
|
+
plugins = backend_core_1.objectStore.enrichPluginURLs(plugins);
|
|
30
|
+
if (type) {
|
|
31
|
+
return plugins.filter((plugin) => { var _a; return ((_a = plugin.schema) === null || _a === void 0 ? void 0 : _a.type) === type; });
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
return plugins;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
exports.fetch = fetch;
|
|
39
|
+
function processUploaded(plugin, source) {
|
|
40
|
+
var _a;
|
|
41
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
const { metadata, directory } = yield (0, file_1.fileUpload)(plugin);
|
|
43
|
+
backend_core_1.plugins.validate(metadata === null || metadata === void 0 ? void 0 : metadata.schema);
|
|
44
|
+
// Only allow components in cloud
|
|
45
|
+
if (!environment_1.default.SELF_HOSTED && ((_a = metadata === null || metadata === void 0 ? void 0 : metadata.schema) === null || _a === void 0 ? void 0 : _a.type) !== types_1.PluginType.COMPONENT) {
|
|
46
|
+
throw new Error("Only component plugins are supported outside of self-host");
|
|
47
|
+
}
|
|
48
|
+
const doc = yield pro_1.sdk.plugins.storePlugin(metadata, directory, source);
|
|
49
|
+
websockets_1.clientAppSocket.emit("plugin-update", { name: doc.name, hash: doc.hash });
|
|
50
|
+
return doc;
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
exports.processUploaded = processUploaded;
|
package/dist/sdk/users/utils.js
CHANGED
|
@@ -34,6 +34,10 @@ function combineMetadataAndUser(user, metadata) {
|
|
|
34
34
|
if (found) {
|
|
35
35
|
newDoc._rev = found._rev;
|
|
36
36
|
}
|
|
37
|
+
// clear fields that shouldn't be in metadata
|
|
38
|
+
delete newDoc.password;
|
|
39
|
+
delete newDoc.forceResetPassword;
|
|
40
|
+
delete newDoc.roles;
|
|
37
41
|
if (found == null || !(0, lodash_1.isEqual)(newDoc, found)) {
|
|
38
42
|
return Object.assign(Object.assign({}, found), newDoc);
|
|
39
43
|
}
|
|
@@ -53,10 +57,9 @@ function syncGlobalUsers() {
|
|
|
53
57
|
return __awaiter(this, void 0, void 0, function* () {
|
|
54
58
|
// sync user metadata
|
|
55
59
|
const db = backend_core_1.context.getAppDB();
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
]);
|
|
60
|
+
const resp = yield Promise.all([(0, global_1.getGlobalUsers)(), rawUserMetadata()]);
|
|
61
|
+
const users = resp[0];
|
|
62
|
+
const metadata = resp[1];
|
|
60
63
|
const toWrite = [];
|
|
61
64
|
for (let user of users) {
|
|
62
65
|
const combined = combineMetadataAndUser(user, metadata);
|
|
@@ -64,6 +67,20 @@ function syncGlobalUsers() {
|
|
|
64
67
|
toWrite.push(combined);
|
|
65
68
|
}
|
|
66
69
|
}
|
|
70
|
+
let foundEmails = [];
|
|
71
|
+
for (let data of metadata) {
|
|
72
|
+
if (!data._id) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const alreadyExisting = data.email && foundEmails.indexOf(data.email) !== -1;
|
|
76
|
+
const globalId = (0, utils_1.getGlobalIDFromUserMetadataID)(data._id);
|
|
77
|
+
if (!users.find(user => user._id === globalId) || alreadyExisting) {
|
|
78
|
+
toWrite.push(Object.assign(Object.assign({}, data), { _deleted: true }));
|
|
79
|
+
}
|
|
80
|
+
if (data.email) {
|
|
81
|
+
foundEmails.push(data.email);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
67
84
|
yield db.bulkDocs(toWrite);
|
|
68
85
|
});
|
|
69
86
|
}
|