Browse Source

creating new apps ...

pull/12/head
michael shanks 7 years ago
parent
commit
66ba4e687f
  1. 1
      .gitignore
  2. 2
      packages/core
  3. 7
      packages/datastores/datastores/local.js
  4. 8
      packages/server/app.js
  5. 424
      packages/server/appPackages/master/appDefinition.json
  6. 60
      packages/server/appPackages/master/main.js
  7. 4
      packages/server/appPackages/master/plugins.js
  8. 1
      packages/server/appPackages/master/plugins.json
  9. 1
      packages/server/appPackages/testApp/access_levels.json
  10. 1
      packages/server/appPackages/testApp/appDefinition.json
  11. BIN
      packages/server/appPackages/testApp/dist/package.tar.gz
  12. 2
      packages/server/config.js
  13. 4
      packages/server/config.sample.js
  14. 42
      packages/server/initialise/createInstanceDb.js
  15. 21
      packages/server/initialise/createMasterDb.js
  16. 10
      packages/server/initialise/initialiseBudibase.js
  17. 26
      packages/server/initialise/initialiseRuntimePackages.js
  18. 28
      packages/server/middleware/routers.js
  19. 6
      packages/server/package.json
  20. 2
      packages/server/tests/all.spec.js
  21. 52
      packages/server/tests/authenticate.js
  22. 72
      packages/server/tests/createNewApp.js
  23. 9
      packages/server/tests/helpers.js
  24. 25
      packages/server/tests/testApp.js
  25. 6
      packages/server/utilities/constructHierarchy.js
  26. 29
      packages/server/utilities/createAppPackage.js
  27. 19
      packages/server/utilities/fsawait.js
  28. 8
      packages/server/utilities/runtimePackages.js
  29. 3
      packages/server/utilities/statusCodes.js
  30. 91
      packages/server/utilities/targzAppPackage.js
  31. 156
      packages/server/yarn.lock

1
.gitignore

@ -1,4 +1,5 @@
.data/ .data/
.temp/
# Logs # Logs
logs logs

2
packages/core

@ -1 +1 @@
Subproject commit feb2f3412a0e3748d6509a3693b1f38c448bd743 Subproject commit babcb77e70088ddd689062e1d02d8fe2c5bc3417

7
packages/datastores/datastores/local.js

