@budibase/server 2.4.43 → 2.4.44-alpha.1
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.8b377b88.js → index.76deb808.js} +385 -384
- package/builder/assets/index.7f9a008b.css +6 -0
- package/builder/index.html +7 -7
- package/dist/api/controllers/application.js +28 -24
- package/dist/api/controllers/public/metrics.js +113 -0
- package/dist/api/controllers/row/external.js +15 -0
- package/dist/api/controllers/static/index.js +84 -24
- package/dist/api/controllers/static/templates/BudibaseApp.svelte +34 -11
- package/dist/api/controllers/table/utils.js +2 -4
- package/dist/api/routes/public/index.js +8 -0
- package/dist/api/routes/public/metrics.js +30 -0
- package/dist/app.js +1 -0
- package/dist/integrations/googlesheets.js +4 -0
- package/dist/integrations/redis.js +1 -1
- package/dist/middleware/currentapp.js +1 -27
- package/dist/package.json +12 -11
- package/dist/sdk/users/utils.js +11 -6
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utilities/fileSystem/app.js +1 -10
- package/dist/utilities/global.js +17 -7
- package/jest.config.ts +1 -0
- package/package.json +13 -12
- package/specs/openapi.json +39 -0
- package/specs/openapi.yaml +169 -0
- package/specs/resources/application.ts +11 -0
- package/specs/resources/index.ts +2 -0
- package/specs/resources/metrics.ts +81 -0
- package/src/api/controllers/application.ts +20 -21
- package/src/api/controllers/component.ts +2 -2
- package/src/api/controllers/public/metrics.ts +251 -0
- package/src/api/controllers/row/external.ts +14 -0
- package/src/api/controllers/static/index.ts +69 -26
- package/src/api/controllers/static/templates/BudibaseApp.svelte +34 -11
- package/src/api/controllers/table/tests/utils.spec.ts +97 -0
- package/src/api/controllers/table/utils.ts +20 -12
- package/src/api/controllers/view/tests/__snapshots__/viewBuilder.spec.js.snap +48 -48
- package/src/api/routes/public/index.ts +10 -1
- package/src/api/routes/public/metrics.ts +28 -0
- package/src/api/routes/public/tests/metrics.spec.js +34 -0
- package/src/api/routes/tests/__snapshots__/datasource.spec.ts.snap +22 -22
- package/src/api/routes/tests/__snapshots__/view.spec.js.snap +5 -5
- package/src/api/routes/tests/appSync.spec.ts +1 -1
- package/src/api/routes/tests/internalSearch.spec.js +6 -6
- package/src/api/routes/tests/user.spec.js +2 -2
- package/src/app.ts +2 -1
- package/src/automations/automationUtils.ts +1 -1
- package/src/automations/tests/automation.spec.ts +99 -0
- package/src/db/defaultData/datasource_bb_default.ts +1 -1
- package/src/definitions/openapi.ts +15 -0
- package/src/integrations/googlesheets.ts +4 -0
- package/src/integrations/redis.ts +1 -1
- package/src/integrations/tests/googlesheets.spec.ts +4 -0
- package/src/integrations/tests/redis.spec.ts +9 -5
- package/src/middleware/currentapp.ts +3 -32
- package/src/middleware/tests/currentapp.spec.js +6 -42
- package/src/sdk/users/tests/utils.spec.ts +159 -0
- package/src/sdk/users/utils.ts +18 -7
- package/src/tests/jestSetup.ts +5 -1
- package/src/tests/utilities/TestConfiguration.ts +7 -19
- package/src/tests/utilities/structures.ts +13 -1
- package/src/utilities/fileSystem/app.ts +2 -9
- package/src/utilities/global.ts +21 -9
- package/src/utilities/rowProcessor/index.ts +1 -1
- package/builder/assets/favicon.e7fc7733.png +0 -0
- package/builder/assets/index.b0e3aca6.css +0 -6
- package/src/automations/tests/automation.spec.js +0 -84
package/builder/index.html
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
<!doctype html>
|
|
2
2
|
<html class="spectrum spectrum--medium spectrum--darkest" lang="en" dir="ltr">
|
|
3
|
+
|
|
3
4
|
<head>
|
|
4
5
|
<meta charset='utf8'>
|
|
5
6
|
<meta name='viewport' content='width=device-width'>
|
|
6
7
|
<title>Budibase</title>
|
|
7
|
-
<link rel='icon' href='/builder/assets/favicon.e7fc7733.png'>
|
|
8
8
|
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
|
9
|
-
<link
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
<script type="module" crossorigin src="/builder/assets/index.8b377b88.js"></script>
|
|
14
|
-
<link rel="stylesheet" href="/builder/assets/index.b0e3aca6.css">
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=Source+Sans+Pro:wght@400;600;700&display=swap"
|
|
10
|
+
rel="stylesheet" />
|
|
11
|
+
<script type="module" crossorigin src="/builder/assets/index.76deb808.js"></script>
|
|
12
|
+
<link rel="stylesheet" href="/builder/assets/index.7f9a008b.css">
|
|
15
13
|
</head>
|
|
14
|
+
|
|
16
15
|
<body id="app">
|
|
17
16
|
|
|
18
17
|
</body>
|
|
18
|
+
|
|
19
19
|
</html>
|
|
@@ -320,7 +320,7 @@ function appPostCreate(ctx, app) {
|
|
|
320
320
|
});
|
|
321
321
|
}
|
|
322
322
|
catch (err) {
|
|
323
|
-
if (err.code && err.code === backend_core_1.
|
|
323
|
+
if (err.code && err.code === backend_core_1.ErrorCode.USAGE_LIMIT_EXCEEDED) {
|
|
324
324
|
// this import resulted in row usage exceeding the quota
|
|
325
325
|
// delete the app
|
|
326
326
|
// skip pre and post-steps as no rows have been added to quotas yet
|
|
@@ -415,17 +415,19 @@ function revertClient(ctx) {
|
|
|
415
415
|
});
|
|
416
416
|
}
|
|
417
417
|
exports.revertClient = revertClient;
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
418
|
+
function unpublishApp(ctx) {
|
|
419
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
420
|
+
let appId = ctx.params.appId;
|
|
421
|
+
appId = backend_core_1.db.getProdAppID(appId);
|
|
422
|
+
const db = backend_core_1.context.getProdAppDB();
|
|
423
|
+
const result = yield db.destroy();
|
|
424
|
+
yield backend_core_1.events.app.unpublished({ appId });
|
|
425
|
+
// automations only in production
|
|
426
|
+
yield (0, utils_2.cleanupAutomations)(appId);
|
|
427
|
+
yield backend_core_1.cache.app.invalidateAppMetadata(appId);
|
|
428
|
+
return result;
|
|
429
|
+
});
|
|
430
|
+
}
|
|
429
431
|
function destroyApp(ctx) {
|
|
430
432
|
return __awaiter(this, void 0, void 0, function* () {
|
|
431
433
|
let appId = ctx.params.appId;
|
|
@@ -476,18 +478,20 @@ function destroy(ctx) {
|
|
|
476
478
|
});
|
|
477
479
|
}
|
|
478
480
|
exports.destroy = destroy;
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
481
|
+
function unpublish(ctx) {
|
|
482
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
483
|
+
const prodAppId = backend_core_1.db.getProdAppID(ctx.params.appId);
|
|
484
|
+
const dbExists = yield backend_core_1.db.dbExists(prodAppId);
|
|
485
|
+
// check app has been published
|
|
486
|
+
if (!dbExists) {
|
|
487
|
+
return ctx.throw(400, "App has not been published.");
|
|
488
|
+
}
|
|
489
|
+
yield preDestroyApp(ctx);
|
|
490
|
+
yield unpublishApp(ctx);
|
|
491
|
+
yield postDestroyApp(ctx);
|
|
492
|
+
ctx.status = 204;
|
|
493
|
+
});
|
|
494
|
+
}
|
|
491
495
|
exports.unpublish = unpublish;
|
|
492
496
|
function sync(ctx) {
|
|
493
497
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -0,0 +1,113 @@
|
|
|
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.convertToOpenMetrics = exports.fetch = void 0;
|
|
16
|
+
const backend_core_1 = require("@budibase/backend-core");
|
|
17
|
+
const pro_1 = require("@budibase/pro");
|
|
18
|
+
const os_1 = __importDefault(require("os"));
|
|
19
|
+
function fetch(ctx) {
|
|
20
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
+
// *** OPERATING SYSTEM ***
|
|
22
|
+
const freeMem = os_1.default.freemem();
|
|
23
|
+
const totalMem = os_1.default.totalmem();
|
|
24
|
+
const usedMem = totalMem - freeMem;
|
|
25
|
+
const uptime = os_1.default.uptime();
|
|
26
|
+
// *** APPS ***
|
|
27
|
+
const allDatabases = yield backend_core_1.db.getAllDbs();
|
|
28
|
+
const devAppIDs = yield backend_core_1.db.getDevAppIDs();
|
|
29
|
+
const prodAppIDs = yield backend_core_1.db.getProdAppIDs();
|
|
30
|
+
const allAppIds = yield backend_core_1.db.getAllApps({ idsOnly: true });
|
|
31
|
+
// *** USERS ***
|
|
32
|
+
const usersObject = yield backend_core_1.users.getAllUserIds();
|
|
33
|
+
// *** QUOTAS ***
|
|
34
|
+
const usage = yield pro_1.quotas.getQuotaUsage();
|
|
35
|
+
const license = yield pro_1.licensing.cache.getCachedLicense();
|
|
36
|
+
const appsQuotaUsage = usage.usageQuota.apps;
|
|
37
|
+
const rowsQuotaUsage = usage.usageQuota.rows;
|
|
38
|
+
const pluginsQuotaUsage = usage.usageQuota.plugins;
|
|
39
|
+
const userGroupsQuotaUsage = usage.usageQuota.userGroups;
|
|
40
|
+
const queryQuotaUsage = usage.monthly.current.queries;
|
|
41
|
+
const automationsQuotaUsage = usage.monthly.current.automations;
|
|
42
|
+
const appsQuotaLimit = license.quotas.usage.static.apps.value;
|
|
43
|
+
const rowsQuotaLimit = license.quotas.usage.static.rows.value;
|
|
44
|
+
const userGroupsQuotaLimit = license.quotas.usage.static.userGroups.value;
|
|
45
|
+
const pluginsQuotaLimit = license.quotas.usage.static.plugins.value;
|
|
46
|
+
const queryQuotaLimit = license.quotas.usage.monthly.queries.value;
|
|
47
|
+
const automationsQuotaLimit = license.quotas.usage.monthly.automations.value;
|
|
48
|
+
// *** BUILD THE OUTPUT STRING ***
|
|
49
|
+
var outputString = "";
|
|
50
|
+
// **** budibase_os_uptime ****
|
|
51
|
+
outputString += convertToOpenMetrics("budibase_os_uptime", "Time in seconds that the host operating system has been up", "counter", uptime);
|
|
52
|
+
// **** budibase_os_free_mem ****
|
|
53
|
+
outputString += convertToOpenMetrics("budibase_os_free_mem", "Bytes of memory free for usage on the host operating system", "gauge", freeMem);
|
|
54
|
+
// **** budibase_os_total_mem ****
|
|
55
|
+
outputString += convertToOpenMetrics("budibase_os_total_mem", "Total bytes of memory on the host operating system", "gauge", totalMem);
|
|
56
|
+
// **** budibase_os_used_mem ****
|
|
57
|
+
outputString += convertToOpenMetrics("budibase_os_used_mem", "Total bytes of memory in use on the host operating system", "gauge", usedMem);
|
|
58
|
+
// **** budibase_os_load1 ****
|
|
59
|
+
outputString += convertToOpenMetrics("budibase_os_load1", "Host operating system load average", "gauge", os_1.default.loadavg()[0]);
|
|
60
|
+
// **** budibase_os_load5 ****
|
|
61
|
+
outputString += convertToOpenMetrics("budibase_os_load5", "Host operating system load average", "gauge", os_1.default.loadavg()[1]);
|
|
62
|
+
// **** budibase_os_load15 ****
|
|
63
|
+
outputString += convertToOpenMetrics("budibase_os_load15", "Host operating system load average", "gauge", os_1.default.loadavg()[2]);
|
|
64
|
+
// **** budibase_tenant_user_count ****
|
|
65
|
+
outputString += convertToOpenMetrics("budibase_tenant_user_count", "The number of users created", "gauge", usersObject.length);
|
|
66
|
+
// **** budibase_tenant_app_count ****
|
|
67
|
+
outputString += convertToOpenMetrics("budibase_tenant_app_count", "The number of apps created by a user", "gauge", allAppIds.length);
|
|
68
|
+
// **** budibase_tenant_production_app_count ****
|
|
69
|
+
outputString += convertToOpenMetrics("budibase_tenant_production_app_count", "The number of apps a user has published", "gauge", prodAppIDs.length);
|
|
70
|
+
// **** budibase_tenant_dev_app_count ****
|
|
71
|
+
outputString += convertToOpenMetrics("budibase_tenant_dev_app_count", "The number of apps a user has unpublished in development", "gauge", devAppIDs.length);
|
|
72
|
+
// **** budibase_tenant_db_count ****
|
|
73
|
+
outputString += convertToOpenMetrics("budibase_tenant_db_count", "The number of couchdb databases including global tables such as _users", "gauge", allDatabases.length);
|
|
74
|
+
// **** budibase_quota_usage_apps ****
|
|
75
|
+
outputString += convertToOpenMetrics("budibase_quota_usage_apps", "The number of apps created", "gauge", appsQuotaUsage);
|
|
76
|
+
// **** budibase_quota_limit_apps ****
|
|
77
|
+
outputString += convertToOpenMetrics("budibase_quota_limit_apps", "The limit on the number of apps that can be created", "gauge", appsQuotaLimit == -1 ? Number.MAX_SAFE_INTEGER : appsQuotaLimit);
|
|
78
|
+
// **** budibase_quota_usage_rows ****
|
|
79
|
+
outputString += convertToOpenMetrics("budibase_quota_usage_rows", "The number of database rows used from the quota", "gauge", rowsQuotaUsage);
|
|
80
|
+
// **** budibase_quota_limit_rows ****
|
|
81
|
+
outputString += convertToOpenMetrics("budibase_quota_limit_rows", "The limit on the number of rows that can be created", "gauge", rowsQuotaLimit == -1 ? Number.MAX_SAFE_INTEGER : rowsQuotaLimit);
|
|
82
|
+
// **** budibase_quota_usage_plugins ****
|
|
83
|
+
outputString += convertToOpenMetrics("budibase_quota_usage_plugins", "The number of plugins in use", "gauge", pluginsQuotaUsage);
|
|
84
|
+
// **** budibase_quota_limit_plugins ****
|
|
85
|
+
outputString += convertToOpenMetrics("budibase_quota_limit_plugins", "The limit on the number of plugins that can be created", "gauge", pluginsQuotaLimit == -1 ? Number.MAX_SAFE_INTEGER : pluginsQuotaLimit);
|
|
86
|
+
// **** budibase_quota_usage_user_groups ****
|
|
87
|
+
outputString += convertToOpenMetrics("budibase_quota_usage_user_groups", "The number of user groups created", "gauge", userGroupsQuotaUsage);
|
|
88
|
+
// **** budibase_quota_limit_user_groups ****
|
|
89
|
+
outputString += convertToOpenMetrics("budibase_quota_limit_user_groups", "The limit on the number of user groups that can be created", "gauge", userGroupsQuotaLimit == -1 ? Number.MAX_SAFE_INTEGER : userGroupsQuotaLimit);
|
|
90
|
+
// **** budibase_quota_usage_queries ****
|
|
91
|
+
outputString += convertToOpenMetrics("budibase_quota_usage_queries", "The number of queries used in the current month", "gauge", queryQuotaUsage);
|
|
92
|
+
// **** budibase_quota_limit_queries ****
|
|
93
|
+
outputString += convertToOpenMetrics("budibase_quota_limit_queries", "The limit on the number of queries for the current month", "gauge", queryQuotaLimit == -1 ? Number.MAX_SAFE_INTEGER : queryQuotaLimit);
|
|
94
|
+
// **** budibase_quota_usage_automations ****
|
|
95
|
+
outputString += convertToOpenMetrics("budibase_quota_usage_automations", "The number of automations used in the current month", "gauge", automationsQuotaUsage);
|
|
96
|
+
// **** budibase_quota_limit_automations ****
|
|
97
|
+
outputString += convertToOpenMetrics("budibase_quota_limit_automations", "The limit on the number of automations that can be created", "gauge", automationsQuotaLimit == -1
|
|
98
|
+
? Number.MAX_SAFE_INTEGER
|
|
99
|
+
: automationsQuotaLimit);
|
|
100
|
+
ctx.body = outputString;
|
|
101
|
+
ctx.set("Content-Type", "text/plain");
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
exports.fetch = fetch;
|
|
105
|
+
function convertToOpenMetrics(metricName, metricHelp, metricType, metricValue) {
|
|
106
|
+
return `# HELP ${metricName} ${metricHelp}.
|
|
107
|
+
# TYPE ${metricName} ${metricType}
|
|
108
|
+
${metricName} ${metricValue}\n`;
|
|
109
|
+
}
|
|
110
|
+
exports.convertToOpenMetrics = convertToOpenMetrics;
|
|
111
|
+
exports.default = {
|
|
112
|
+
fetch,
|
|
113
|
+
};
|
|
@@ -54,6 +54,7 @@ const exporters = __importStar(require("../view/exporters"));
|
|
|
54
54
|
const fileSystem_1 = require("../../../utilities/fileSystem");
|
|
55
55
|
const types_1 = require("@budibase/types");
|
|
56
56
|
const sdk_1 = __importDefault(require("../../../sdk"));
|
|
57
|
+
const utils = __importStar(require("./utils"));
|
|
57
58
|
const { cleanExportRows } = require("./utils");
|
|
58
59
|
function handleRequest(operation, tableId, opts) {
|
|
59
60
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -83,6 +84,13 @@ function patch(ctx) {
|
|
|
83
84
|
const id = inputs._id;
|
|
84
85
|
// don't save the ID to db
|
|
85
86
|
delete inputs._id;
|
|
87
|
+
const validateResult = yield utils.validate({
|
|
88
|
+
row: inputs,
|
|
89
|
+
tableId,
|
|
90
|
+
});
|
|
91
|
+
if (!validateResult.valid) {
|
|
92
|
+
throw { validation: validateResult.errors };
|
|
93
|
+
}
|
|
86
94
|
return handleRequest(types_1.Operation.UPDATE, tableId, {
|
|
87
95
|
id: (0, utils_1.breakRowIdField)(id),
|
|
88
96
|
row: inputs,
|
|
@@ -95,6 +103,13 @@ function save(ctx) {
|
|
|
95
103
|
return __awaiter(this, void 0, void 0, function* () {
|
|
96
104
|
const inputs = ctx.request.body;
|
|
97
105
|
const tableId = ctx.params.tableId;
|
|
106
|
+
const validateResult = yield utils.validate({
|
|
107
|
+
row: inputs,
|
|
108
|
+
tableId,
|
|
109
|
+
});
|
|
110
|
+
if (!validateResult.valid) {
|
|
111
|
+
throw { validation: validateResult.errors };
|
|
112
|
+
}
|
|
98
113
|
return handleRequest(types_1.Operation.CREATE, tableId, {
|
|
99
114
|
row: inputs,
|
|
100
115
|
includeSqlRelationships: types_1.IncludeRelationship.EXCLUDE,
|
|
@@ -1,4 +1,27 @@
|
|
|
1
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
|
+
};
|
|
2
25
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
26
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
27
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -25,6 +48,7 @@ const backend_core_1 = require("@budibase/backend-core");
|
|
|
25
48
|
const aws_sdk_1 = __importDefault(require("aws-sdk"));
|
|
26
49
|
const fs_1 = __importDefault(require("fs"));
|
|
27
50
|
const sdk_1 = __importDefault(require("../../../sdk"));
|
|
51
|
+
const pro = __importStar(require("@budibase/pro"));
|
|
28
52
|
const send = require("koa-send");
|
|
29
53
|
function prepareUpload({ s3Key, bucket, metadata, file }) {
|
|
30
54
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -102,31 +126,67 @@ const deleteObjects = function (ctx) {
|
|
|
102
126
|
exports.deleteObjects = deleteObjects;
|
|
103
127
|
const serveApp = function (ctx) {
|
|
104
128
|
return __awaiter(this, void 0, void 0, function* () {
|
|
105
|
-
|
|
106
|
-
const
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
129
|
+
//Public Settings
|
|
130
|
+
const { config } = yield backend_core_1.configs.getSettingsConfigDoc();
|
|
131
|
+
const branding = yield pro.branding.getBrandingConfig(config);
|
|
132
|
+
let db;
|
|
133
|
+
try {
|
|
134
|
+
db = backend_core_1.context.getAppDB({ skip_setup: true });
|
|
135
|
+
const appInfo = yield db.get(utils_1.DocumentType.APP_METADATA);
|
|
136
|
+
let appId = backend_core_1.context.getAppId();
|
|
137
|
+
if (!environment_1.default.isJest()) {
|
|
138
|
+
const App = require("./templates/BudibaseApp.svelte").default;
|
|
139
|
+
const plugins = backend_core_1.objectStore.enrichPluginURLs(appInfo.usedPlugins);
|
|
140
|
+
const { head, html, css } = App.render({
|
|
141
|
+
metaImage: (branding === null || branding === void 0 ? void 0 : branding.metaImageUrl) ||
|
|
142
|
+
"https://res.cloudinary.com/daog6scxm/image/upload/v1666109324/meta-images/budibase-meta-image_uukc1m.png",
|
|
143
|
+
metaDescription: (branding === null || branding === void 0 ? void 0 : branding.metaDescription) || "",
|
|
144
|
+
metaTitle: (branding === null || branding === void 0 ? void 0 : branding.metaTitle) || `${appInfo.name} - built with Budibase`,
|
|
145
|
+
title: appInfo.name,
|
|
146
|
+
production: environment_1.default.isProd(),
|
|
147
|
+
appId,
|
|
148
|
+
clientLibPath: backend_core_1.objectStore.clientLibraryUrl(appId, appInfo.version),
|
|
149
|
+
usedPlugins: plugins,
|
|
150
|
+
favicon: branding.faviconUrl !== ""
|
|
151
|
+
? backend_core_1.objectStore.getGlobalFileUrl("settings", "faviconUrl")
|
|
152
|
+
: "",
|
|
153
|
+
logo: (config === null || config === void 0 ? void 0 : config.logoUrl) !== ""
|
|
154
|
+
? backend_core_1.objectStore.getGlobalFileUrl("settings", "logoUrl")
|
|
155
|
+
: "",
|
|
156
|
+
});
|
|
157
|
+
const appHbs = (0, fileSystem_1.loadHandlebarsFile)(`${__dirname}/templates/app.hbs`);
|
|
158
|
+
ctx.body = yield (0, string_templates_1.processString)(appHbs, {
|
|
159
|
+
head,
|
|
160
|
+
body: html,
|
|
161
|
+
style: css.code,
|
|
162
|
+
appId,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
// just return the app info for jest to assert on
|
|
167
|
+
ctx.body = appInfo;
|
|
168
|
+
}
|
|
126
169
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
170
|
+
catch (error) {
|
|
171
|
+
if (!environment_1.default.isJest()) {
|
|
172
|
+
const App = require("./templates/BudibaseApp.svelte").default;
|
|
173
|
+
const { head, html, css } = App.render({
|
|
174
|
+
title: branding === null || branding === void 0 ? void 0 : branding.metaTitle,
|
|
175
|
+
metaTitle: branding === null || branding === void 0 ? void 0 : branding.metaTitle,
|
|
176
|
+
metaImage: (branding === null || branding === void 0 ? void 0 : branding.metaImageUrl) ||
|
|
177
|
+
"https://res.cloudinary.com/daog6scxm/image/upload/v1666109324/meta-images/budibase-meta-image_uukc1m.png",
|
|
178
|
+
metaDescription: (branding === null || branding === void 0 ? void 0 : branding.metaDescription) || "",
|
|
179
|
+
favicon: branding.faviconUrl !== ""
|
|
180
|
+
? backend_core_1.objectStore.getGlobalFileUrl("settings", "faviconUrl")
|
|
181
|
+
: "",
|
|
182
|
+
});
|
|
183
|
+
const appHbs = (0, fileSystem_1.loadHandlebarsFile)(`${__dirname}/templates/app.hbs`);
|
|
184
|
+
ctx.body = yield (0, string_templates_1.processString)(appHbs, {
|
|
185
|
+
head,
|
|
186
|
+
body: html,
|
|
187
|
+
style: css.code,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
130
190
|
}
|
|
131
191
|
});
|
|
132
192
|
};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
<script>
|
|
2
2
|
export let title = ""
|
|
3
3
|
export let favicon = ""
|
|
4
|
+
|
|
4
5
|
export let metaImage = ""
|
|
6
|
+
export let metaTitle = ""
|
|
7
|
+
export let metaDescription = ""
|
|
5
8
|
|
|
6
9
|
export let clientLibPath
|
|
7
10
|
export let usedPlugins
|
|
@@ -13,18 +16,33 @@
|
|
|
13
16
|
name="viewport"
|
|
14
17
|
content="width=device-width, initial-scale=1.0, viewport-fit=cover"
|
|
15
18
|
/>
|
|
19
|
+
|
|
20
|
+
<!-- Primary Meta Tags -->
|
|
21
|
+
<meta name="title" content={metaTitle} />
|
|
22
|
+
<meta name="description" content={metaDescription} />
|
|
23
|
+
|
|
16
24
|
<!-- Opengraph Meta Tags -->
|
|
17
|
-
<meta name="twitter:card" content="summary_large_image" />
|
|
18
|
-
<meta name="twitter:site" content="@budibase" />
|
|
19
|
-
<meta name="twitter:image" content={metaImage} />
|
|
20
|
-
<meta name="twitter:title" content="{title} - built with Budibase" />
|
|
21
25
|
<meta property="og:site_name" content="Budibase" />
|
|
22
|
-
<meta property="og:title" content=
|
|
26
|
+
<meta property="og:title" content={metaTitle} />
|
|
27
|
+
<meta property="og:description" content={metaDescription} />
|
|
23
28
|
<meta property="og:type" content="website" />
|
|
24
29
|
<meta property="og:image" content={metaImage} />
|
|
25
30
|
|
|
31
|
+
<!-- Twitter -->
|
|
32
|
+
<meta property="twitter:card" content="summary_large_image" />
|
|
33
|
+
<meta property="twitter:site" content="@budibase" />
|
|
34
|
+
<meta property="twitter:image" content={metaImage} />
|
|
35
|
+
<meta property="twitter:image:alt" content={metaTitle} />
|
|
36
|
+
<meta property="twitter:title" content={metaTitle} />
|
|
37
|
+
<meta property="twitter:description" content={metaDescription} />
|
|
38
|
+
|
|
26
39
|
<title>{title}</title>
|
|
27
|
-
|
|
40
|
+
{#if favicon !== ""}
|
|
41
|
+
<link rel="icon" type="image/png" href={favicon} />
|
|
42
|
+
{:else}
|
|
43
|
+
<link rel="icon" type="image/png" href="https://i.imgur.com/Xhdt1YP.png" />
|
|
44
|
+
{/if}
|
|
45
|
+
|
|
28
46
|
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
|
29
47
|
<link rel="preconnect" href="https://fonts.gstatic.com" />
|
|
30
48
|
<link
|
|
@@ -83,11 +101,16 @@
|
|
|
83
101
|
|
|
84
102
|
<body id="app">
|
|
85
103
|
<div id="error">
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
104
|
+
{#if clientLibPath}
|
|
105
|
+
<h1>There was an error loading your app</h1>
|
|
106
|
+
<h2>
|
|
107
|
+
The Budibase client library could not be loaded. Try republishing your
|
|
108
|
+
app.
|
|
109
|
+
</h2>
|
|
110
|
+
{:else}
|
|
111
|
+
<h2>We couldn't find that application</h2>
|
|
112
|
+
<p />
|
|
113
|
+
{/if}
|
|
91
114
|
</div>
|
|
92
115
|
<script type="application/javascript">
|
|
93
116
|
window.INIT_TIME = Date.now()
|
|
@@ -96,7 +96,7 @@ function makeSureTableUpToDate(table, tableToSave) {
|
|
|
96
96
|
return tableToSave;
|
|
97
97
|
}
|
|
98
98
|
exports.makeSureTableUpToDate = makeSureTableUpToDate;
|
|
99
|
-
function importToRows(data, table, user =
|
|
99
|
+
function importToRows(data, table, user = null) {
|
|
100
100
|
let finalData = [];
|
|
101
101
|
for (let i = 0; i < data.length; i++) {
|
|
102
102
|
let row = data[i];
|
|
@@ -107,9 +107,7 @@ function importToRows(data, table, user = {}) {
|
|
|
107
107
|
});
|
|
108
108
|
row = processed.row;
|
|
109
109
|
table = processed.table;
|
|
110
|
-
|
|
111
|
-
let schema;
|
|
112
|
-
for ([fieldName, schema] of Object.entries(table.schema)) {
|
|
110
|
+
for (const [fieldName, schema] of Object.entries(table.schema)) {
|
|
113
111
|
// check whether the options need to be updated for inclusion as part of the data import
|
|
114
112
|
if (schema.type === constants_1.FieldTypes.OPTIONS &&
|
|
115
113
|
row[fieldName] &&
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.shutdown = void 0;
|
|
7
7
|
const applications_1 = __importDefault(require("./applications"));
|
|
8
|
+
const metrics_1 = __importDefault(require("./metrics"));
|
|
8
9
|
const queries_1 = __importDefault(require("./queries"));
|
|
9
10
|
const tables_1 = __importDefault(require("./tables"));
|
|
10
11
|
const rows_1 = __importDefault(require("./rows"));
|
|
@@ -86,6 +87,12 @@ function addToRouter(endpoints) {
|
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
89
|
}
|
|
90
|
+
function applyAdminRoutes(endpoints) {
|
|
91
|
+
addMiddleware(endpoints.read, backend_core_1.middleware.builderOrAdmin);
|
|
92
|
+
addMiddleware(endpoints.write, backend_core_1.middleware.builderOrAdmin);
|
|
93
|
+
addToRouter(endpoints.read);
|
|
94
|
+
addToRouter(endpoints.write);
|
|
95
|
+
}
|
|
89
96
|
function applyRoutes(endpoints, permType, resource, subResource) {
|
|
90
97
|
const paramMiddleware = subResource
|
|
91
98
|
? (0, resourceId_1.paramSubResource)(resource, subResource)
|
|
@@ -107,6 +114,7 @@ function applyRoutes(endpoints, permType, resource, subResource) {
|
|
|
107
114
|
addToRouter(endpoints.read);
|
|
108
115
|
addToRouter(endpoints.write);
|
|
109
116
|
}
|
|
117
|
+
applyAdminRoutes(metrics_1.default);
|
|
110
118
|
applyRoutes(applications_1.default, PermissionType.APP, "appId");
|
|
111
119
|
applyRoutes(tables_1.default, PermissionType.TABLE, "tableId");
|
|
112
120
|
applyRoutes(users_1.default, PermissionType.USER, "userId");
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const metrics_1 = __importDefault(require("../../controllers/public/metrics"));
|
|
7
|
+
const Endpoint_1 = __importDefault(require("./utils/Endpoint"));
|
|
8
|
+
const read = [];
|
|
9
|
+
/**
|
|
10
|
+
* @openapi
|
|
11
|
+
* /metrics:
|
|
12
|
+
* get:
|
|
13
|
+
* operationId: metricsGet
|
|
14
|
+
* summary: Retrieve Budibase tenant metrics
|
|
15
|
+
* description: Output metrics in OpenMetrics format compatible with Prometheus
|
|
16
|
+
* tags:
|
|
17
|
+
* - metrics
|
|
18
|
+
* responses:
|
|
19
|
+
* 200:
|
|
20
|
+
* description: Returns tenant metrics.
|
|
21
|
+
* content:
|
|
22
|
+
* text/plain:
|
|
23
|
+
* schema:
|
|
24
|
+
* type: string
|
|
25
|
+
* examples:
|
|
26
|
+
* metrics:
|
|
27
|
+
* $ref: '#/components/examples/metrics'
|
|
28
|
+
*/
|
|
29
|
+
read.push(new Endpoint_1.default("get", "/metrics", metrics_1.default.fetch));
|
|
30
|
+
exports.default = { read };
|
package/dist/app.js
CHANGED
|
@@ -105,6 +105,7 @@ server.on("close", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
105
105
|
}
|
|
106
106
|
shuttingDown = true;
|
|
107
107
|
console.log("Server Closed");
|
|
108
|
+
backend_core_1.timers.cleanup();
|
|
108
109
|
yield automations.shutdown();
|
|
109
110
|
yield redis.shutdown();
|
|
110
111
|
backend_core_1.events.shutdown();
|
|
@@ -201,6 +201,10 @@ class GoogleSheetsIntegration {
|
|
|
201
201
|
}
|
|
202
202
|
buildSchema(datasourceId, entities) {
|
|
203
203
|
return __awaiter(this, void 0, void 0, function* () {
|
|
204
|
+
// not fully configured yet
|
|
205
|
+
if (!this.config.auth) {
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
204
208
|
yield this.connect();
|
|
205
209
|
const sheets = this.client.sheetsByIndex;
|
|
206
210
|
const tables = {};
|
|
@@ -21,34 +21,14 @@ exports.default = (ctx, next) => __awaiter(void 0, void 0, void 0, function* ()
|
|
|
21
21
|
var _a;
|
|
22
22
|
// try to get the appID from the request
|
|
23
23
|
let requestAppId = yield backend_core_1.utils.getAppIdFromCtx(ctx);
|
|
24
|
-
|
|
25
|
-
let appCookie;
|
|
26
|
-
try {
|
|
27
|
-
appCookie = backend_core_1.utils.getCookie(ctx, backend_core_1.constants.Cookie.CurrentApp);
|
|
28
|
-
}
|
|
29
|
-
catch (err) {
|
|
30
|
-
backend_core_1.utils.clearCookie(ctx, backend_core_1.constants.Cookie.CurrentApp);
|
|
31
|
-
}
|
|
32
|
-
if (!appCookie && !requestAppId) {
|
|
24
|
+
if (!requestAppId) {
|
|
33
25
|
return next();
|
|
34
26
|
}
|
|
35
|
-
// check the app exists referenced in cookie
|
|
36
|
-
if (appCookie) {
|
|
37
|
-
const appId = appCookie.appId;
|
|
38
|
-
const exists = yield backend_core_1.db.dbExists(appId);
|
|
39
|
-
if (!exists) {
|
|
40
|
-
backend_core_1.utils.clearCookie(ctx, backend_core_1.constants.Cookie.CurrentApp);
|
|
41
|
-
return next();
|
|
42
|
-
}
|
|
43
|
-
// if the request app ID wasn't set, update it with the cookie
|
|
44
|
-
requestAppId = requestAppId || appId;
|
|
45
|
-
}
|
|
46
27
|
// deny access to application preview
|
|
47
28
|
if (!environment_1.default.isTest()) {
|
|
48
29
|
if ((0, utils_1.isDevAppID)(requestAppId) &&
|
|
49
30
|
!(0, utils_2.isWebhookEndpoint)(ctx) &&
|
|
50
31
|
(!ctx.user || !ctx.user.builder || !ctx.user.builder.global)) {
|
|
51
|
-
backend_core_1.utils.clearCookie(ctx, backend_core_1.constants.Cookie.CurrentApp);
|
|
52
32
|
return ctx.redirect("/");
|
|
53
33
|
}
|
|
54
34
|
}
|
|
@@ -118,12 +98,6 @@ exports.default = (ctx, next) => __awaiter(void 0, void 0, void 0, function* ()
|
|
|
118
98
|
globalId,
|
|
119
99
|
roleId, role: yield backend_core_1.roles.getRole(roleId) });
|
|
120
100
|
}
|
|
121
|
-
if ((requestAppId !== appId ||
|
|
122
|
-
appCookie == null ||
|
|
123
|
-
appCookie.appId !== requestAppId) &&
|
|
124
|
-
!skipCookie) {
|
|
125
|
-
backend_core_1.utils.setCookie(ctx, { appId }, backend_core_1.constants.Cookie.CurrentApp);
|
|
126
|
-
}
|
|
127
101
|
return next();
|
|
128
102
|
}));
|
|
129
103
|
});
|