@budibase/server 2.5.6-alpha.14 → 2.5.6-alpha.16
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.b2935042.js → index.46394ade.js} +319 -320
- package/builder/index.html +1 -1
- package/dist/api/routes/index.js +0 -2
- package/dist/package.json +7 -7
- package/dist/sdk/app/backups/exports.js +1 -35
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/src/api/index.ts +0 -1
- package/src/api/routes/index.ts +0 -2
- package/src/sdk/app/backups/exports.ts +0 -35
- package/dist/api/controllers/cloud.js +0 -130
- package/dist/api/routes/cloud.js +0 -39
- 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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/server",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "2.5.6-alpha.
|
|
4
|
+
"version": "2.5.6-alpha.16",
|
|
5
5
|
"description": "Budibase Web Server",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -45,12 +45,12 @@
|
|
|
45
45
|
"license": "GPL-3.0",
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@apidevtools/swagger-parser": "10.0.3",
|
|
48
|
-
"@budibase/backend-core": "2.5.6-alpha.
|
|
49
|
-
"@budibase/client": "2.5.6-alpha.
|
|
50
|
-
"@budibase/pro": "2.5.6-alpha.
|
|
51
|
-
"@budibase/shared-core": "2.5.6-alpha.
|
|
52
|
-
"@budibase/string-templates": "2.5.6-alpha.
|
|
53
|
-
"@budibase/types": "2.5.6-alpha.
|
|
48
|
+
"@budibase/backend-core": "2.5.6-alpha.16",
|
|
49
|
+
"@budibase/client": "2.5.6-alpha.16",
|
|
50
|
+
"@budibase/pro": "2.5.6-alpha.15",
|
|
51
|
+
"@budibase/shared-core": "2.5.6-alpha.16",
|
|
52
|
+
"@budibase/string-templates": "2.5.6-alpha.16",
|
|
53
|
+
"@budibase/types": "2.5.6-alpha.16",
|
|
54
54
|
"@bull-board/api": "3.7.0",
|
|
55
55
|
"@bull-board/koa": "3.9.4",
|
|
56
56
|
"@elastic/elasticsearch": "7.10.0",
|
|
@@ -176,5 +176,5 @@
|
|
|
176
176
|
"optionalDependencies": {
|
|
177
177
|
"oracledb": "5.3.0"
|
|
178
178
|
},
|
|
179
|
-
"gitHead": "
|
|
179
|
+
"gitHead": "5d2b4112effb2cc3dbb67a95f60e38ae0f672559"
|
|
180
180
|
}
|
package/src/api/index.ts
CHANGED
|
@@ -4,7 +4,6 @@ import currentApp from "../middleware/currentapp"
|
|
|
4
4
|
import zlib from "zlib"
|
|
5
5
|
import { mainRoutes, staticRoutes, publicRoutes } from "./routes"
|
|
6
6
|
import pkg from "../../package.json"
|
|
7
|
-
import env from "../environment"
|
|
8
7
|
import { middleware as pro } from "@budibase/pro"
|
|
9
8
|
export { shutdown } from "./routes/public"
|
|
10
9
|
const compress = require("koa-compress")
|
package/src/api/routes/index.ts
CHANGED
|
@@ -22,7 +22,6 @@ import queryRoutes from "./query"
|
|
|
22
22
|
import backupRoutes from "./backup"
|
|
23
23
|
import metadataRoutes from "./metadata"
|
|
24
24
|
import devRoutes from "./dev"
|
|
25
|
-
import cloudRoutes from "./cloud"
|
|
26
25
|
import migrationRoutes from "./migrations"
|
|
27
26
|
import pluginRoutes from "./plugin"
|
|
28
27
|
import opsRoutes from "./ops"
|
|
@@ -60,7 +59,6 @@ export const mainRoutes: Router[] = [
|
|
|
60
59
|
queryRoutes,
|
|
61
60
|
metadataRoutes,
|
|
62
61
|
devRoutes,
|
|
63
|
-
cloudRoutes,
|
|
64
62
|
rowRoutes,
|
|
65
63
|
migrationRoutes,
|
|
66
64
|
pluginRoutes,
|
|
@@ -148,41 +148,6 @@ export async function exportApp(appId: string, config?: ExportOpts) {
|
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
/**
|
|
152
|
-
* Export all apps + global DB (if supplied) to a single tarball, this includes
|
|
153
|
-
* the attachments for each app as well.
|
|
154
|
-
* @param {object[]} appMetadata The IDs and names of apps to export.
|
|
155
|
-
* @param {string} globalDbContents The contents of the global DB to export as well.
|
|
156
|
-
* @return {string} The path to the tarball.
|
|
157
|
-
*/
|
|
158
|
-
export async function exportMultipleApps(
|
|
159
|
-
appMetadata: { appId: string; name: string }[],
|
|
160
|
-
globalDbContents?: string
|
|
161
|
-
) {
|
|
162
|
-
const tmpPath = join(budibaseTempDir(), uuid())
|
|
163
|
-
fs.mkdirSync(tmpPath)
|
|
164
|
-
let exportPromises: Promise<void>[] = []
|
|
165
|
-
// export each app to a directory, then move it into the complete export
|
|
166
|
-
const exportAndMove = async (appId: string, appName: string) => {
|
|
167
|
-
const path = await exportApp(appId)
|
|
168
|
-
await fs.promises.rename(path, join(tmpPath, appName))
|
|
169
|
-
}
|
|
170
|
-
for (let metadata of appMetadata) {
|
|
171
|
-
exportPromises.push(exportAndMove(metadata.appId, metadata.name))
|
|
172
|
-
}
|
|
173
|
-
// wait for all exports to finish
|
|
174
|
-
await Promise.all(exportPromises)
|
|
175
|
-
// add the global DB contents
|
|
176
|
-
if (globalDbContents) {
|
|
177
|
-
fs.writeFileSync(join(tmpPath, GLOBAL_DB_EXPORT_FILE), globalDbContents)
|
|
178
|
-
}
|
|
179
|
-
const appNames = appMetadata.map(metadata => metadata.name)
|
|
180
|
-
const tarPath = tarFilesToTmp(tmpPath, [...appNames, GLOBAL_DB_EXPORT_FILE])
|
|
181
|
-
// clear up the tmp path now tarball generated
|
|
182
|
-
fs.rmSync(tmpPath, { recursive: true, force: true })
|
|
183
|
-
return tarPath
|
|
184
|
-
}
|
|
185
|
-
|
|
186
151
|
/**
|
|
187
152
|
* Streams a backup of the database state for an app
|
|
188
153
|
* @param {string} appId The ID of the app which is to be backed up.
|
|
@@ -1,130 +0,0 @@
|
|
|
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.importApps = exports.hasBeenImported = exports.exportApps = void 0;
|
|
16
|
-
const environment_1 = __importDefault(require("../../environment"));
|
|
17
|
-
const backend_core_1 = require("@budibase/backend-core");
|
|
18
|
-
const fileSystem_1 = require("../../utilities/fileSystem");
|
|
19
|
-
const utilities_1 = require("../../utilities");
|
|
20
|
-
const utils_1 = require("../../db/utils");
|
|
21
|
-
const application_1 = require("./application");
|
|
22
|
-
const path_1 = require("path");
|
|
23
|
-
const sdk_1 = __importDefault(require("../../sdk"));
|
|
24
|
-
function createApp(appName, appDirectory) {
|
|
25
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
-
const ctx = {
|
|
27
|
-
request: {
|
|
28
|
-
body: {
|
|
29
|
-
useTemplate: true,
|
|
30
|
-
name: appName,
|
|
31
|
-
},
|
|
32
|
-
files: {
|
|
33
|
-
templateFile: {
|
|
34
|
-
path: appDirectory,
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
// @ts-ignore
|
|
40
|
-
return (0, application_1.create)(ctx);
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
function getAllDocType(db, docType) {
|
|
44
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
-
const response = yield db.allDocs((0, utils_1.getDocParams)(docType, null, {
|
|
46
|
-
include_docs: true,
|
|
47
|
-
}));
|
|
48
|
-
return response.rows.map(row => row.doc);
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
function exportApps(ctx) {
|
|
52
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
53
|
-
if (environment_1.default.SELF_HOSTED || !environment_1.default.MULTI_TENANCY) {
|
|
54
|
-
ctx.throw(400, "Exporting only allowed in multi-tenant cloud environments.");
|
|
55
|
-
}
|
|
56
|
-
const apps = (yield backend_core_1.db.getAllApps({ all: true }));
|
|
57
|
-
const globalDBString = yield sdk_1.default.backups.exportDB(backend_core_1.db.getGlobalDBName(), {
|
|
58
|
-
filter: (doc) => !doc._id.startsWith(utils_1.DocumentType.USER),
|
|
59
|
-
});
|
|
60
|
-
// only export the dev apps as they will be the latest, the user can republish the apps
|
|
61
|
-
// in their self-hosted environment
|
|
62
|
-
let appMetadata = apps
|
|
63
|
-
.filter((app) => (0, utils_1.isDevAppID)(app.appId || app._id))
|
|
64
|
-
.map((app) => ({ appId: (app.appId || app._id), name: app.name }));
|
|
65
|
-
const tmpPath = yield sdk_1.default.backups.exportMultipleApps(appMetadata, globalDBString);
|
|
66
|
-
const filename = `cloud-export-${new Date().getTime()}.tar.gz`;
|
|
67
|
-
ctx.attachment(filename);
|
|
68
|
-
ctx.body = (0, fileSystem_1.streamFile)(tmpPath);
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
exports.exportApps = exportApps;
|
|
72
|
-
function checkHasBeenImported() {
|
|
73
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
-
if (!environment_1.default.SELF_HOSTED) {
|
|
75
|
-
return true;
|
|
76
|
-
}
|
|
77
|
-
const apps = yield backend_core_1.db.getAllApps({ all: true });
|
|
78
|
-
return apps.length !== 0;
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
function hasBeenImported(ctx) {
|
|
82
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
83
|
-
ctx.body = {
|
|
84
|
-
imported: yield checkHasBeenImported(),
|
|
85
|
-
};
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
exports.hasBeenImported = hasBeenImported;
|
|
89
|
-
function importApps(ctx) {
|
|
90
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
91
|
-
if (!environment_1.default.SELF_HOSTED) {
|
|
92
|
-
ctx.throw(400, "Importing only allowed in self hosted environments.");
|
|
93
|
-
}
|
|
94
|
-
const beenImported = yield checkHasBeenImported();
|
|
95
|
-
if (beenImported || !ctx.request.files || !ctx.request.files.importFile) {
|
|
96
|
-
ctx.throw(400, "Import file is required and environment must be fresh to import apps.");
|
|
97
|
-
}
|
|
98
|
-
const file = ctx.request.files.importFile;
|
|
99
|
-
if (Array.isArray(file)) {
|
|
100
|
-
ctx.throw(400, "Single file is required");
|
|
101
|
-
}
|
|
102
|
-
if (file.type !== "application/gzip" && file.type !== "application/x-gzip") {
|
|
103
|
-
ctx.throw(400, "Import file must be a gzipped tarball.");
|
|
104
|
-
}
|
|
105
|
-
// initially get all the app databases out of the tarball
|
|
106
|
-
const tmpPath = sdk_1.default.backups.untarFile(file);
|
|
107
|
-
const globalDbImport = sdk_1.default.backups.getGlobalDBFile(tmpPath);
|
|
108
|
-
const appNames = sdk_1.default.backups.getListOfAppsInMulti(tmpPath);
|
|
109
|
-
const globalDb = backend_core_1.tenancy.getGlobalDB();
|
|
110
|
-
// load the global db first
|
|
111
|
-
yield globalDb.load((0, utilities_1.stringToReadStream)(globalDbImport));
|
|
112
|
-
for (let appName of appNames) {
|
|
113
|
-
yield createApp(appName, (0, path_1.join)(tmpPath, appName));
|
|
114
|
-
}
|
|
115
|
-
// if there are any users make sure to remove them
|
|
116
|
-
let users = yield getAllDocType(globalDb, utils_1.DocumentType.USER);
|
|
117
|
-
let userDeletionPromises = [];
|
|
118
|
-
for (let user of users) {
|
|
119
|
-
userDeletionPromises.push(globalDb.remove(user._id, user._rev));
|
|
120
|
-
}
|
|
121
|
-
if (userDeletionPromises.length > 0) {
|
|
122
|
-
yield Promise.all(userDeletionPromises);
|
|
123
|
-
}
|
|
124
|
-
yield globalDb.bulkDocs(users);
|
|
125
|
-
ctx.body = {
|
|
126
|
-
message: "Apps successfully imported.",
|
|
127
|
-
};
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
exports.importApps = importApps;
|
package/dist/api/routes/cloud.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
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
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
-
};
|
|
28
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
const router_1 = __importDefault(require("@koa/router"));
|
|
30
|
-
const controller = __importStar(require("../controllers/cloud"));
|
|
31
|
-
const authorized_1 = __importDefault(require("../../middleware/authorized"));
|
|
32
|
-
const backend_core_1 = require("@budibase/backend-core");
|
|
33
|
-
const router = new router_1.default();
|
|
34
|
-
router
|
|
35
|
-
.get("/api/cloud/export", (0, authorized_1.default)(backend_core_1.permissions.BUILDER), controller.exportApps)
|
|
36
|
-
// has to be public, only run if apps don't exist
|
|
37
|
-
.post("/api/cloud/import", controller.importApps)
|
|
38
|
-
.get("/api/cloud/import/complete", controller.hasBeenImported);
|
|
39
|
-
exports.default = router;
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import env from "../../environment"
|
|
2
|
-
import { db as dbCore, tenancy } from "@budibase/backend-core"
|
|
3
|
-
import { streamFile } from "../../utilities/fileSystem"
|
|
4
|
-
import { stringToReadStream } from "../../utilities"
|
|
5
|
-
import { getDocParams, DocumentType, isDevAppID } from "../../db/utils"
|
|
6
|
-
import { create } from "./application"
|
|
7
|
-
import { join } from "path"
|
|
8
|
-
import sdk from "../../sdk"
|
|
9
|
-
import { App, Ctx, Database } from "@budibase/types"
|
|
10
|
-
|
|
11
|
-
async function createApp(appName: string, appDirectory: string) {
|
|
12
|
-
const ctx = {
|
|
13
|
-
request: {
|
|
14
|
-
body: {
|
|
15
|
-
useTemplate: true,
|
|
16
|
-
name: appName,
|
|
17
|
-
},
|
|
18
|
-
files: {
|
|
19
|
-
templateFile: {
|
|
20
|
-
path: appDirectory,
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
},
|
|
24
|
-
}
|
|
25
|
-
// @ts-ignore
|
|
26
|
-
return create(ctx)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
async function getAllDocType(db: Database, docType: string) {
|
|
30
|
-
const response = await db.allDocs(
|
|
31
|
-
getDocParams(docType, null, {
|
|
32
|
-
include_docs: true,
|
|
33
|
-
})
|
|
34
|
-
)
|
|
35
|
-
return response.rows.map(row => row.doc)
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export async function exportApps(ctx: Ctx) {
|
|
39
|
-
if (env.SELF_HOSTED || !env.MULTI_TENANCY) {
|
|
40
|
-
ctx.throw(400, "Exporting only allowed in multi-tenant cloud environments.")
|
|
41
|
-
}
|
|
42
|
-
const apps = (await dbCore.getAllApps({ all: true })) as App[]
|
|
43
|
-
const globalDBString = await sdk.backups.exportDB(dbCore.getGlobalDBName(), {
|
|
44
|
-
filter: (doc: any) => !doc._id.startsWith(DocumentType.USER),
|
|
45
|
-
})
|
|
46
|
-
// only export the dev apps as they will be the latest, the user can republish the apps
|
|
47
|
-
// in their self-hosted environment
|
|
48
|
-
let appMetadata = apps
|
|
49
|
-
.filter((app: App) => isDevAppID(app.appId || app._id))
|
|
50
|
-
.map((app: App) => ({ appId: (app.appId || app._id)!, name: app.name }))
|
|
51
|
-
const tmpPath = await sdk.backups.exportMultipleApps(
|
|
52
|
-
appMetadata,
|
|
53
|
-
globalDBString
|
|
54
|
-
)
|
|
55
|
-
const filename = `cloud-export-${new Date().getTime()}.tar.gz`
|
|
56
|
-
ctx.attachment(filename)
|
|
57
|
-
ctx.body = streamFile(tmpPath)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async function checkHasBeenImported() {
|
|
61
|
-
if (!env.SELF_HOSTED) {
|
|
62
|
-
return true
|
|
63
|
-
}
|
|
64
|
-
const apps = await dbCore.getAllApps({ all: true })
|
|
65
|
-
return apps.length !== 0
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export async function hasBeenImported(ctx: Ctx) {
|
|
69
|
-
ctx.body = {
|
|
70
|
-
imported: await checkHasBeenImported(),
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
export async function importApps(ctx: Ctx) {
|
|
75
|
-
if (!env.SELF_HOSTED) {
|
|
76
|
-
ctx.throw(400, "Importing only allowed in self hosted environments.")
|
|
77
|
-
}
|
|
78
|
-
const beenImported = await checkHasBeenImported()
|
|
79
|
-
if (beenImported || !ctx.request.files || !ctx.request.files.importFile) {
|
|
80
|
-
ctx.throw(
|
|
81
|
-
400,
|
|
82
|
-
"Import file is required and environment must be fresh to import apps."
|
|
83
|
-
)
|
|
84
|
-
}
|
|
85
|
-
const file = ctx.request.files.importFile as any
|
|
86
|
-
if (Array.isArray(file)) {
|
|
87
|
-
ctx.throw(400, "Single file is required")
|
|
88
|
-
}
|
|
89
|
-
if (file.type !== "application/gzip" && file.type !== "application/x-gzip") {
|
|
90
|
-
ctx.throw(400, "Import file must be a gzipped tarball.")
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// initially get all the app databases out of the tarball
|
|
94
|
-
const tmpPath = sdk.backups.untarFile(file)
|
|
95
|
-
const globalDbImport = sdk.backups.getGlobalDBFile(tmpPath)
|
|
96
|
-
const appNames = sdk.backups.getListOfAppsInMulti(tmpPath)
|
|
97
|
-
|
|
98
|
-
const globalDb = tenancy.getGlobalDB()
|
|
99
|
-
// load the global db first
|
|
100
|
-
await globalDb.load(stringToReadStream(globalDbImport))
|
|
101
|
-
for (let appName of appNames) {
|
|
102
|
-
await createApp(appName, join(tmpPath, appName))
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// if there are any users make sure to remove them
|
|
106
|
-
let users = await getAllDocType(globalDb, DocumentType.USER)
|
|
107
|
-
let userDeletionPromises = []
|
|
108
|
-
for (let user of users) {
|
|
109
|
-
userDeletionPromises.push(globalDb.remove(user._id, user._rev))
|
|
110
|
-
}
|
|
111
|
-
if (userDeletionPromises.length > 0) {
|
|
112
|
-
await Promise.all(userDeletionPromises)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
await globalDb.bulkDocs(users)
|
|
116
|
-
ctx.body = {
|
|
117
|
-
message: "Apps successfully imported.",
|
|
118
|
-
}
|
|
119
|
-
}
|
package/src/api/routes/cloud.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import Router from "@koa/router"
|
|
2
|
-
import * as controller from "../controllers/cloud"
|
|
3
|
-
import authorized from "../../middleware/authorized"
|
|
4
|
-
import { permissions } from "@budibase/backend-core"
|
|
5
|
-
|
|
6
|
-
const router: Router = new Router()
|
|
7
|
-
|
|
8
|
-
router
|
|
9
|
-
.get(
|
|
10
|
-
"/api/cloud/export",
|
|
11
|
-
authorized(permissions.BUILDER),
|
|
12
|
-
controller.exportApps
|
|
13
|
-
)
|
|
14
|
-
// has to be public, only run if apps don't exist
|
|
15
|
-
.post("/api/cloud/import", controller.importApps)
|
|
16
|
-
.get("/api/cloud/import/complete", controller.hasBeenImported)
|
|
17
|
-
|
|
18
|
-
export default router
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { App } from "@budibase/types"
|
|
2
|
-
|
|
3
|
-
jest.setTimeout(30000)
|
|
4
|
-
|
|
5
|
-
import { AppStatus } from "../../../db/utils"
|
|
6
|
-
|
|
7
|
-
import * as setup from "./utilities"
|
|
8
|
-
|
|
9
|
-
import { wipeDb } from "./utilities/TestFunctions"
|
|
10
|
-
import { tenancy } from "@budibase/backend-core"
|
|
11
|
-
|
|
12
|
-
describe("/cloud", () => {
|
|
13
|
-
let request = setup.getRequest()!
|
|
14
|
-
let config = setup.getConfig()
|
|
15
|
-
|
|
16
|
-
afterAll(setup.afterAll)
|
|
17
|
-
|
|
18
|
-
beforeAll(async () => {
|
|
19
|
-
// Importing is only allowed in self hosted environments
|
|
20
|
-
await config.init()
|
|
21
|
-
config.modeSelf()
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
describe("import", () => {
|
|
25
|
-
it("should be able to import apps", async () => {
|
|
26
|
-
// first we need to delete any existing apps on the system so it looks clean otherwise the
|
|
27
|
-
// import will not run
|
|
28
|
-
await wipeDb()
|
|
29
|
-
|
|
30
|
-
// Perform the import
|
|
31
|
-
const res = await request
|
|
32
|
-
.post(`/api/cloud/import`)
|
|
33
|
-
.set(config.publicHeaders())
|
|
34
|
-
.attach("importFile", "src/api/routes/tests/data/export-test.tar.gz")
|
|
35
|
-
.expect(200)
|
|
36
|
-
expect(res.body.message).toEqual("Apps successfully imported.")
|
|
37
|
-
|
|
38
|
-
// get a count of apps after the import
|
|
39
|
-
const postImportApps = await request
|
|
40
|
-
.get(`/api/applications?status=${AppStatus.ALL}`)
|
|
41
|
-
.set(config.publicHeaders())
|
|
42
|
-
.expect("Content-Type", /json/)
|
|
43
|
-
.expect(200)
|
|
44
|
-
|
|
45
|
-
const apps = postImportApps.body as App[]
|
|
46
|
-
// There are two apps in the file that was imported so check for this
|
|
47
|
-
expect(apps.length).toEqual(2)
|
|
48
|
-
// The new tenant id was assigned to the imported apps
|
|
49
|
-
expect(tenancy.getTenantIDFromAppID(apps[0].appId)).toBe(
|
|
50
|
-
config.getTenantId()
|
|
51
|
-
)
|
|
52
|
-
})
|
|
53
|
-
})
|
|
54
|
-
})
|