@ -11,6 +11,7 @@ const rmdir = promisify(fs.rmdir);
const unlink = promisify(fs.unlink); const unlink = promisify(fs.unlink);
const readdir = promisify(fs.readdir); const readdir = promisify(fs.readdir);
const rename = promisify(fs.rename); const rename = promisify(fs.rename);
const stat = promisify(fs.stat);
const updateFile = root => async (path, file) => const updateFile = root => async (path, file) =>
await writeFile( await writeFile(
@ -77,6 +78,11 @@ const renameFile = root => async (oldPath, newPath) =>
join(root, newPath) join(root, newPath)
); );
const getFileSize = root => async (path) =>
(await stat(
join(root,path)
)).size;
const datastoreFolder = (applicationId, instanceId) => const datastoreFolder = (applicationId, instanceId) =>
applicationId === "master" ? "master" applicationId === "master" ? "master"
: `app.${applicationId}.${instanceId}`; : `app.${applicationId}.${instanceId}`;
@ -120,6 +126,7 @@ module.exports.getDatastore = rootFolderPath => ({
writableFileStream: writableFileStream(rootFolderPath), writableFileStream: writableFileStream(rootFolderPath),
renameFile: renameFile(rootFolderPath), renameFile: renameFile(rootFolderPath),
getFolderContents: getFolderContents(rootFolderPath), getFolderContents: getFolderContents(rootFolderPath),
getFileSize: getFileSize(rootFolderPath),
createEmptyDb: createEmptyDb(rootFolderPath), createEmptyDb: createEmptyDb(rootFolderPath),
datastoreType : "local", datastoreType : "local",
datastoreDescription: rootFolderPath datastoreDescription: rootFolderPath

8
packages/server/app.js

@ -2,19 +2,19 @@ const Koa = require('koa');
const app = new Koa(); const app = new Koa();
const getMasterAppInternal = require("./utilities/masterAppInternal"); const getMasterAppInternal = require("./utilities/masterAppInternal");
const router = require("./middleware/routers"); const router = require("./middleware/routers");
const bodyParser = require('koa-bodyparser'); const koaBody = require('koa-body');
const initialiseRuntimeApps = require("./initialise/initialiseRuntimePackages"); const initialiseRuntimePackages = require("./initialise/initialiseRuntimePackages");
module.exports = async (config) => { module.exports = async (config) => {
app.keys = config.keys; app.keys = config.keys;
app.context.master = await getMasterAppInternal(config); app.context.master = await getMasterAppInternal(config);
app.context.getAppPackage = await initialiseRuntimeApps( app.context.getAppPackage = await initialiseRuntimePackages(
config, config,
app.context.master, app.context.master,
config.latestAppsPath config.latestAppsPath
) )
app.use(bodyParser()); app.use(koaBody({ multipart : true }));
app.use(router(config, app).routes()); app.use(router(config, app).routes());
return app.listen(); return app.listen();
}; };

424
packages/server/appPackages/master/appDefinition.json

File diff suppressed because one or more lines are too long

60
packages/server/appPackages/master/main.js

@ -0,0 +1,60 @@
const { tmpdir } = require("os");
const { join } = require("path");
const uuid = require("uuid/v1");
const { take, takeRight } = require("lodash/fp");
const { splitKey, $ } = require("budibase-core").common;
const { unzipTarGzPackageToRuntime } = require("../../utilities/targzAppPackage");
const { getRuntimePackageDirectory } = require("../../utilities/runtimePackages");
const { exists } = require("../../utilities/fsawait");
const createInstanceDb = require("../../initialise/createInstanceDb");
module.exports = (config) => ({
initialiseInstance : async ({ instance, apis }) => {
const appKey = $(instance.key, [
splitKey,
take(2)
]);
const application = await apis.recordApi.load(appKey);
const dbConfig = await createInstanceDb(
require(config.datastore),
config.datastoreConfig,
application.id,
instance.id
);
const versionId = $(instance.version.key, [
splitKey,
takeRight(1)
]);
const runtimeDir = getRuntimePackageDirectory(
application.name,
versionId);
if(!await exists(runtimeDir))
await downloadAppPackage(instance, application.name, versionId);
instance.datastoreconfig = JSON.stringify(dbConfig);
instance.isNew = false;
await apis.recordApi.save(instance);
}
});
const downloadAppPackage = async (instance, appName, versionId) => {
const inputStream = apis.recordApi.downloadFile(instance.key, "package.tar.gz");
const tempFilePath = join(tmpdir(), `bbpackage_${uuid()}.tar.gz`);
const outputStream = await app.datastore.writableFileStream(
tempFilePath);
await new Promise((resolve,reject) => {
inputStream.pipe(outputStream);
outputStream.on('error', reject);
outputStream.on('finish', resolve);
});
await unzipTarGzPackageToRuntime(tempFilePath, appName, versionId);
}

4
packages/server/appPackages/master/plugins.js

@ -0,0 +1,4 @@
module.exports = config => ({
main: require("./main")(config)
});

1
packages/server/appPackages/master/plugins.json

@ -1 +0,0 @@
{}

1
packages/server/appPackages/testApp/access_levels.json

@ -0,0 +1 @@
{"levels":[{"name":"owner","permissions":[{"type":"create record","nodeKey":"/applications/1-{id}"},{"type":"update record","nodeKey":"/applications/1-{id}"},{"type":"delete record","nodeKey":"/applications/1-{id}"},{"type":"read record","nodeKey":"/applications/1-{id}"},{"type":"create record","nodeKey":"/applications/1-{id}/users/8-{id}"},{"type":"update record","nodeKey":"/applications/1-{id}/users/8-{id}"},{"type":"delete record","nodeKey":"/applications/1-{id}/users/8-{id}"},{"type":"read record","nodeKey":"/applications/1-{id}/users/8-{id}"},{"type":"create record","nodeKey":"/applications/1-{id}/instances/2-{id}"},{"type":"update record","nodeKey":"/applications/1-{id}/instances/2-{id}"},{"type":"delete record","nodeKey":"/applications/1-{id}/instances/2-{id}"},{"type":"read record","nodeKey":"/applications/1-{id}/instances/2-{id}"},{"type":"create record","nodeKey":"/applications/1-{id}/versions/3-{id}"},{"type":"update record","nodeKey":"/applications/1-{id}/versions/3-{id}"},{"type":"delete record","nodeKey":"/applications/1-{id}/versions/3-{id}"},{"type":"read record","nodeKey":"/applications/1-{id}/versions/3-{id}"},{"type":"create record","nodeKey":"/applications/1-{id}/sessions/16-{id}"},{"type":"update record","nodeKey":"/applications/1-{id}/sessions/16-{id}"},{"type":"delete record","nodeKey":"/applications/1-{id}/sessions/16-{id}"},{"type":"read record","nodeKey":"/applications/1-{id}/sessions/16-{id}"},{"type":"create record","nodeKey":"/sessions/17-{id}"},{"type":"update record","nodeKey":"/sessions/17-{id}"},{"type":"delete record","nodeKey":"/sessions/17-{id}"},{"type":"read record","nodeKey":"/sessions/17-{id}"},{"type":"read index","nodeKey":"/mastersessions_by_user"},{"type":"read index","nodeKey":"/all_applications"},{"type":"read index","nodeKey":"/applications/1-{id}/allinstances"},{"type":"read index","nodeKey":"/applications/1-{id}/sessions_by_user"},{"type":"read index","nodeKey":"/applications/1-{id}/user_name_lookup"},{"type":"read index","nodeKey":"/applications/1-{id}/all_versions"},{"type":"read index","nodeKey":"/applications/1-{id}/instances/2-{id}/users_on_this_instance"},{"type":"read index","nodeKey":"/applications/1-{id}/versions/3-{id}/instances_for_this_version"},{"type":"read index","nodeKey":"/applications/1-{id}/versions/3-{id}/instances_on_this_version"},{"type":"write templates"},{"type":"create user"},{"type":"set password"},{"type":"create temporary access"},{"type":"enable or disable user"},{"type":"write access levels"},{"type":"list users"},{"type":"list access levels"},{"type":"manage index"},{"type":"manage collection"},{"type":"set user access levels"}]}],"version":0}

1
packages/server/appPackages/testApp/appDefinition.json

File diff suppressed because one or more lines are too long

BIN
packages/server/appPackages/testApp/dist/package.tar.gz

Binary file not shown.

2
packages/server/config.js

@ -8,6 +8,6 @@ module.exports = () => ({
keys: ["secret1", "secret2"], keys: ["secret1", "secret2"],
port: 4001, port: 4001,
latestAppsPath: "./appPackages", latestAppsPath: "./appPackages",
masterPlugins: {}, extraMasterPlugins: {},
customizeMaster: appDefinition => appDefinition customizeMaster: appDefinition => appDefinition
}) })

4
packages/server/config.sample.js

@ -18,10 +18,10 @@ module.exports = () => ({
port: 4001, port: 4001,
// path to where your appDefinition etc is stored (dev time) // path to where your appDefinition etc is stored (dev time)
latestAppsPath: "./appPackages", latestAppsPath: "./",
// register plugins for master // register plugins for master
masterPlugins: {}, extraMasterPlugins: {},
// make modifications to master's appdefinition - e.g. add plugins // make modifications to master's appdefinition - e.g. add plugins
customizeMaster: appDefinition => appDefinition customizeMaster: appDefinition => appDefinition

42
packages/server/initialise/createInstanceDb.js

@ -0,0 +1,42 @@
const {
initialiseData,
setupDatastore
} = require("budibase-core");
const constructHierarchy = require("../utilities/constructHierarchy");
const getDatabaseManager = require("../utilities/databaseManager");
const {
getApisForUser,
getApisWithFullAccess
} = require("../utilities/budibaseApi");
const masterDbAppDefinition = require("../appPackages/master/appDefinition.json");
const masterDbAccessLevels = require("../appPackages/master/access_levels.json");
const { masterAppPackage } = require("../utilities/createAppPackage");
module.exports = async (datastoreModule, rootDatastoreConfig, appId, instanceId) => {
try {
const databaseManager = getDatabaseManager(
datastoreModule, rootDatastoreConfig);
await databaseManager.createEmptyInstanceDb(
appId, instanceId);
const dbConfig = databaseManager.getInstanceDatastoreConfig(
appId, instanceId);
const datastore = setupDatastore(
datastoreModule.getDatastore(dbConfig));
await initialiseData(datastore,
constructHierarchy(masterDbAppDefinition));
return dbConfig;
} catch(e) {
throw e;
}
};

21
packages/server/initialise/createMasterDb.js

@ -1,14 +1,14 @@
const {initialiseData, setupDatastore, const {initialiseData, setupDatastore} = require("budibase-core");
getTemplateApi} = require("budibase-core"); const constructHierarchy = require("../utilities/constructHierarchy");
const getDatabaseManager = require("../utilities/databaseManager"); const getDatabaseManager = require("../utilities/databaseManager");
const {getApisForUser, getApisWithFullAccess} = require("../utilities/budibaseApi"); const {getApisForUser, getApisWithFullAccess} = require("../utilities/budibaseApi");
const masterDbAppDefinition = require("../appPackages/master/appDefinition.json"); const masterDbAppDefinition = require("../appPackages/master/appDefinition.json");
const masterDbAccessLevels = require("../appPackages/master/access_levels.json"); const masterDbAccessLevels = require("../appPackages/master/access_levels.json");
const { masterAppPackage } = require("../utilities/createAppPackage"); const { masterAppPackage } = require("../utilities/createAppPackage");
module.exports = async (datastoreModule, rootConfig, username, password) => { module.exports = async (datastoreModule, rootDatastoreConfig, username, password, budibaseConfig) => {
try { try {
const databaseManager = getDatabaseManager(datastoreModule, rootConfig); const databaseManager = getDatabaseManager(datastoreModule, rootDatastoreConfig);
await databaseManager.createEmptyMasterDb(); await databaseManager.createEmptyMasterDb();
const masterDbConfig = databaseManager.masterDatastoreConfig; const masterDbConfig = databaseManager.masterDatastoreConfig;
@ -16,23 +16,18 @@ module.exports = async (datastoreModule, rootConfig, username, password) => {
datastoreModule.getDatastore(masterDbConfig) datastoreModule.getDatastore(masterDbConfig)
); );
const templateApi = getTemplateApi({datastore}); await initialiseData(datastore,
constructHierarchy(masterDbAppDefinition));
await initialiseData(datastore, {
hierarchy:templateApi.constructHierarchy(masterDbAppDefinition.hierarchy),
actions:masterDbAppDefinition.actions,
triggers:masterDbAppDefinition.triggers
});
const bbMaster = await getApisWithFullAccess( const bbMaster = await getApisWithFullAccess(
datastore, masterAppPackage()); datastore, masterAppPackage(budibaseConfig));
await bbMaster.authApi.saveAccessLevels(masterDbAccessLevels); await bbMaster.authApi.saveAccessLevels(masterDbAccessLevels);
const user = bbMaster.authApi.getNewUser(); const user = bbMaster.authApi.getNewUser();
user.name = username; user.name = username;
user.accessLevels= ["owner"]; user.accessLevels= ["owner"];
await bbMaster.authApi.createUser(user, password); await bbMaster.authApi.createUser(user, password);
return await getApisForUser(datastore, masterAppPackage(), username, password); return await getApisForUser(datastore, masterAppPackage(budibaseConfig), username, password);
} catch(e) { } catch(e) {
throw e; throw e;
} }

10
packages/server/initialise/initialiseBudibase.js

@ -1,12 +1,11 @@
const create = require("./createMasterDb"); const create = require("./createMasterDb");
const argv = require("yargs").argv const argv = require("yargs").argv
const readline = require('readline'); const readline = require('readline');
const { promisify } = require('util'); const { promisify } = require('util');
const rimraf = promisify(require("rimraf")); const { mkdir, rimraf } = require("../utilities/fsawait");
const fs = require("fs") const budibaseConfig = require("../config");
const mkdir = promisify(fs.mkdir);
readline.Interface.prototype.question[promisify.custom] = function(prompt) { readline.Interface.prototype.question[promisify.custom] = function(prompt) {
return new Promise(resolve => return new Promise(resolve =>
@ -72,5 +71,6 @@ const question = async (q) => {
datastoreModule, datastoreModule,
rootconfig, rootconfig,
username, username,
password) password,
budibaseConfig)
})() })()

26
packages/server/initialise/initialiseRuntimePackages.js

@ -1,21 +1,7 @@
const util = require("util");
const fs = require("fs");
const { join } = require("path");
const { ncp } = require('ncp'); const { ncp } = require('ncp');
const { masterAppPackage } = require("../utilities/createAppPackage"); const { masterAppPackage } = require("../utilities/createAppPackage");
const rimraf = util.promisify(require("rimraf")); const { mkdir, rimraf, exists } = require("../utilities/fsawait");
const mkdir = util.promisify(fs.mkdir); const { runtimePackagesDirectory } = require("../utilities/runtimePackages");
const exists = root => async (path) => {
try {
await util.promisify(fs.access)(
join(root,path)
);
} catch (e) {
return false;
}
return true;
};
const copyfolder = (source, destination) => const copyfolder = (source, destination) =>
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
@ -28,20 +14,20 @@ const copyfolder = (source, destination) =>
}); });
}); });
module.exports = async (config, bbMaster, latestAppsFolder) => { module.exports = async (config, bbMaster, latestAppsFolder) => {
const appsRuntimeFolder = "./runtime_apps";
// create runtime folder // create runtime folder
// copy master into /master/latest // copy master into /master/latest
if(await exists(appsRuntimeFolder)) { if(await exists(runtimePackagesDirectory)) {
try { try {
await rimraf(appsRuntimeFolder); await rimraf(runtimePackagesDirectory);
} catch(err) { } catch(err) {
console.log(err); console.log(err);
} }
} }
await mkdir(appsRuntimeFolder); await mkdir(runtimePackagesDirectory);
/* /*

28
packages/server/middleware/routers.js

@ -1,6 +1,8 @@
const Router = require("koa-router"); const Router = require("@koa/router");
const session = require("./session"); const session = require("./session");
const StatusCodes = require("../utilities/statusCodes"); const StatusCodes = require("../utilities/statusCodes");
const fs = require("fs");
module.exports = (config, app) => { module.exports = (config, app) => {
const router = new Router(); const router = new Router();
@ -148,21 +150,30 @@ module.exports = (config, app) => {
); );
ctx.response.status = StatusCodes.OK; ctx.response.status = StatusCodes.OK;
}) })
.post("/:appname/api/record/:recordkey", async (ctx) => { .post("/:appname/api/files/*", async (ctx) => {
const file = ctx.request.files.file;
ctx.body = await ctx.instance.recordApi.uploadFile(
getRecordKey(ctx.params.appname, ctx.request.path),
fs.createReadStream(file.path),
file.name
);
ctx.response.status = StatusCodes.OK;
})
.post("/:appname/api/record/*", async (ctx) => {
ctx.body = await ctx.instance.recordApi.save( ctx.body = await ctx.instance.recordApi.save(
ctx.request.body ctx.request.body
); );
ctx.response.status = StatusCodes.OK; ctx.response.status = StatusCodes.OK;
}) })
.get("/:appname/api/record/:recordkey", async (ctx) => { .get("/:appname/api/record/*", async (ctx) => {
ctx.body = await ctx.instance.recordApi.load( ctx.body = await ctx.instance.recordApi.load(
ctx.params.recordKey getRecordKey(ctx.params.appname, ctx.request.path)
); );
ctx.response.status = StatusCodes.OK; ctx.response.status = StatusCodes.OK;
}) })
.del("/:appname/api/record/:recordkey", async (ctx) => { .del("/:appname/api/record/*", async (ctx) => {
await ctx.instance.recordApi.delete( await ctx.instance.recordApi.delete(
ctx.params.recordKey getRecordKey(ctx.params.appname, ctx.request.path)
); );
ctx.response.status = StatusCodes.OK; ctx.response.status = StatusCodes.OK;
}) })
@ -185,6 +196,11 @@ module.exports = (config, app) => {
ctx.response.status = StatusCodes.OK; ctx.response.status = StatusCodes.OK;
}); });
const getRecordKey = (appname, wholePath) =>
wholePath
.replace(`/${appname}/api/record/`, "")
.replace(`/${appname}/api/files/`, "");
return router; return router;
} }

6
packages/server/package.json

@ -12,14 +12,16 @@
"author": "Michael Shanks", "author": "Michael Shanks",
"license": "AGPL-3.0-or-later", "license": "AGPL-3.0-or-later",
"dependencies": { "dependencies": {
"@koa/router": "^8.0.0",
"argon2": "^0.23.0", "argon2": "^0.23.0",
"budibase-core": "file:../core/dist", "budibase-core": "file:../core/dist",
"koa": "^2.7.0", "koa": "^2.7.0",
"koa-bodyparser": "^4.2.1", "koa-body": "^4.1.0",
"koa-router": "^7.4.0",
"koa-session": "^5.12.0", "koa-session": "^5.12.0",
"ncp": "^2.0.0", "ncp": "^2.0.0",
"rimraf": "^2.6.3", "rimraf": "^2.6.3",
"tar-fs": "^2.0.0",
"uuid": "^3.3.2",
"yargs": "^13.2.4" "yargs": "^13.2.4"
}, },
"devDependencies": { "devDependencies": {

2
packages/server/tests/all.spec.js

@ -1,10 +1,12 @@
const app = require("./testApp")(); const app = require("./testApp")();
const authenticateMaster = require("./authenticate"); const authenticateMaster = require("./authenticate");
const createNewApp = require("./createNewApp");
beforeAll(async () => await app.start()) beforeAll(async () => await app.start())
afterAll(async () => await app.destroy()) afterAll(async () => await app.destroy())
describe("authenticateMaster", () => authenticateMaster(app)); describe("authenticateMaster", () => authenticateMaster(app));
describe("createNewApp", () => createNewApp(app));

52
packages/server/tests/authenticate.js

@ -1,7 +1,6 @@
const statusCodes = require("../utilities/statusCodes"); const statusCodes = require("../utilities/statusCodes");
const util = require("util"); const { readFile } = require("../utilities/fsawait");
const fs = require("fs"); const { timeout } = require("./helpers");
const readFile = util.promisify(fs.readFile);
module.exports = (app) => { module.exports = (app) => {
@ -31,7 +30,6 @@ module.exports = (app) => {
}); });
let ownerCookie;
it("should return ok correct username and password supplied", async () => { it("should return ok correct username and password supplied", async () => {
const response = await app.post("/_master/api/authenticate", { const response = await app.post("/_master/api/authenticate", {
@ -40,7 +38,7 @@ module.exports = (app) => {
}) })
.expect(statusCodes.OK); .expect(statusCodes.OK);
ownerCookie = response.header['set-cookie']; app.masterAuth.cookie = response.header['set-cookie'];
}); });
const testUserName = "test_user"; const testUserName = "test_user";
@ -56,7 +54,7 @@ module.exports = (app) => {
}, },
password: testPassword password: testPassword
}) })
.set("cookie", ownerCookie) .set("cookie", app.masterAuth.cookie)
.expect(statusCodes.OK); .expect(statusCodes.OK);
@ -74,7 +72,7 @@ module.exports = (app) => {
newUserCookie = responseNewUser.header['set-cookie']; newUserCookie = responseNewUser.header['set-cookie'];
expect(newUserCookie).toBeDefined(); expect(newUserCookie).toBeDefined();
expect(newUserCookie).not.toEqual(ownerCookie); expect(newUserCookie).not.toEqual(app.masterAuth.cookie);
app.get("/_master/api/users/") app.get("/_master/api/users/")
.set("cookie", newUserCookie) .set("cookie", newUserCookie)
@ -86,7 +84,7 @@ module.exports = (app) => {
await app.post("/_master/api/disableUser", { await app.post("/_master/api/disableUser", {
username: testUserName username: testUserName
}) })
.set("cookie", ownerCookie) .set("cookie", app.masterAuth.cookie)
.expect(statusCodes.OK); .expect(statusCodes.OK);
await app.get("/_master/api/users/") await app.get("/_master/api/users/")
@ -114,7 +112,7 @@ module.exports = (app) => {
await app.post("/_master/api/enableUser", { await app.post("/_master/api/enableUser", {
username: testUserName username: testUserName
}) })
.set("cookie", ownerCookie) .set("cookie", app.masterAuth.cookie)
.expect(statusCodes.OK); .expect(statusCodes.OK);
await app.post("/_master/api/authenticate", { await app.post("/_master/api/authenticate", {
@ -124,8 +122,9 @@ module.exports = (app) => {
.expect(statusCodes.OK); .expect(statusCodes.OK);
}); });
let testUserTempCode;
it("should be able to reset password with temporary access", async () => { it("should be able to reset password with temporary access", async () => {
// need to sort out behaviour sources for this...
await app.post("/_master/api/createTemporaryAccess", { await app.post("/_master/api/createTemporaryAccess", {
username: testUserName username: testUserName
}) })
@ -133,11 +132,15 @@ module.exports = (app) => {
testPassword = "test_user_new_password"; testPassword = "test_user_new_password";
const tempCode = await readFile(`./tests/.data/tempaccess${testUserName}`, "utf8"); // the behaviour that creates the below file is async,
/// to this timeout is giving it a change to work its magic
await timeout(10);
const testUserTempCode = await readFile(`./tests/.data/tempaccess${testUserName}`, "utf8");
await app.post("/_master/api/setPasswordFromTemporaryCode", { await app.post("/_master/api/setPasswordFromTemporaryCode", {
username: testUserName, username: testUserName,
tempCode, tempCode:testUserTempCode,
newPassword:testPassword newPassword:testPassword
}) })
.expect(statusCodes.OK); .expect(statusCodes.OK);
@ -148,5 +151,30 @@ module.exports = (app) => {
}) })
.expect(statusCodes.OK); .expect(statusCodes.OK);
});
it("should not be able to set password with used temp code", async () => {
await app.post("/_master/api/setPasswordFromTemporaryCode", {
username: testUserName,
tempCode:testUserTempCode,
newPassword:"whatever"
})
.expect(statusCodes.OK);
await app.post("/_master/api/authenticate", {
username: testUserName,
password: "whatever"
})
.expect(statusCodes.UNAUTHORIZED);
await app.post("/_master/api/authenticate", {
username: testUserName,
password: testPassword
})
.expect(statusCodes.OK);
}); });
}; };

72
packages/server/tests/createNewApp.js

@ -0,0 +1,72 @@
const statusCodes = require("../utilities/statusCodes");
const constructHierarchy = require("../utilities/constructHierarchy");
const { readFile } = require("../utilities/fsawait");
const {getRecordApi, getAuthApi} = require("budibase-core");
const masterAppDefinition = constructHierarchy(
require("../appPackages/master/appDefinition.json"));
const {getApisWithFullAccess} = require("../utilities/budibaseApi");
const { createTarGzPackage } = require("../utilities/targzAppPackage");
module.exports = (app) => {
let _master;
const getmaster = async () => {
if(!_master)
_master = await getApisWithFullAccess({}, app.masterAppPackage);
return _master;
}
let newAppKey = "";
it("create new application should be successful for owner", async () => {
const master = await getmaster();
const newApp = master.recordApi.getNew("/applications", "application");
newApp.name = app.testAppInfo.name
newAppKey = newApp.key;
await app.post(`/_master/api/record/${newApp.key}`, newApp)
.set("cookie", app.masterAuth.cookie)
.expect(statusCodes.OK);
const response = await app.get(`/_master/api/record/${newApp.key}`)
.set("cookie", app.masterAuth.cookie)
.expect(statusCodes.OK);
expect(response.body.name).toBe(newApp.name);
});
let version1Key = "";
it("should be able to upload new version including package files", async () => {
const master = await getmaster();
const version1 = master.recordApi
.getNew(`${newAppKey}/versions`, "version");
version1.name = "v1";
version1Key = version1.key;
const { path, size } = await createTarGzPackage(app.config, "testApp");
version1.package = { relativePath: "package.tar.gz", size};
await app.post(`/_master/api/record/${version1.key}`, version1)
.set("cookie", app.masterAuth.cookie)
.expect(statusCodes.OK);
await app.post(`/_master/api/files/${version1.key}`)
.attach("file", path, "package.tar.gz")
.set("cookie", app.masterAuth.cookie)
.expect(statusCodes.OK);
});
it("should be able to create new instance of app", async () => {
const master = await getmaster();
const instance1 = master.recordApi
.getNew(`${newAppKey}/instances`, "instance");
instance1.name = "instance 1";
instance1.active = true;
instance1.version = {key:version1Key, name:"v1"};
instance1.datastoreconfig;
});
}

9
packages/server/tests/helpers.js

@ -0,0 +1,9 @@
module.exports.timeout = ms =>
new Promise(resolve => setTimeout(resolve, ms));
module.exports.sleep = async (ms, fn) => {
await timeout(ms);
return await fn(...args);
}

25
packages/server/tests/testApp.js

@ -1,16 +1,16 @@
const app = require("../app"); const app = require("../app");
const { promisify } = require("util"); const { rimraf, mkdir } = require("../utilities/fsawait");
const rimraf = promisify(require("rimraf"));
const createMasterDb = require("../initialise/createMasterDb"); const createMasterDb = require("../initialise/createMasterDb");
const request = require("supertest"); const request = require("supertest");
const fs = require("fs"); const fs = require("fs");
const { masterAppPackage } = require("../utilities/createAppPackage");
var enableDestroy = require('server-destroy'); var enableDestroy = require('server-destroy');
const mkdir = promisify(fs.mkdir);
const masterOwnerName = "test_master"; const masterOwnerName = "test_master";
const masterOwnerPassword = "test_master_pass"; const masterOwnerPassword = "test_master_pass";
const masterPlugins = { const extraMasterPlugins = {
main: { main: {
outputToFile : ({filename, content}) => { outputToFile : ({filename, content}) => {
fs.writeFile(`./tests/.data/${filename}`, content, {encoding:"utf8"}); fs.writeFile(`./tests/.data/${filename}`, content, {encoding:"utf8"});
@ -44,7 +44,8 @@ const config = {
}, },
keys: ["secret1", "secret2"], keys: ["secret1", "secret2"],
port: 4002, port: 4002,
masterPlugins, latestAppsPath: "./appPackages",
extraMasterPlugins,
customizeMaster customizeMaster
} }
@ -69,12 +70,19 @@ module.exports = () => {
get: (url) => getRequest(server, url), get: (url) => getRequest(server, url),
masterAuth: { masterAuth: {
username: masterOwnerName, username: masterOwnerName,
password: masterOwnerPassword password: masterOwnerPassword,
cookie: ""
},
testAppInfo: {
name: "testApp"
}, },
destroy: () => server.destroy() destroy: () => server.destroy(),
masterAppPackage: masterAppPackage(config)
}) })
}; };
const postRequest = (server, url, body) => const postRequest = (server, url, body) =>
request(server) request(server)
.post(url) .post(url)
@ -98,7 +106,8 @@ const reInitialize = async () => {
datastoreModule, datastoreModule,
config.datastoreConfig, config.datastoreConfig,
masterOwnerName, masterOwnerName,
masterOwnerPassword masterOwnerPassword ,
config
); );
} }

6
packages/server/utilities/constructHierarchy.js

@ -0,0 +1,6 @@
const {getTemplateApi} = require("budibase-core");
const templateApi = getTemplateApi({});
module.exports = (appDefinition) => {
appDefinition.hierarchy = templateApi.constructHierarchy(appDefinition.hierarchy);
return appDefinition;
}

29
packages/server/utilities/createAppPackage.js

@ -1,8 +1,9 @@
const { join } = require("path"); const { join } = require("path");
const constructHierarchy = require("./constructHierarchy");
const { common } = require("budibase-core");
const createAppPackage = (appPath) => ({ const createAppPackage = (appPath) => ({
appDefinition: require(join(appPath, "appDefinition.json")), appDefinition: require(join(appPath, "appDefinition.json")),
behaviourSources: require(join(appPath, "plugins.json")), behaviourSources: require(join(appPath, "plugins.js")),
appPath appPath
}); });
@ -13,19 +14,25 @@ module.exports.masterAppPackage = (config) => {
? config.customizeMaster ? config.customizeMaster
: a => a; : a => a;
const appDefinition = customizeMaster( const appDefinition = common.$(standardPackage.appDefinition, [
standardPackage.appDefinition); customizeMaster,
constructHierarchy
]);
const plugins = require("../appPackages/master/plugins.js")
(config);
return ({ return ({
appDefinition, appDefinition,
behaviourSources: config && config.masterPlugins behaviourSources: config && config.extraMasterPlugins
? config.masterPlugins ? {...plugins, ...config.extraMasterPlugins}
: standardPackage.behaviourSources, : plugins,
appPath: standardPackage.appPath appPath: standardPackage.appPath
}); });
} }
module.exports.applictionVersionPackage = (appname, versionId) => module.exports.applictionVersionPackage = (appname, versionId) => {
createAppPackage(`../runtimePackages/${appname}/${versionId}`); const pkg = createAppPackage(`../runtimePackages/${appname}/${versionId}`);
pkg.appDefinition = constructHierarchy(appDefinition);
return pkg;
}

19
packages/server/utilities/fsawait.js

@ -0,0 +1,19 @@
const util = require("util");
const fs = require("fs");
module.exports.readFile = util.promisify(fs.readFile);
module.exports.rimraf = util.promisify(require("rimraf"));
module.exports.mkdir = util.promisify(fs.mkdir);
module.exports.unlink = util.promisify(fs.unlink);
module.exports.stat = util.promisify(fs.stat);
module.exports.exists = async (path) => {
try {
await util.promisify(fs.access)(
path
);
} catch (e) {
return false;
}
return true;
};

8
packages/server/utilities/runtimePackages.js

@ -0,0 +1,8 @@
const { join } = require("path");
const runtimePackagesDirectory = "./runtime_apps";
module.exports.runtimePackagesDirectory = runtimePackagesDirectory;
module.exports.getRuntimePackageDirectory = (appName, versionId) =>
join(runtimePackagesDirectory, appName, versionId);

3
packages/server/utilities/statusCodes.js

@ -2,5 +2,6 @@ module.exports = {
OK:200, OK:200,
UNAUTHORIZED:401, UNAUTHORIZED:401,
FORBIDDEN:403, FORBIDDEN:403,
NOT_FOUND:404 NOT_FOUND:404,
INTERAL_ERROR:500
}; };

91
packages/server/utilities/targzAppPackage.js

@ -0,0 +1,91 @@
// Based on https://github.com/lafin/node-targz
// MIT license
const fs = require("fs");
const tar = require('tar-fs');
const zlib = require("zlib");
const { join, dirname, sep } = require("path");
const { exists, mkdir, unlink, stat } = require("../utilities/fsawait");
const { getRuntimePackageDirectory } = require("./runtimePackages");
module.exports.createTarGzPackage = async (config, appName) => {
const appPath = join(config.latestAppsPath, appName);
const distPath = join(appPath, "dist");
if(!await exists(distPath)) {
await mkdir(distPath);
}
const packagePath = `${distPath}/package.tar.gz`;
if(await exists(`${packagePath}`)) {
await unlink(packagePath);
}
await compress(appPath, packagePath);
const size = (await stat(packagePath)).size;
return {size, path:packagePath};
}
module.exports.unzipTarGzPackageToRuntime = async (src, appName, versionId) => {
const versionDir = getRuntimePackageDirectory(appName, versionId);
if(await exists(versionDir)) {
await rimraf(versionDir);
}
await mkdir(versionDir);
decompress(src, versionDir);
}
const compress = (src, dest) => new Promise((resolve, reject) => {
// ensure opts
opts = {src, dest};
opts.tar = {ignore: name => dirname(name).split(sep).pop() === "dist"};
opts.gz = opts.gz || {};
// default gzip config
opts.gz.level = opts.gz.level || 6;
opts.gz.memLevel = opts.gz.memLevel || 6;
// ensure src and dest
if(!opts.src) return reject("No source for compress!");
if(!opts.dest) return reject("No destination for compress!");
// go
process.nextTick(function () {
tar.pack(opts.src, opts.tar)
.on('error', reject)
.pipe(zlib.createGzip(opts.gz)
.on('error', reject))
.pipe(fs.createWriteStream(opts.dest)
.on('error', reject)
.on('finish', resolve));
});
});
const decompress = (src, dest) => new Promise((resolve, reject) => {
// ensure opts
opts = {src, dest};
opts.tar = opts.tar || {};
opts.gz = opts.gz || {};
// ensure src and dest
if(!opts.src) return reject("No source for decompress!");
if(!opts.dest) return reject("No destination for decompress!");
// go
process.nextTick(function () {
fs.createReadStream(opts.src)
.on('error', reject)
.pipe(zlib.createGunzip(opts.gz)
.on('error', reject))
.pipe(tar.extract(opts.dest, opts.tar)
.on('error', reject)
.on('finish', resolve));
});
});

156
packages/server/yarn.lock

@ -285,6 +285,18 @@
"@types/istanbul-reports" "^1.1.1" "@types/istanbul-reports" "^1.1.1"
"@types/yargs" "^12.0.9" "@types/yargs" "^12.0.9"
"@koa/router@^8.0.0":
version "8.0.0"
resolved "https://registry.yarnpkg.com/@koa/router/-/router-8.0.0.tgz#fd4ffa6f03d8293a04c023cb4a22b612401fbe70"
integrity sha512-P70CGOGs6JPu/mnrd9lt6ESzlBXLHT/uTK8+5U4M7Oapt8la/tiZv2c7X9jq0ksFsM59RH3AwJYzKOuavDcjIw==
dependencies:
debug "^3.1.0"
http-errors "^1.3.1"
koa-compose "^3.0.0"
methods "^1.0.1"
path-to-regexp "^1.1.1"
urijs "^1.19.0"
"@nx-js/compiler-util@^2.0.0": "@nx-js/compiler-util@^2.0.0":
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/@nx-js/compiler-util/-/compiler-util-2.0.0.tgz#c74c12165fa2f017a292bb79af007e8fce0af297" resolved "https://registry.yarnpkg.com/@nx-js/compiler-util/-/compiler-util-2.0.0.tgz#c74c12165fa2f017a292bb79af007e8fce0af297"
@ -330,6 +342,19 @@
dependencies: dependencies:
"@babel/types" "^7.3.0" "@babel/types" "^7.3.0"
"@types/events@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7"
integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==
"@types/formidable@^1.0.31":
version "1.0.31"
resolved "https://registry.yarnpkg.com/@types/formidable/-/formidable-1.0.31.tgz#274f9dc2d0a1a9ce1feef48c24ca0859e7ec947b"
integrity sha512-dIhM5t8lRP0oWe2HF8MuPvdd1TpPTjhDMAqemcq6oIZQCBQTovhBAdTQ5L5veJB4pdQChadmHuxtB0YzqvfU3Q==
dependencies:
"@types/events" "*"
"@types/node" "*"
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": "@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.1.tgz#42995b446db9a48a11a07ec083499a860e9138ff"
@ -350,6 +375,11 @@
"@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-coverage" "*"
"@types/istanbul-lib-report" "*" "@types/istanbul-lib-report" "*"
"@types/node@*":
version "12.0.10"
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.0.10.tgz#51babf9c7deadd5343620055fc8aff7995c8b031"
integrity sha512-LcsGbPomWsad6wmMNv7nBLw7YYYyfdYcz6xryKYQhx89c3XXan+8Q6AJ43G5XDIaklaVkK3mE4fCb0SBvMiPSQ==
"@types/stack-utils@^1.0.1": "@types/stack-utils@^1.0.1":
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
@ -612,6 +642,13 @@ bcrypt-pbkdf@^1.0.0:
dependencies: dependencies:
tweetnacl "^0.14.3" tweetnacl "^0.14.3"
bl@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bl/-/bl-3.0.0.tgz#3611ec00579fd18561754360b21e9f784500ff88"
integrity sha512-EUAyP5UHU5hxF8BPT0LKW8gjYLhq1DQIcneOX/pL/m2Alo+OYDQAJlHq+yseMP50Os2nHXOSic6Ss3vSQeyf4A==
dependencies:
readable-stream "^3.0.1"
brace-expansion@^1.1.7: brace-expansion@^1.1.7:
version "1.1.11" version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@ -776,15 +813,15 @@ cliui@^5.0.0:
strip-ansi "^5.2.0" strip-ansi "^5.2.0"
wrap-ansi "^5.1.0" wrap-ansi "^5.1.0"
co-body@^6.0.0: co-body@^5.1.1:
version "6.0.0" version "5.2.0"
resolved "https://registry.yarnpkg.com/co-body/-/co-body-6.0.0.tgz#965b9337d7f5655480787471f4237664820827e3" resolved "https://registry.yarnpkg.com/co-body/-/co-body-5.2.0.tgz#5a0a658c46029131e0e3a306f67647302f71c124"
integrity sha512-9ZIcixguuuKIptnY8yemEOuhb71L/lLf+Rl5JfJEUiDNJk0e02MBt7BPxR2GEh5mw8dPthQYR4jPI/BnS1MQgw== integrity sha512-sX/LQ7LqUhgyaxzbe7IqwPeTr2yfpfUIQ/dgpKo6ZI4y4lpQA0YxAomWIY+7I7rHWcG02PG+OuPREzMW/5tszQ==
dependencies: dependencies:
inflation "^2.0.0" inflation "^2.0.0"
qs "^6.5.2" qs "^6.4.0"
raw-body "^2.3.3" raw-body "^2.2.0"
type-is "^1.6.16" type-is "^1.6.14"
co@^4.6.0: co@^4.6.0:
version "4.6.0" version "4.6.0"
@ -880,11 +917,6 @@ copy-descriptor@^0.1.0:
resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d"
integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=
copy-to@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/copy-to/-/copy-to-2.0.1.tgz#2680fbb8068a48d08656b6098092bdafc906f4a5"
integrity sha1-JoD7uAaKSNCGVrYJgJK9r8kG9KU=
core-util-is@1.0.2, core-util-is@^1.0.2, core-util-is@~1.0.0: core-util-is@1.0.2, core-util-is@^1.0.2, core-util-is@~1.0.0:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
@ -1083,7 +1115,7 @@ emoji-regex@^7.0.1:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
end-of-stream@^1.1.0: end-of-stream@^1.1.0, end-of-stream@^1.4.1:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q== integrity sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==
@ -1310,7 +1342,7 @@ form-data@^2.3.1, form-data@~2.3.2:
combined-stream "^1.0.6" combined-stream "^1.0.6"
mime-types "^2.1.12" mime-types "^2.1.12"
formidable@^1.2.0: formidable@^1.1.1, formidable@^1.2.0:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.1.tgz#70fb7ca0290ee6ff961090415f4b3df3d2082659" resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.1.tgz#70fb7ca0290ee6ff961090415f4b3df3d2082659"
integrity sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg== integrity sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==
@ -1327,6 +1359,11 @@ fresh@~0.5.2:
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
fs-constants@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
fs-minipass@^1.2.5: fs-minipass@^1.2.5:
version "1.2.6" version "1.2.6"
resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.6.tgz#2c5cc30ded81282bfe8a0d7c7c1853ddeb102c07"
@ -1519,7 +1556,18 @@ http-assert@^1.3.0:
deep-equal "~1.0.1" deep-equal "~1.0.1"
http-errors "~1.7.2" http-errors "~1.7.2"
http-errors@1.7.2, http-errors@^1.3.1, http-errors@^1.6.3, http-errors@~1.7.2: http-errors@1.7.3, http-errors@^1.3.1:
version "1.7.3"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06"
integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw==
dependencies:
depd "~1.1.2"
inherits "2.0.4"
setprototypeof "1.1.1"
statuses ">= 1.5.0 < 2"
toidentifier "1.0.0"
http-errors@^1.6.3, http-errors@~1.7.2:
version "1.7.2" version "1.7.2"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f"
integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==
@ -1589,6 +1637,11 @@ inherits@2, inherits@2.0.3, inherits@~2.0.3:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
inherits@2.0.4, inherits@^2.0.3:
version "2.0.4"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
ini@~1.3.0: ini@~1.3.0:
version "1.3.5" version "1.3.5"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
@ -2322,13 +2375,14 @@ kleur@^3.0.2:
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
koa-bodyparser@^4.2.1: koa-body@^4.1.0:
version "4.2.1" version "4.1.0"
resolved "https://registry.yarnpkg.com/koa-bodyparser/-/koa-bodyparser-4.2.1.tgz#4d7dacb5e6db1106649b595d9e5ccb158b6f3b29" resolved "https://registry.yarnpkg.com/koa-body/-/koa-body-4.1.0.tgz#99295ee2e9543884e5730ae696780930b3821c44"
integrity sha512-UIjPAlMZfNYDDe+4zBaOAUKYqkwAGcIU6r2ARf1UOXPAlfennQys5IiShaVeNf7KkVBlf88f2LeLvBFvKylttw== integrity sha512-rWkMfMaCjFmIAMohtjlrg4BqDzcotK5BdZhiwJu1ONuR1ceoFUjnH3wp0hEV39HuBlc9tI3eUUFMK4Cp6ccFtA==
dependencies: dependencies:
co-body "^6.0.0" "@types/formidable" "^1.0.31"
copy-to "^2.0.1" co-body "^5.1.1"
formidable "^1.1.1"
koa-compose@^3.0.0: koa-compose@^3.0.0:
version "3.2.1" version "3.2.1"
@ -2355,18 +2409,6 @@ koa-is-json@^1.0.0:
resolved "https://registry.yarnpkg.com/koa-is-json/-/koa-is-json-1.0.0.tgz#273c07edcdcb8df6a2c1ab7d59ee76491451ec14" resolved "https://registry.yarnpkg.com/koa-is-json/-/koa-is-json-1.0.0.tgz#273c07edcdcb8df6a2c1ab7d59ee76491451ec14"
integrity sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ= integrity sha1-JzwH7c3Ljfaiwat9We52SRRR7BQ=
koa-router@^7.4.0:
version "7.4.0"
resolved "https://registry.yarnpkg.com/koa-router/-/koa-router-7.4.0.tgz#aee1f7adc02d5cb31d7d67465c9eacc825e8c5e0"
integrity sha512-IWhaDXeAnfDBEpWS6hkGdZ1ablgr6Q6pGdXCyK38RbzuH4LkUOpPqPw+3f8l8aTDrQmBQ7xJc0bs2yV4dzcO+g==
dependencies:
debug "^3.1.0"
http-errors "^1.3.1"
koa-compose "^3.0.0"
methods "^1.0.1"
path-to-regexp "^1.1.1"
urijs "^1.19.0"
koa-session@^5.12.0: koa-session@^5.12.0:
version "5.12.0" version "5.12.0"
resolved "https://registry.yarnpkg.com/koa-session/-/koa-session-5.12.0.tgz#1e6c6cea86b8ca2cca921c4a8881cfbfcc2628e0" resolved "https://registry.yarnpkg.com/koa-session/-/koa-session-5.12.0.tgz#1e6c6cea86b8ca2cca921c4a8881cfbfcc2628e0"
@ -3113,7 +3155,7 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
qs@^6.5.1, qs@^6.5.2: qs@^6.4.0, qs@^6.5.1:
version "6.7.0" version "6.7.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
@ -3123,13 +3165,13 @@ qs@~6.5.2:
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
raw-body@^2.3.3: raw-body@^2.2.0:
version "2.4.0" version "2.4.1"
resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.1.tgz#30ac82f98bb5ae8c152e67149dac8d55153b168c"
integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== integrity sha512-9WmIKF6mkvA0SLmA2Knm9+qj89e+j1zqgyn8aXGd7+nAduPoqgI9lO57SAZNn/Byzo5P7JhXTyg9PzaJbH73bA==
dependencies: dependencies:
bytes "3.1.0" bytes "3.1.0"
http-errors "1.7.2" http-errors "1.7.3"
iconv-lite "0.4.24" iconv-lite "0.4.24"
unpipe "1.0.0" unpipe "1.0.0"
@ -3178,6 +3220,15 @@ readable-stream@^2.0.1, readable-stream@^2.0.6, readable-stream@^2.3.5:
string_decoder "~1.1.1" string_decoder "~1.1.1"
util-deprecate "~1.0.1" util-deprecate "~1.0.1"
readable-stream@^3.0.1, readable-stream@^3.1.1:
version "3.4.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc"
integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ==
dependencies:
inherits "^2.0.3"
string_decoder "^1.1.1"
util-deprecate "^1.0.1"
realpath-native@^1.1.0: realpath-native@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c" resolved "https://registry.yarnpkg.com/realpath-native/-/realpath-native-1.1.0.tgz#2003294fea23fb0672f2476ebe22fcf498a2d65c"
@ -3601,7 +3652,7 @@ string-width@^3.0.0, string-width@^3.1.0:
is-fullwidth-code-point "^2.0.0" is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0" strip-ansi "^5.1.0"
string_decoder@^1.2.0: string_decoder@^1.1.1, string_decoder@^1.2.0:
version "1.2.0" version "1.2.0"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.2.0.tgz#fe86e738b19544afe70469243b2a1ee9240eae8d"
integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w== integrity sha512-6YqyX6ZWEYguAxgZzHGL7SsCeGx3V2TtOTqZz1xSTSWnqsbWwbptafNyvf/ACquZUXV3DANr5BDIwNYe1mN42w==
@ -3694,6 +3745,27 @@ symbol-tree@^3.2.2:
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
tar-fs@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.0.0.tgz#677700fc0c8b337a78bee3623fdc235f21d7afad"
integrity sha512-vaY0obB6Om/fso8a8vakQBzwholQ7v5+uy+tF3Ozvxv1KNezmVQAiWtcNmMHFSFPqL3dJA8ha6gdtFbfX9mcxA==
dependencies:
chownr "^1.1.1"
mkdirp "^0.5.1"
pump "^3.0.0"
tar-stream "^2.0.0"
tar-stream@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.0.tgz#d1aaa3661f05b38b5acc9b7020efdca5179a2cc3"
integrity sha512-+DAn4Nb4+gz6WZigRzKEZl1QuJVOLtAwwF+WUxy1fJ6X63CaGaUAxJRD2KEn1OMfcbCjySTYpNC6WmfQoIEOdw==
dependencies:
bl "^3.0.0"
end-of-stream "^1.4.1"
fs-constants "^1.0.0"
inherits "^2.0.3"
readable-stream "^3.1.1"
tar@^4: tar@^4:
version "4.4.10" version "4.4.10"
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.10.tgz#946b2810b9a5e0b26140cf78bea6b0b0d689eba1"
@ -3809,7 +3881,7 @@ type-check@~0.3.2:
dependencies: dependencies:
prelude-ls "~1.1.2" prelude-ls "~1.1.2"
type-is@^1.6.16: type-is@^1.6.14, type-is@^1.6.16:
version "1.6.18" version "1.6.18"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131"
integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==
@ -3870,7 +3942,7 @@ use@^3.1.0:
resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f"
integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==
util-deprecate@~1.0.1: util-deprecate@^1.0.1, util-deprecate@~1.0.1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=

Loading…
Cancel
Save