From 301f681c882567219a1b115aed2a23a74a947dfb Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Tue, 20 Apr 2021 18:14:36 +0100 Subject: [PATCH 01/29] config creation and management APIs --- packages/auth/src/db/utils.js | 26 +++++++- packages/auth/src/index.js | 4 ++ .../auth/src/middleware/passport/google.js | 14 +++-- .../src/api/controllers/admin/configs.js | 60 +++++++++++++++++++ .../worker/src/api/routes/admin/configs.js | 28 +++++++++ packages/worker/src/api/routes/index.js | 3 +- packages/worker/src/constants/index.js | 6 ++ 7 files changed, 135 insertions(+), 6 deletions(-) create mode 100644 packages/worker/src/api/controllers/admin/configs.js create mode 100644 packages/worker/src/api/routes/admin/configs.js diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index 89aedb60bf..32034bd731 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -10,6 +10,7 @@ const DocumentTypes = { USER: "us", APP: "app", GROUP: "group", + CONFIG: "config", } exports.DocumentTypes = DocumentTypes @@ -52,7 +53,7 @@ exports.getGroupParams = (id = "", otherProps = {}) => { } /** - * Gets parameters for retrieving users. + * Gets parameters for retrieving users, this is a utility function for the getDocParams function. */ exports.getUserParams = (email = "", otherProps = {}) => { if (!email) { @@ -64,3 +65,26 @@ exports.getUserParams = (email = "", otherProps = {}) => { endkey: `${DocumentTypes.USER}${SEPARATOR}${email}${UNICODE_MAX}`, } } + +/** + * Generates a new configuration ID. + * @returns {string} The new configuration ID which the config doc can be stored under. + */ +exports.generateConfigID = (type = "", group = "") => { + group += SEPARATOR + + return `${ + DocumentTypes.CONFIG + }${SEPARATOR}${type}${SEPARATOR}${group}${newid()}` +} + +/** + * Gets parameters for retrieving configurations. + */ +exports.getConfigParams = (type = "", group = "", otherProps = {}) => { + return { + ...otherProps, + startkey: `${DocumentTypes.CONFIG}${SEPARATOR}${type}${SEPARATOR}${group}`, + endkey: `${DocumentTypes.CONFIG}${SEPARATOR}${type}${SEPARATOR}${group}${UNICODE_MAX}`, + } +} diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index 455181d538..4c6ece1b62 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -20,6 +20,8 @@ const { generateGroupID, getGroupParams, getEmailFromUserID, + generateConfigID, + getConfigParams, } = require("./db/utils") // Strategies @@ -54,6 +56,8 @@ module.exports = { generateGroupID, getGroupParams, getEmailFromUserID, + generateConfigID, + getConfigParams, hash, compare, getAppId, diff --git a/packages/auth/src/middleware/passport/google.js b/packages/auth/src/middleware/passport/google.js index 05b435aedd..6246e5e768 100644 --- a/packages/auth/src/middleware/passport/google.js +++ b/packages/auth/src/middleware/passport/google.js @@ -6,7 +6,13 @@ exports.options = { callbackURL: env.GOOGLE_AUTH_CALLBACK_URL, } -// exports.authenticate = async function(token, tokenSecret, profile, done) { -// // retrieve user ... -// fetchUser().then(user => done(null, user)) -// } +exports.authenticate = async function(token, tokenSecret, profile, done) { + console.log({ + token, + tokenSecret, + profile, + done, + }) + // retrieve user ... + // fetchUser().then(user => done(null, user)) +} diff --git a/packages/worker/src/api/controllers/admin/configs.js b/packages/worker/src/api/controllers/admin/configs.js new file mode 100644 index 0000000000..e9fc8a3942 --- /dev/null +++ b/packages/worker/src/api/controllers/admin/configs.js @@ -0,0 +1,60 @@ +const CouchDB = require("../../../db") +const { StaticDatabases } = require("@budibase/auth") +const { generateConfigID } = require("@budibase/auth") +const { getConfigParams } = require("@budibase/auth/src/db/utils") + +const GLOBAL_DB = StaticDatabases.GLOBAL.name + +exports.save = async function(ctx) { + const db = new CouchDB(GLOBAL_DB) + const configDoc = ctx.request.body + + // Config does not exist yet + if (!configDoc._id) { + configDoc._id = generateConfigID(configDoc.type, configDoc.group) + } + + try { + const response = await db.post(configDoc) + ctx.body = { + type: configDoc.type, + _id: response.id, + _rev: response.rev, + } + } catch (err) { + ctx.throw(err.status, err) + } +} + +exports.fetch = async function(ctx) { + const db = new CouchDB(GLOBAL_DB) + const response = await db.allDocs( + getConfigParams(undefined, { + include_docs: true, + }) + ) + const groups = response.rows.map(row => row.doc) + ctx.body = groups +} + +exports.find = async function(ctx) { + const db = new CouchDB(GLOBAL_DB) + try { + const record = await db.get(ctx.params.id) + ctx.body = record + } catch (err) { + ctx.throw(err.status, err) + } +} + +exports.destroy = async function(ctx) { + const db = new CouchDB(GLOBAL_DB) + const { id, rev } = ctx.params + + try { + await db.remove(id, rev) + ctx.body = { message: "Config deleted successfully" } + } catch (err) { + ctx.throw(err.status, err) + } +} diff --git a/packages/worker/src/api/routes/admin/configs.js b/packages/worker/src/api/routes/admin/configs.js new file mode 100644 index 0000000000..5b7354bfc3 --- /dev/null +++ b/packages/worker/src/api/routes/admin/configs.js @@ -0,0 +1,28 @@ +const Router = require("@koa/router") +const controller = require("../../controllers/admin/configs") +const joiValidator = require("../../../middleware/joi-validator") +const { authenticated } = require("@budibase/auth") +const Joi = require("joi") +const { Configs } = require("../../../constants") + +const router = Router() + +function buildConfigSaveValidation() { + // prettier-ignore + return joiValidator.body(Joi.object({ + type: Joi.string().valid(...Object.values(Configs)).required() + }).required().unknown(true)) +} + +router + .post( + "/api/admin/configs", + buildConfigSaveValidation(), + authenticated, + controller.save + ) + .delete("/api/admin/configs/:id", authenticated, controller.destroy) + .get("/api/admin/configs", authenticated, controller.fetch) + .get("/api/admin/configs/:id", authenticated, controller.find) + +module.exports = router diff --git a/packages/worker/src/api/routes/index.js b/packages/worker/src/api/routes/index.js index 5c6b088443..aa1c6874e3 100644 --- a/packages/worker/src/api/routes/index.js +++ b/packages/worker/src/api/routes/index.js @@ -1,6 +1,7 @@ const userRoutes = require("./admin/users") +const configRoutes = require("./admin/configs") const groupRoutes = require("./admin/groups") const authRoutes = require("./auth") const appRoutes = require("./app") -exports.routes = [userRoutes, groupRoutes, authRoutes, appRoutes] +exports.routes = [configRoutes, userRoutes, groupRoutes, authRoutes, appRoutes] diff --git a/packages/worker/src/constants/index.js b/packages/worker/src/constants/index.js index 586d69c86f..76245a3d7d 100644 --- a/packages/worker/src/constants/index.js +++ b/packages/worker/src/constants/index.js @@ -6,3 +6,9 @@ exports.UserStatus = { exports.Groups = { ALL_USERS: "all_users", } + +exports.Configs = { + SETTINGS: "settings", + ACCOUNT: "account", + SMTP: "smtp", +} From ffe167bbd330237d01294959745497f463751d59 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Wed, 21 Apr 2021 12:12:22 +0100 Subject: [PATCH 02/29] google auth E2E --- packages/auth/src/db/utils.js | 9 ++- packages/auth/src/index.js | 9 +-- .../auth/src/middleware/passport/google.js | 52 ++++++++++++--- .../src/components/login/LoginForm.svelte | 1 + .../src/api/controllers/admin/configs.js | 38 +++++++++-- packages/worker/src/api/controllers/auth.js | 66 +++++++++++++++++-- .../worker/src/api/routes/admin/configs.js | 3 +- packages/worker/src/api/routes/auth.js | 12 ++-- 8 files changed, 155 insertions(+), 35 deletions(-) diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index 32034bd731..90b44c43b7 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -70,12 +70,11 @@ exports.getUserParams = (email = "", otherProps = {}) => { * Generates a new configuration ID. * @returns {string} The new configuration ID which the config doc can be stored under. */ -exports.generateConfigID = (type = "", group = "") => { - group += SEPARATOR +exports.generateConfigID = (type = "", group = "", user = "") => { + // group += SEPARATOR + const scope = [type, group, user].join(SEPARATOR) - return `${ - DocumentTypes.CONFIG - }${SEPARATOR}${type}${SEPARATOR}${group}${newid()}` + return `${DocumentTypes.CONFIG}${SEPARATOR}${scope}${newid()}` } /** diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index 4c6ece1b62..4ef30c9f02 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -1,10 +1,10 @@ const passport = require("koa-passport") const LocalStrategy = require("passport-local").Strategy const JwtStrategy = require("passport-jwt").Strategy -// const GoogleStrategy = require("passport-google-oauth").Strategy +const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy const database = require("./db") -const { StaticDatabases } = require("./db/utils") -const { jwt, local, authenticated } = require("./middleware") +const { StaticDatabases, DocumentTypes } = require("./db/utils") +const { jwt, local, google, authenticated } = require("./middleware") const { Cookies, UserStatus } = require("./constants") const { hash, compare } = require("./hashing") const { @@ -27,7 +27,7 @@ const { // Strategies passport.use(new LocalStrategy(local.options, local.authenticate)) passport.use(new JwtStrategy(jwt.options, jwt.authenticate)) -// passport.use(new GoogleStrategy(google.options, google.authenticate)) +passport.use(new GoogleStrategy(google.options, google.authenticate)) passport.serializeUser((user, done) => done(null, user)) @@ -50,6 +50,7 @@ module.exports = { passport, Cookies, UserStatus, + DocumentTypes, StaticDatabases, generateUserID, getUserParams, diff --git a/packages/auth/src/middleware/passport/google.js b/packages/auth/src/middleware/passport/google.js index 6246e5e768..9113fba1cf 100644 --- a/packages/auth/src/middleware/passport/google.js +++ b/packages/auth/src/middleware/passport/google.js @@ -1,18 +1,54 @@ const env = require("../../environment") +const jwt = require("jsonwebtoken") +const database = require("../../db") +const { StaticDatabases, generateUserID } = require("../../db/utils") exports.options = { - clientId: env.GOOGLE_CLIENT_ID, + clientID: env.GOOGLE_CLIENT_ID, clientSecret: env.GOOGLE_CLIENT_SECRET, callbackURL: env.GOOGLE_AUTH_CALLBACK_URL, } exports.authenticate = async function(token, tokenSecret, profile, done) { - console.log({ - token, - tokenSecret, - profile, - done, + if (!profile._json.email) return done(null, false, "Email Required.") + + // Check the user exists in the instance DB by email + const db = new database.CouchDB(StaticDatabases.GLOBAL.name) + + let dbUser + const userId = generateUserID(profile._json.email) + + try { + // use the google profile id + dbUser = await db.get(userId) + } catch (err) { + console.error("Google user not found. Creating..") + // create the user + const user = { + _id: userId, + provider: profile.provider, + roles: {}, + builder: { + global: true, + }, + ...profile._json, + } + const response = await db.post(user) + + dbUser = user + dbUser._rev = response.rev + } + + // authenticate + const payload = { + userId: dbUser._id, + builder: dbUser.builder, + email: dbUser.email, + } + + dbUser.token = jwt.sign(payload, env.JWT_SECRET, { + expiresIn: "1 day", }) - // retrieve user ... - // fetchUser().then(user => done(null, user)) + + return done(null, dbUser) } diff --git a/packages/builder/src/components/login/LoginForm.svelte b/packages/builder/src/components/login/LoginForm.svelte index 7e32efb7c5..55d1ee3bf5 100644 --- a/packages/builder/src/components/login/LoginForm.svelte +++ b/packages/builder/src/components/login/LoginForm.svelte @@ -46,6 +46,7 @@ + Sign In with Google diff --git a/packages/worker/src/api/controllers/admin/configs.js b/packages/worker/src/api/controllers/admin/configs.js index e9fc8a3942..10f1d2cf2b 100644 --- a/packages/worker/src/api/controllers/admin/configs.js +++ b/packages/worker/src/api/controllers/admin/configs.js @@ -1,17 +1,47 @@ const CouchDB = require("../../../db") -const { StaticDatabases } = require("@budibase/auth") -const { generateConfigID } = require("@budibase/auth") -const { getConfigParams } = require("@budibase/auth/src/db/utils") +const { StaticDatabases, DocumentTypes } = require("@budibase/auth") +const { generateConfigID, getConfigParams } = require("@budibase/auth") +const { SEPARATOR } = require("@budibase/auth/src/db/utils") +const { Configs } = require("../../../constants") const GLOBAL_DB = StaticDatabases.GLOBAL.name +exports.configStatus = async function(ctx) { + const db = new CouchDB(GLOBAL_DB) + let configured = {} + + // check for super admin user + try { + configured.user = true + } catch (err) { + configured.user = false + } + + // check for SMTP config + try { + const response = await db.allDocs( + getConfigParams(`${DocumentTypes.CONFIG}${SEPARATOR}${Configs.SMTP}`) + ) + console.log(response) + configured.smtp = true + } catch (err) { + configured.smtp = false + } + + ctx.body = configured +} + exports.save = async function(ctx) { const db = new CouchDB(GLOBAL_DB) const configDoc = ctx.request.body // Config does not exist yet if (!configDoc._id) { - configDoc._id = generateConfigID(configDoc.type, configDoc.group) + configDoc._id = generateConfigID( + configDoc.type, + configDoc.group, + configDoc.user + ) } try { diff --git a/packages/worker/src/api/controllers/auth.js b/packages/worker/src/api/controllers/auth.js index 03589ab457..d2aaf552e0 100644 --- a/packages/worker/src/api/controllers/auth.js +++ b/packages/worker/src/api/controllers/auth.js @@ -1,4 +1,38 @@ -const { passport, Cookies, clearCookie } = require("@budibase/auth") +const { + passport, + Cookies, + StaticDatabases, + clearCookie, +} = require("@budibase/auth") +const CouchDB = require("../../db") + +const GLOBAL_DB = StaticDatabases.GLOBAL.name + +async function setToken(ctx) { + return async function(err, user) { + if (err) { + return ctx.throw(403, "Unauthorized") + } + + const expires = new Date() + expires.setDate(expires.getDate() + 1) + + if (!user) { + return ctx.throw(403, "Unauthorized") + } + + ctx.cookies.set(Cookies.Auth, user.token, { + expires, + path: "/", + httpOnly: false, + overwrite: true, + }) + + delete user.token + + ctx.body = { user } + } +} exports.authenticate = async (ctx, next) => { return passport.authenticate("local", async (err, user) => { @@ -31,10 +65,30 @@ exports.logout = async ctx => { ctx.body = { message: "User logged out" } } -exports.googleAuth = async () => { - // return passport.authenticate("google") -} +exports.googleAuth = async (ctx, next) => { + return passport.authenticate( + "google", + { successRedirect: "/", failureRedirect: "/" }, + async (err, user) => { + if (err) { + return ctx.throw(403, "Unauthorized") + } -exports.googleAuth = async () => { - // return passport.authenticate("google") + const expires = new Date() + expires.setDate(expires.getDate() + 1) + + if (!user) { + return ctx.throw(403, "Unauthorized") + } + + ctx.cookies.set(Cookies.Auth, user.token, { + expires, + path: "/", + httpOnly: false, + overwrite: true, + }) + + ctx.redirect("/") + } + )(ctx, next) } diff --git a/packages/worker/src/api/routes/admin/configs.js b/packages/worker/src/api/routes/admin/configs.js index 5b7354bfc3..0399026cf2 100644 --- a/packages/worker/src/api/routes/admin/configs.js +++ b/packages/worker/src/api/routes/admin/configs.js @@ -10,7 +10,7 @@ const router = Router() function buildConfigSaveValidation() { // prettier-ignore return joiValidator.body(Joi.object({ - type: Joi.string().valid(...Object.values(Configs)).required() + type: Joi.string().valid(...Object.values(Configs)).required(), }).required().unknown(true)) } @@ -21,6 +21,7 @@ router authenticated, controller.save ) + .post("/api/admin/config/status", controller.configStatus) .delete("/api/admin/configs/:id", authenticated, controller.destroy) .get("/api/admin/configs", authenticated, controller.fetch) .get("/api/admin/configs/:id", authenticated, controller.find) diff --git a/packages/worker/src/api/routes/auth.js b/packages/worker/src/api/routes/auth.js index deea678c63..ac87ef977a 100644 --- a/packages/worker/src/api/routes/auth.js +++ b/packages/worker/src/api/routes/auth.js @@ -1,19 +1,17 @@ const Router = require("@koa/router") const { passport } = require("@budibase/auth") const authController = require("../controllers/auth") +const context = require("koa/lib/context") const router = Router() router .post("/api/admin/auth", authController.authenticate) - .post("/api/admin/auth/logout", authController.logout) - .get("/api/auth/google", passport.authenticate("google")) .get( - "/api/auth/google/callback", - passport.authenticate("google", { - successRedirect: "/app", - failureRedirect: "/", - }) + "/api/admin/auth/google", + passport.authenticate("google", { scope: ["profile", "email"] }) ) + .get("/api/admin/auth/google/callback", authController.googleAuth) + .post("/api/admin/auth/logout", authController.logout) module.exports = router From 76ceb6a9515f52ae202c399b7346ce1274ae2528 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 21 Apr 2021 16:42:44 +0100 Subject: [PATCH 03/29] Some re-work of the auth package, making it a bit easier to use/less likely to make a mistake. --- packages/auth/src/db/utils.js | 27 ++++++++- packages/auth/src/index.js | 44 ++++---------- packages/auth/src/middleware/authenticated.js | 29 +++++---- packages/server/src/api/index.js | 16 +++-- packages/server/src/api/routes/index.js | 2 +- packages/server/src/constants/index.js | 2 +- packages/server/src/middleware/currentapp.js | 3 +- .../src/middleware/tests/currentapp.spec.js | 60 ++++++++++++------- .../src/tests/utilities/TestConfiguration.js | 2 +- .../src/api/controllers/admin/groups.js | 3 +- .../worker/src/api/controllers/admin/index.js | 7 --- .../src/api/controllers/admin/templates.js | 18 ++++++ .../worker/src/api/controllers/admin/users.js | 5 +- packages/worker/src/api/controllers/auth.js | 5 +- packages/worker/src/api/index.js | 4 ++ .../worker/src/api/routes/admin/groups.js | 8 +-- .../worker/src/api/routes/admin/templates.js | 20 +++++++ packages/worker/src/api/routes/admin/users.js | 8 +-- packages/worker/src/api/routes/app.js | 3 +- packages/worker/src/api/routes/auth.js | 2 +- packages/worker/src/index.js | 2 +- 21 files changed, 164 insertions(+), 106 deletions(-) delete mode 100644 packages/worker/src/api/controllers/admin/index.js create mode 100644 packages/worker/src/api/controllers/admin/templates.js create mode 100644 packages/worker/src/api/routes/admin/templates.js diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index 2e2c3f1aed..4bd1f399cd 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -14,6 +14,7 @@ const DocumentTypes = { USER: "us", APP: "app", GROUP: "group", + TEMPLATE: "template", } exports.DocumentTypes = DocumentTypes @@ -53,7 +54,7 @@ exports.generateGlobalUserID = () => { /** * Gets parameters for retrieving users. */ -exports.getGlobalUserParams = (globalId = "", otherProps = {}) => { +exports.getGlobalUserParams = (globalId, otherProps = {}) => { if (!globalId) { globalId = "" } @@ -63,3 +64,27 @@ exports.getGlobalUserParams = (globalId = "", otherProps = {}) => { endkey: `${DocumentTypes.USER}${SEPARATOR}${globalId}${UNICODE_MAX}`, } } + +/** + * Generates a template ID. + * @param ownerId The owner/user of the template, this could be global or a group level. + */ +exports.generateTemplateID = ownerId => { + return `${DocumentTypes.TEMPLATE}${SEPARATOR}${ownerId}${newid()}` +} + +/** + * Gets parameters for retrieving templates. Owner ID must be specified, either global or a group level. + */ +exports.getTemplateParams = (ownerId, templateId, otherProps = {}) => { + if (!templateId) { + templateId = "" + } + const base = `${DocumentTypes.TEMPLATE}${SEPARATOR}${ownerId}` + const final = templateId ? `${base}${SEPARATOR}${templateId}` : base + return { + ...otherProps, + startkey: final, + endkey: `${final}${UNICODE_MAX}`, + } +} diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index fee83b65d8..937b1491c5 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -5,23 +5,6 @@ const JwtStrategy = require("passport-jwt").Strategy const { setDB, getDB } = require("./db") const { StaticDatabases } = require("./db/utils") const { jwt, local, authenticated } = require("./middleware") -const { Cookies, UserStatus } = require("./constants") -const { hash, compare } = require("./hashing") -const { - getAppId, - setCookie, - getCookie, - clearCookie, - isClient, - getGlobalUserByEmail, -} = require("./utils") -const { - generateGlobalUserID, - getGlobalUserParams, - generateGroupID, - getGroupParams, -} = require("./db/utils") - // Strategies passport.use(new LocalStrategy(local.options, local.authenticate)) passport.use(new JwtStrategy(jwt.options, jwt.authenticate)) @@ -45,21 +28,14 @@ module.exports = { init(pouch) { setDB(pouch) }, - passport, - Cookies, - UserStatus, - StaticDatabases, - generateGlobalUserID, - getGlobalUserParams, - generateGroupID, - getGroupParams, - hash, - compare, - getAppId, - setCookie, - getCookie, - clearCookie, - authenticated, - isClient, - getGlobalUserByEmail, + db: require("./db/utils"), + utils: { + ...require("./utils"), + ...require("./hashing") + }, + auth: { + buildAuthMiddleware: authenticated, + passport, + }, + constants: require("./constants"), } diff --git a/packages/auth/src/middleware/authenticated.js b/packages/auth/src/middleware/authenticated.js index 8f69a49e17..fc3a5b177e 100644 --- a/packages/auth/src/middleware/authenticated.js +++ b/packages/auth/src/middleware/authenticated.js @@ -1,18 +1,25 @@ const { Cookies } = require("../constants") const { getCookie } = require("../utils") -module.exports = async (ctx, next) => { - try { - // check the actual user is authenticated first - const authCookie = getCookie(ctx, Cookies.Auth) - - if (authCookie) { - ctx.isAuthenticated = true - ctx.user = authCookie +module.exports = (noAuthPatterns = []) => { + const regex = new RegExp(noAuthPatterns.join("|")) + return async (ctx, next) => { + // the path is not authenticated + if (regex.test(ctx.request.url)) { + return next() } + try { + // check the actual user is authenticated first + const authCookie = getCookie(ctx, Cookies.Auth) - await next() - } catch (err) { - ctx.throw(err.status || 403, err) + if (authCookie) { + ctx.isAuthenticated = true + ctx.user = authCookie + } + + return next() + } catch (err) { + ctx.throw(err.status || 403, err) + } } } diff --git a/packages/server/src/api/index.js b/packages/server/src/api/index.js index 201a9f1c33..369578d05e 100644 --- a/packages/server/src/api/index.js +++ b/packages/server/src/api/index.js @@ -1,14 +1,21 @@ const Router = require("@koa/router") -const { authenticated } = require("@budibase/auth") +const { buildAuthMiddleware } = require("@budibase/auth").auth const currentApp = require("../middleware/currentapp") const compress = require("koa-compress") const zlib = require("zlib") -const { mainRoutes, authRoutes, staticRoutes } = require("./routes") +const { mainRoutes, staticRoutes } = require("./routes") const pkg = require("../../package.json") const router = new Router() const env = require("../environment") +const NO_AUTH_ENDPOINTS = [ + "/health", + "/version", + "webhooks/trigger", + "webhooks/schema", +] + router .use( compress({ @@ -31,7 +38,7 @@ router }) .use("/health", ctx => (ctx.status = 200)) .use("/version", ctx => (ctx.body = pkg.version)) - .use(authenticated) + .use(buildAuthMiddleware(NO_AUTH_ENDPOINTS)) .use(currentApp) // error handling middleware @@ -53,9 +60,6 @@ router.use(async (ctx, next) => { router.get("/health", ctx => (ctx.status = 200)) -router.use(authRoutes.routes()) -router.use(authRoutes.allowedMethods()) - // authenticated routes for (let route of mainRoutes) { router.use(route.routes()) diff --git a/packages/server/src/api/routes/index.js b/packages/server/src/api/routes/index.js index 19de709ca9..0b09a78bb8 100644 --- a/packages/server/src/api/routes/index.js +++ b/packages/server/src/api/routes/index.js @@ -25,6 +25,7 @@ const backupRoutes = require("./backup") const devRoutes = require("./dev") exports.mainRoutes = [ + authRoutes, deployRoutes, layoutRoutes, screenRoutes, @@ -52,5 +53,4 @@ exports.mainRoutes = [ rowRoutes, ] -exports.authRoutes = authRoutes exports.staticRoutes = staticRoutes diff --git a/packages/server/src/constants/index.js b/packages/server/src/constants/index.js index 5b4291998e..9853676aa6 100644 --- a/packages/server/src/constants/index.js +++ b/packages/server/src/constants/index.js @@ -1,5 +1,5 @@ const { BUILTIN_ROLE_IDS } = require("../utilities/security/roles") -const { UserStatus } = require("@budibase/auth") +const { UserStatus } = require("@budibase/auth").constants exports.LOGO_URL = "https://d33wubrfki0l68.cloudfront.net/aac32159d7207b5085e74a7ef67afbb7027786c5/2b1fd/img/logo/bb-emblem.svg" diff --git a/packages/server/src/middleware/currentapp.js b/packages/server/src/middleware/currentapp.js index 0d75e808ad..f429c74267 100644 --- a/packages/server/src/middleware/currentapp.js +++ b/packages/server/src/middleware/currentapp.js @@ -1,4 +1,5 @@ -const { getAppId, setCookie, getCookie, Cookies } = require("@budibase/auth") +const { getAppId, setCookie, getCookie } = require("@budibase/auth").utils +const { Cookies } = require("@budibase/auth").constants const { getRole } = require("../utilities/security/roles") const { getGlobalUsers } = require("../utilities/workerRequests") const { BUILTIN_ROLE_IDS } = require("../utilities/security/roles") diff --git a/packages/server/src/middleware/tests/currentapp.spec.js b/packages/server/src/middleware/tests/currentapp.spec.js index 3ed17bb521..61d5bf018d 100644 --- a/packages/server/src/middleware/tests/currentapp.spec.js +++ b/packages/server/src/middleware/tests/currentapp.spec.js @@ -23,10 +23,14 @@ function mockAuthWithNoCookie() { jest.resetModules() mockWorker() jest.mock("@budibase/auth", () => ({ - getAppId: jest.fn(), - setCookie: jest.fn(), - getCookie: jest.fn(), - Cookies: {}, + utils: { + getAppId: jest.fn(), + setCookie: jest.fn(), + getCookie: jest.fn(), + }, + constants: { + Cookies: {}, + }, })) } @@ -34,15 +38,19 @@ function mockAuthWithCookie() { jest.resetModules() mockWorker() jest.mock("@budibase/auth", () => ({ - getAppId: () => { - return "app_test" + utils: { + getAppId: () => { + return "app_test" + }, + setCookie: jest.fn(), + getCookie: () => ({appId: "app_different", roleId: "PUBLIC"}), + }, + constants: { + Cookies: { + Auth: "auth", + CurrentApp: "currentapp", + }, }, - setCookie: jest.fn(), - getCookie: () => ({ appId: "app_different", roleId: "PUBLIC" }), - Cookies: { - Auth: "auth", - CurrentApp: "currentapp", - } })) } @@ -102,7 +110,7 @@ describe("Current app middleware", () => { async function checkExpected(setCookie) { config.setUser() await config.executeMiddleware() - const cookieFn = require("@budibase/auth").setCookie + const cookieFn = require("@budibase/auth").utils.setCookie if (setCookie) { expect(cookieFn).toHaveBeenCalled() } else { @@ -122,12 +130,16 @@ describe("Current app middleware", () => { it("should perform correct when no cookie exists", async () => { mockReset() jest.mock("@budibase/auth", () => ({ - getAppId: () => { - return "app_test" + utils: { + getAppId: () => { + return "app_test" + }, + setCookie: jest.fn(), + getCookie: jest.fn(), + }, + constants: { + Cookies: {}, }, - setCookie: jest.fn(), - getCookie: jest.fn(), - Cookies: {}, })) await checkExpected(true) }) @@ -135,12 +147,14 @@ describe("Current app middleware", () => { it("lastly check what occurs when cookie doesn't need updated", async () => { mockReset() jest.mock("@budibase/auth", () => ({ - getAppId: () => { - return "app_test" + utils: { + getAppId: () => { + return "app_test" + }, + setCookie: jest.fn(), + getCookie: () => ({appId: "app_test", roleId: "BASIC"}), }, - setCookie: jest.fn(), - getCookie: () => ({ appId: "app_test", roleId: "BASIC" }), - Cookies: {}, + constants: { Cookies: {} }, })) await checkExpected(false) }) diff --git a/packages/server/src/tests/utilities/TestConfiguration.js b/packages/server/src/tests/utilities/TestConfiguration.js index 0f036647bf..630ea4256e 100644 --- a/packages/server/src/tests/utilities/TestConfiguration.js +++ b/packages/server/src/tests/utilities/TestConfiguration.js @@ -15,7 +15,7 @@ const { const controllers = require("./controllers") const supertest = require("supertest") const { cleanup } = require("../../utilities/fileSystem") -const { Cookies } = require("@budibase/auth") +const { Cookies } = require("@budibase/auth").constants const EMAIL = "babs@babs.com" const PASSWORD = "babs_password" diff --git a/packages/worker/src/api/controllers/admin/groups.js b/packages/worker/src/api/controllers/admin/groups.js index 86623c337a..0943a58b1f 100644 --- a/packages/worker/src/api/controllers/admin/groups.js +++ b/packages/worker/src/api/controllers/admin/groups.js @@ -1,6 +1,5 @@ const CouchDB = require("../../../db") -const { getGroupParams, StaticDatabases } = require("@budibase/auth") -const { generateGroupID } = require("@budibase/auth") +const { getGroupParams, generateGroupID, StaticDatabases } = require("@budibase/auth").db const GLOBAL_DB = StaticDatabases.GLOBAL.name diff --git a/packages/worker/src/api/controllers/admin/index.js b/packages/worker/src/api/controllers/admin/index.js deleted file mode 100644 index 60ca3b2900..0000000000 --- a/packages/worker/src/api/controllers/admin/index.js +++ /dev/null @@ -1,7 +0,0 @@ -const users = require("./users") -const groups = require("./groups") - -module.exports = { - users, - groups, -} diff --git a/packages/worker/src/api/controllers/admin/templates.js b/packages/worker/src/api/controllers/admin/templates.js new file mode 100644 index 0000000000..5a2e018702 --- /dev/null +++ b/packages/worker/src/api/controllers/admin/templates.js @@ -0,0 +1,18 @@ +const { generateTemplateID, getTemplateParams } = require("@budibase/auth").db +const { CouchDB } = require("../../../db") + +exports.save = async ctx => { + +} + +exports.fetch = async ctx => { + +} + +exports.find = async ctx => { + +} + +exports.destroy = async ctx => { + +} diff --git a/packages/worker/src/api/controllers/admin/users.js b/packages/worker/src/api/controllers/admin/users.js index 96243d49fd..95dd474e9a 100644 --- a/packages/worker/src/api/controllers/admin/users.js +++ b/packages/worker/src/api/controllers/admin/users.js @@ -1,11 +1,10 @@ const CouchDB = require("../../../db") const { - hash, generateGlobalUserID, getGlobalUserParams, StaticDatabases, - getGlobalUserByEmail, -} = require("@budibase/auth") +} = require("@budibase/auth").db +const { hash, getGlobalUserByEmail } = require("@budibase/auth").utils const { UserStatus } = require("../../../constants") const FIRST_USER_EMAIL = "test@test.com" diff --git a/packages/worker/src/api/controllers/auth.js b/packages/worker/src/api/controllers/auth.js index 03589ab457..96ab8e73f0 100644 --- a/packages/worker/src/api/controllers/auth.js +++ b/packages/worker/src/api/controllers/auth.js @@ -1,4 +1,7 @@ -const { passport, Cookies, clearCookie } = require("@budibase/auth") +const authPkg = require("@budibase/auth") +const { clearCookie } = authPkg.utils +const { Cookies } = authPkg.constants +const { passport } = authPkg.auth exports.authenticate = async (ctx, next) => { return passport.authenticate("local", async (err, user) => { diff --git a/packages/worker/src/api/index.js b/packages/worker/src/api/index.js index 0568d79a68..bc3c74aac9 100644 --- a/packages/worker/src/api/index.js +++ b/packages/worker/src/api/index.js @@ -2,6 +2,9 @@ const Router = require("@koa/router") const compress = require("koa-compress") const zlib = require("zlib") const { routes } = require("./routes") +const { buildAuthMiddleware } = require("@budibase/auth").auth + +const NO_AUTH_ENDPOINTS = ["/api/admin/users/first"] const router = new Router() @@ -19,6 +22,7 @@ router }) ) .use("/health", ctx => (ctx.status = 200)) + .use(buildAuthMiddleware(NO_AUTH_ENDPOINTS)) // error handling middleware router.use(async (ctx, next) => { diff --git a/packages/worker/src/api/routes/admin/groups.js b/packages/worker/src/api/routes/admin/groups.js index e683a01c2b..c9d9f1c92f 100644 --- a/packages/worker/src/api/routes/admin/groups.js +++ b/packages/worker/src/api/routes/admin/groups.js @@ -1,7 +1,6 @@ const Router = require("@koa/router") const controller = require("../../controllers/admin/groups") const joiValidator = require("../../../middleware/joi-validator") -const { authenticated } = require("@budibase/auth") const Joi = require("joi") const router = Router() @@ -28,11 +27,10 @@ router .post( "/api/admin/groups", buildGroupSaveValidation(), - authenticated, controller.save ) - .delete("/api/admin/groups/:id", authenticated, controller.destroy) - .get("/api/admin/groups", authenticated, controller.fetch) - .get("/api/admin/groups/:id", authenticated, controller.find) + .get("/api/admin/groups", controller.fetch) + .delete("/api/admin/groups/:id", controller.destroy) + .get("/api/admin/groups/:id", controller.find) module.exports = router diff --git a/packages/worker/src/api/routes/admin/templates.js b/packages/worker/src/api/routes/admin/templates.js new file mode 100644 index 0000000000..0632d82ec2 --- /dev/null +++ b/packages/worker/src/api/routes/admin/templates.js @@ -0,0 +1,20 @@ +const Router = require("@koa/router") +const controller = require("../../controllers/admin/templates") +const joiValidator = require("../../../middleware/joi-validator") +const Joi = require("joi") + +const router = Router() + +function buildTemplateSaveValidation() { + +} + +router + .post( + "/api/admin/template/:type", + buildTemplateSaveValidation(), + controller.save + ) + .get("/api/admin/template/:type", controller.fetch) + .delete("/api/admin/template/:type/:id", controller.destroy) + .get("/api/admin/template/:type/:id", controller.find) diff --git a/packages/worker/src/api/routes/admin/users.js b/packages/worker/src/api/routes/admin/users.js index d7d19cbf49..bd7d8bbbd5 100644 --- a/packages/worker/src/api/routes/admin/users.js +++ b/packages/worker/src/api/routes/admin/users.js @@ -1,7 +1,6 @@ const Router = require("@koa/router") const controller = require("../../controllers/admin/users") const joiValidator = require("../../../middleware/joi-validator") -const { authenticated } = require("@budibase/auth") const Joi = require("joi") const router = Router() @@ -29,12 +28,11 @@ router .post( "/api/admin/users", buildUserSaveValidation(), - authenticated, controller.userSave ) + .get("/api/admin/users", controller.userFetch) .post("/api/admin/users/first", controller.firstUser) - .delete("/api/admin/users/:id", authenticated, controller.userDelete) - .get("/api/admin/users", authenticated, controller.userFetch) - .get("/api/admin/users/:id", authenticated, controller.userFind) + .delete("/api/admin/users/:id", controller.userDelete) + .get("/api/admin/users/:id", controller.userFind) module.exports = router diff --git a/packages/worker/src/api/routes/app.js b/packages/worker/src/api/routes/app.js index 07120f63a5..86004cb674 100644 --- a/packages/worker/src/api/routes/app.js +++ b/packages/worker/src/api/routes/app.js @@ -1,9 +1,8 @@ const Router = require("@koa/router") const controller = require("../controllers/app") -const { authenticated } = require("@budibase/auth") const router = Router() -router.get("/api/apps", authenticated, controller.getApps) +router.get("/api/apps", controller.getApps) module.exports = router diff --git a/packages/worker/src/api/routes/auth.js b/packages/worker/src/api/routes/auth.js index deea678c63..5ce1b69860 100644 --- a/packages/worker/src/api/routes/auth.js +++ b/packages/worker/src/api/routes/auth.js @@ -1,5 +1,5 @@ const Router = require("@koa/router") -const { passport } = require("@budibase/auth") +const { passport } = require("@budibase/auth").auth const authController = require("../controllers/auth") const router = Router() diff --git a/packages/worker/src/index.js b/packages/worker/src/index.js index 21ad8381fe..8b67181fcc 100644 --- a/packages/worker/src/index.js +++ b/packages/worker/src/index.js @@ -5,7 +5,7 @@ require("@budibase/auth").init(CouchDB) const Koa = require("koa") const destroyable = require("server-destroy") const koaBody = require("koa-body") -const { passport } = require("@budibase/auth") +const { passport } = require("@budibase/auth").auth const logger = require("koa-pino-logger") const http = require("http") const api = require("./api") From 15223080d59e628487b964d8079ea9ec07a6858a Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 21 Apr 2021 16:46:51 +0100 Subject: [PATCH 04/29] Formatting and linting. --- packages/auth/src/index.js | 2 +- .../src/api/controllers/admin/groups.js | 6 +++++- .../src/api/controllers/admin/templates.js | 19 +++++++++++++------ .../worker/src/api/routes/admin/groups.js | 6 +----- .../worker/src/api/routes/admin/templates.js | 8 +++----- packages/worker/src/api/routes/admin/users.js | 6 +----- 6 files changed, 24 insertions(+), 23 deletions(-) diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index 937b1491c5..0961e15232 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -31,7 +31,7 @@ module.exports = { db: require("./db/utils"), utils: { ...require("./utils"), - ...require("./hashing") + ...require("./hashing"), }, auth: { buildAuthMiddleware: authenticated, diff --git a/packages/worker/src/api/controllers/admin/groups.js b/packages/worker/src/api/controllers/admin/groups.js index 0943a58b1f..baa510f487 100644 --- a/packages/worker/src/api/controllers/admin/groups.js +++ b/packages/worker/src/api/controllers/admin/groups.js @@ -1,5 +1,9 @@ const CouchDB = require("../../../db") -const { getGroupParams, generateGroupID, StaticDatabases } = require("@budibase/auth").db +const { + getGroupParams, + generateGroupID, + StaticDatabases, +} = require("@budibase/auth").db const GLOBAL_DB = StaticDatabases.GLOBAL.name diff --git a/packages/worker/src/api/controllers/admin/templates.js b/packages/worker/src/api/controllers/admin/templates.js index 5a2e018702..e445f611a8 100644 --- a/packages/worker/src/api/controllers/admin/templates.js +++ b/packages/worker/src/api/controllers/admin/templates.js @@ -1,18 +1,25 @@ -const { generateTemplateID, getTemplateParams } = require("@budibase/auth").db -const { CouchDB } = require("../../../db") +// const { generateTemplateID, getTemplateParams, StaticDatabases } = require("@budibase/auth").db +// const { CouchDB } = require("../../../db") + +// const GLOBAL_DB = StaticDatabases.GLOBAL.name exports.save = async ctx => { - + // const db = new CouchDB(GLOBAL_DB) + // const id = generateTemplateID() + ctx.body = {} } exports.fetch = async ctx => { - + // const db = new CouchDB(GLOBAL_DB) + ctx.body = {} } exports.find = async ctx => { - + // const db = new CouchDB(GLOBAL_DB) + ctx.body = {} } exports.destroy = async ctx => { - + // const db = new CouchDB(GLOBAL_DB) + ctx.body = {} } diff --git a/packages/worker/src/api/routes/admin/groups.js b/packages/worker/src/api/routes/admin/groups.js index c9d9f1c92f..6ae8780a22 100644 --- a/packages/worker/src/api/routes/admin/groups.js +++ b/packages/worker/src/api/routes/admin/groups.js @@ -24,11 +24,7 @@ function buildGroupSaveValidation() { } router - .post( - "/api/admin/groups", - buildGroupSaveValidation(), - controller.save - ) + .post("/api/admin/groups", buildGroupSaveValidation(), controller.save) .get("/api/admin/groups", controller.fetch) .delete("/api/admin/groups/:id", controller.destroy) .get("/api/admin/groups/:id", controller.find) diff --git a/packages/worker/src/api/routes/admin/templates.js b/packages/worker/src/api/routes/admin/templates.js index 0632d82ec2..9c66b87200 100644 --- a/packages/worker/src/api/routes/admin/templates.js +++ b/packages/worker/src/api/routes/admin/templates.js @@ -1,13 +1,11 @@ const Router = require("@koa/router") const controller = require("../../controllers/admin/templates") -const joiValidator = require("../../../middleware/joi-validator") -const Joi = require("joi") +// const joiValidator = require("../../../middleware/joi-validator") +// const Joi = require("joi") const router = Router() -function buildTemplateSaveValidation() { - -} +function buildTemplateSaveValidation() {} router .post( diff --git a/packages/worker/src/api/routes/admin/users.js b/packages/worker/src/api/routes/admin/users.js index bd7d8bbbd5..f06153385e 100644 --- a/packages/worker/src/api/routes/admin/users.js +++ b/packages/worker/src/api/routes/admin/users.js @@ -25,11 +25,7 @@ function buildUserSaveValidation() { } router - .post( - "/api/admin/users", - buildUserSaveValidation(), - controller.userSave - ) + .post("/api/admin/users", buildUserSaveValidation(), controller.userSave) .get("/api/admin/users", controller.userFetch) .post("/api/admin/users/first", controller.firstUser) .delete("/api/admin/users/:id", controller.userDelete) From e85b7682e0f4b0d529680d81f28353e86599a2eb Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Wed, 21 Apr 2021 18:15:57 +0100 Subject: [PATCH 05/29] Initial CRUD interface for templates. --- packages/auth/src/db/utils.js | 8 ++- packages/server/src/db/utils.js | 3 +- .../src/api/controllers/admin/templates.js | 72 ++++++++++++++++--- .../worker/src/api/routes/admin/templates.js | 29 ++++++-- packages/worker/src/constants/index.js | 26 +++++++ 5 files changed, 116 insertions(+), 22 deletions(-) diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index 4bd1f399cd..deff7e1519 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -80,8 +80,12 @@ exports.getTemplateParams = (ownerId, templateId, otherProps = {}) => { if (!templateId) { templateId = "" } - const base = `${DocumentTypes.TEMPLATE}${SEPARATOR}${ownerId}` - const final = templateId ? `${base}${SEPARATOR}${templateId}` : base + let final + if (templateId) { + final = templateId + } else { + final = `${DocumentTypes.TEMPLATE}${SEPARATOR}${ownerId}${SEPARATOR}` + } return { ...otherProps, startkey: final, diff --git a/packages/server/src/db/utils.js b/packages/server/src/db/utils.js index e6bcfada5b..bbed248cf8 100644 --- a/packages/server/src/db/utils.js +++ b/packages/server/src/db/utils.js @@ -107,8 +107,7 @@ exports.getRowParams = (tableId = null, rowId = null, otherProps = {}) => { return getDocParams(DocumentTypes.ROW, null, otherProps) } - const endOfKey = - rowId == null ? `${tableId}${SEPARATOR}` : `${tableId}${SEPARATOR}${rowId}` + const endOfKey = rowId == null ? `${tableId}${SEPARATOR}` : rowId return getDocParams(DocumentTypes.ROW, endOfKey, otherProps) } diff --git a/packages/worker/src/api/controllers/admin/templates.js b/packages/worker/src/api/controllers/admin/templates.js index e445f611a8..25360bd1e5 100644 --- a/packages/worker/src/api/controllers/admin/templates.js +++ b/packages/worker/src/api/controllers/admin/templates.js @@ -1,25 +1,75 @@ -// const { generateTemplateID, getTemplateParams, StaticDatabases } = require("@budibase/auth").db -// const { CouchDB } = require("../../../db") +const { generateTemplateID, getTemplateParams, StaticDatabases } = require("@budibase/auth").db +const { CouchDB } = require("../../../db") +const { TemplatePurposePretty } = require("../../../constants") -// const GLOBAL_DB = StaticDatabases.GLOBAL.name +const GLOBAL_DB = StaticDatabases.GLOBAL.name +const GLOBAL_OWNER = "global" + +async function getTemplates({ ownerId, type, id } = {}) { + const db = new CouchDB(GLOBAL_DB) + const response = await db.allDocs( + getTemplateParams(ownerId, id, { + include_docs: true, + }) + ) + let templates = response.rows.map(row => row.doc) + if (type) { + templates = templates.filter(template => template.type === type) + } + return templates +} exports.save = async ctx => { - // const db = new CouchDB(GLOBAL_DB) - // const id = generateTemplateID() - ctx.body = {} + const db = new CouchDB(GLOBAL_DB) + const type = ctx.params.type + let template = ctx.request.body + if (!template.ownerId) { + template.ownerId = GLOBAL_OWNER + } + if (!template._id) { + template._id = generateTemplateID(template.ownerId) + } + + const response = await db.put({ + ...template, + type, + }) + ctx.body = { + ...template, + _rev: response.rev, + } +} + +exports.definitions = async ctx => { + ctx.body = { + purpose: TemplatePurposePretty + } } exports.fetch = async ctx => { - // const db = new CouchDB(GLOBAL_DB) - ctx.body = {} + ctx.body = await getTemplates() +} + +exports.fetchByType = async ctx => { + ctx.body = await getTemplates({ + type: ctx.params.type, + }) +} + +exports.fetchByOwner = async ctx => { + ctx.body = await getTemplates({ + ownerId: ctx.params.ownerId, + }) } exports.find = async ctx => { - // const db = new CouchDB(GLOBAL_DB) - ctx.body = {} + ctx.body = await getTemplates({ + id: ctx.params.id, + }) } exports.destroy = async ctx => { - // const db = new CouchDB(GLOBAL_DB) + // TODO + const db = new CouchDB(GLOBAL_DB) ctx.body = {} } diff --git a/packages/worker/src/api/routes/admin/templates.js b/packages/worker/src/api/routes/admin/templates.js index 9c66b87200..756b3e7cf0 100644 --- a/packages/worker/src/api/routes/admin/templates.js +++ b/packages/worker/src/api/routes/admin/templates.js @@ -1,18 +1,33 @@ const Router = require("@koa/router") const controller = require("../../controllers/admin/templates") -// const joiValidator = require("../../../middleware/joi-validator") -// const Joi = require("joi") +const joiValidator = require("../../../middleware/joi-validator") +const Joi = require("joi") +const { TemplatePurpose, TemplateTypes } = require("../../../constants") const router = Router() -function buildTemplateSaveValidation() {} +function buildTemplateSaveValidation() { + // prettier-ignore + return joiValidator.body(Joi.object({ + _id: Joi.string().allow(null, ""), + _rev: Joi.string().allow(null, ""), + ownerId: Joi.string().allow(null, ""), + name: Joi.string().allow(null, ""), + contents: Joi.string().required(), + purpose: Joi.string().required().valid(...Object.values(TemplatePurpose)), + type: Joi.string().required().valid(...Object.values(TemplateTypes)), + }).required().unknown(true).optional()) +} router + .get("/api/admin/template/definitions", controller.definitions) .post( - "/api/admin/template/:type", + "/api/admin/template", buildTemplateSaveValidation(), controller.save ) - .get("/api/admin/template/:type", controller.fetch) - .delete("/api/admin/template/:type/:id", controller.destroy) - .get("/api/admin/template/:type/:id", controller.find) + .get("/api/admin/template", controller.fetch) + .get("/api/admin/template/:type", controller.fetchByType) + .get("/api/admin/template/:ownerId", controller.fetchByOwner) + .delete("/api/admin/template/:id", controller.destroy) + .get("/api/admin/template/:id", controller.find) diff --git a/packages/worker/src/constants/index.js b/packages/worker/src/constants/index.js index 586d69c86f..dcdad2bb3e 100644 --- a/packages/worker/src/constants/index.js +++ b/packages/worker/src/constants/index.js @@ -6,3 +6,29 @@ exports.UserStatus = { exports.Groups = { ALL_USERS: "all_users", } + +exports.TemplateTypes = { + EMAIL: "email", +} + +exports.TemplatePurpose = { + PASSWORD_RECOVERY: "password_recovery", + INVITATION: "invitation", + CUSTOM: "custom", +} + +exports.TemplatePurposePretty = [ + { + name: "Password Recovery", + value: exports.TemplatePurpose.PASSWORD_RECOVERY + }, + { + name: "New User Invitation", + value: exports.TemplatePurpose.INVITATION, + }, + { + name: "Custom", + value: exports.TemplatePurpose.CUSTOM, + } +] + From 28f8f8b6efe91cc4d72e328ab62ed3c08cb39c21 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Wed, 21 Apr 2021 18:40:32 +0100 Subject: [PATCH 06/29] custom google middleware --- packages/auth/src/index.js | 3 +- .../auth/src/middleware/passport/google.js | 14 +- packages/worker/.vscode/launch.json | 139 ++++++++++++++++++ .../src/api/controllers/admin/configs.js | 7 + packages/worker/src/api/controllers/auth.js | 8 + 5 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 packages/worker/.vscode/launch.json diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index 4ef30c9f02..d1b09c3ae0 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -1,7 +1,6 @@ const passport = require("koa-passport") const LocalStrategy = require("passport-local").Strategy const JwtStrategy = require("passport-jwt").Strategy -const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy const database = require("./db") const { StaticDatabases, DocumentTypes } = require("./db/utils") const { jwt, local, google, authenticated } = require("./middleware") @@ -27,7 +26,7 @@ const { // Strategies passport.use(new LocalStrategy(local.options, local.authenticate)) passport.use(new JwtStrategy(jwt.options, jwt.authenticate)) -passport.use(new GoogleStrategy(google.options, google.authenticate)) +// passport.use(new GoogleStrategy(google.options, google.authenticate)) passport.serializeUser((user, done) => done(null, user)) diff --git a/packages/auth/src/middleware/passport/google.js b/packages/auth/src/middleware/passport/google.js index 9113fba1cf..69c038638f 100644 --- a/packages/auth/src/middleware/passport/google.js +++ b/packages/auth/src/middleware/passport/google.js @@ -1,6 +1,7 @@ const env = require("../../environment") const jwt = require("jsonwebtoken") const database = require("../../db") +const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy const { StaticDatabases, generateUserID } = require("../../db/utils") exports.options = { @@ -9,7 +10,7 @@ exports.options = { callbackURL: env.GOOGLE_AUTH_CALLBACK_URL, } -exports.authenticate = async function(token, tokenSecret, profile, done) { +async function authenticate(token, tokenSecret, profile, done) { if (!profile._json.email) return done(null, false, "Email Required.") // Check the user exists in the instance DB by email @@ -52,3 +53,14 @@ exports.authenticate = async function(token, tokenSecret, profile, done) { return done(null, dbUser) } + +exports.CustomGoogleStrategy = function(config) { + return new GoogleStrategy( + { + clientID: config.clientID, + clientSecret: config.clientSecret, + callbackURL: config.callbackURL, + }, + authenticate + ) +} diff --git a/packages/worker/.vscode/launch.json b/packages/worker/.vscode/launch.json new file mode 100644 index 0000000000..7417938376 --- /dev/null +++ b/packages/worker/.vscode/launch.json @@ -0,0 +1,139 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Start Server", + "program": "${workspaceFolder}/src/index.js" + }, + { + "type": "node", + "request": "launch", + "name": "Jest - All", + "program": "${workspaceFolder}/node_modules/.bin/jest", + "args": [], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true, + "windows": { + "program": "${workspaceFolder}/node_modules/jest-cli/bin/jest", + } + }, + { + "type": "node", + "request": "launch", + "name": "Jest - Users", + "program": "${workspaceFolder}/node_modules/.bin/jest", + "args": ["user.spec", "--runInBand"], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true, + "windows": { + "program": "${workspaceFolder}/node_modules/jest-cli/bin/jest", + } + }, + { + "type": "node", + "request": "launch", + "name": "Jest - Instances", + "program": "${workspaceFolder}/node_modules/.bin/jest", + "args": ["instance.spec", "--runInBand"], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true, + "windows": { + "program": "${workspaceFolder}/node_modules/jest-cli/bin/jest", + } + }, + { + "type": "node", + "request": "launch", + "name": "Jest - Roles", + "program": "${workspaceFolder}/node_modules/.bin/jest", + "args": ["role.spec", "--runInBand"], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true, + "windows": { + "program": "${workspaceFolder}/node_modules/jest-cli/bin/jest", + } + }, + { + "type": "node", + "request": "launch", + "name": "Jest - Records", + "program": "${workspaceFolder}/node_modules/.bin/jest", + "args": ["record.spec", "--runInBand"], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true, + "windows": { + "program": "${workspaceFolder}/node_modules/jest-cli/bin/jest", + } + }, + { + "type": "node", + "request": "launch", + "name": "Jest - Models", + "program": "${workspaceFolder}/node_modules/.bin/jest", + "args": ["table.spec", "--runInBand"], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true, + "windows": { + "program": "${workspaceFolder}/node_modules/jest-cli/bin/jest", + } + }, + { + "type": "node", + "request": "launch", + "name": "Jest - Views", + "program": "${workspaceFolder}/node_modules/.bin/jest", + "args": ["view.spec", "--runInBand"], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true, + "windows": { + "program": "${workspaceFolder}/node_modules/jest-cli/bin/jest", + } + }, + { + "type": "node", + "request": "launch", + "name": "Jest - Applications", + "program": "${workspaceFolder}/node_modules/.bin/jest", + "args": ["application.spec", "--runInBand"], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true, + "windows": { + "program": "${workspaceFolder}/node_modules/jest-cli/bin/jest", + } + }, + { + "type": "node", + "request": "launch", + "name": "Jest Builder", + "program": "${workspaceFolder}/node_modules/.bin/jest", + "args": ["builder", "--runInBand"], + "console": "integratedTerminal", + "internalConsoleOptions": "neverOpen", + "disableOptimisticBPs": true, + "windows": { + "program": "${workspaceFolder}/node_modules/jest-cli/bin/jest", + } + }, + { + "type": "node", + "request": "launch", + "name": "Initialise Budibase", + "program": "yarn", + "args": ["run", "initialise"], + "console": "externalTerminal" + } + ] +} diff --git a/packages/worker/src/api/controllers/admin/configs.js b/packages/worker/src/api/controllers/admin/configs.js index 10f1d2cf2b..c28f0179ee 100644 --- a/packages/worker/src/api/controllers/admin/configs.js +++ b/packages/worker/src/api/controllers/admin/configs.js @@ -69,6 +69,13 @@ exports.fetch = async function(ctx) { exports.find = async function(ctx) { const db = new CouchDB(GLOBAL_DB) + const response = await db.allDocs( + getConfigParams(undefined, { + include_docs: true, + }) + ) + const groups = response.rows.map(row => row.doc) + ctx.body = groups try { const record = await db.get(ctx.params.id) ctx.body = record diff --git a/packages/worker/src/api/controllers/auth.js b/packages/worker/src/api/controllers/auth.js index d2aaf552e0..df759ffc84 100644 --- a/packages/worker/src/api/controllers/auth.js +++ b/packages/worker/src/api/controllers/auth.js @@ -65,6 +65,14 @@ exports.logout = async ctx => { ctx.body = { message: "User logged out" } } +// exports.googleAuth = async (ctx, next) => +// passport.authenticate( +// "google", +// { successRedirect: "/", failureRedirect: "/" }, +// (ctx +// setToken(ctx, next) +// ) + exports.googleAuth = async (ctx, next) => { return passport.authenticate( "google", From 8fab374c1fce4e515253b198776caaa75fdd6147 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Wed, 21 Apr 2021 21:08:04 +0100 Subject: [PATCH 07/29] google login reading from couch --- packages/auth/src/db/utils.js | 4 +- packages/auth/src/index.js | 6 ++- .../auth/src/middleware/passport/google.js | 54 ++++++++++++++----- .../src/components/login/LoginForm.svelte | 2 +- packages/worker/src/api/controllers/auth.js | 23 ++++---- .../worker/src/api/routes/admin/configs.js | 15 ++---- .../worker/src/api/routes/admin/templates.js | 6 +-- packages/worker/src/api/routes/auth.js | 7 +-- packages/worker/src/constants/index.js | 1 + 9 files changed, 69 insertions(+), 49 deletions(-) diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index 9d366c30a6..ab9142eaee 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -48,8 +48,8 @@ exports.getGroupParams = (id = "", otherProps = {}) => { * Generates a new global user ID. * @returns {string} The new user ID which the user doc can be stored under. */ -exports.generateGlobalUserID = () => { - return `${DocumentTypes.USER}${SEPARATOR}${newid()}` +exports.generateGlobalUserID = id => { + return `${DocumentTypes.USER}${SEPARATOR}${id || newid()}` } /** diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index 3dcf26d346..1906e20be2 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -1,7 +1,7 @@ const passport = require("koa-passport") const LocalStrategy = require("passport-local").Strategy const JwtStrategy = require("passport-jwt").Strategy -const database = require("./db") +const constants = require("./constants") const { StaticDatabases, DocumentTypes } = require("./db/utils") const { jwt, local, google, authenticated } = require("./middleware") const { Cookies, UserStatus } = require("./constants") @@ -55,7 +55,11 @@ module.exports = { auth: { buildAuthMiddleware: authenticated, passport, + middlewares: { + google, + }, }, + constants, passport, Cookies, UserStatus, diff --git a/packages/auth/src/middleware/passport/google.js b/packages/auth/src/middleware/passport/google.js index 69c038638f..ad7c83d189 100644 --- a/packages/auth/src/middleware/passport/google.js +++ b/packages/auth/src/middleware/passport/google.js @@ -2,7 +2,11 @@ const env = require("../../environment") const jwt = require("jsonwebtoken") const database = require("../../db") const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy -const { StaticDatabases, generateUserID } = require("../../db/utils") +const { + StaticDatabases, + generateUserID, + generateGlobalUserID, +} = require("../../db/utils") exports.options = { clientID: env.GOOGLE_CLIENT_ID, @@ -11,13 +15,11 @@ exports.options = { } async function authenticate(token, tokenSecret, profile, done) { - if (!profile._json.email) return done(null, false, "Email Required.") - // Check the user exists in the instance DB by email - const db = new database.CouchDB(StaticDatabases.GLOBAL.name) + const db = database.getDB(StaticDatabases.GLOBAL.name) let dbUser - const userId = generateUserID(profile._json.email) + const userId = generateGlobalUserID(profile.id) try { // use the google profile id @@ -54,13 +56,37 @@ async function authenticate(token, tokenSecret, profile, done) { return done(null, dbUser) } -exports.CustomGoogleStrategy = function(config) { - return new GoogleStrategy( - { - clientID: config.clientID, - clientSecret: config.clientSecret, - callbackURL: config.callbackURL, - }, - authenticate - ) +/** + * Create an instance of the google passport strategy. This wrapper fetches the configuration + * from couchDB rather than environment variables, and is necessary for dynamically configuring passport. + * @returns Passport Google Strategy + */ +exports.strategyFactory = async function() { + try { + const db = database.getDB(StaticDatabases.GLOBAL.name) + + const config = await db.get( + "config_google__767bd8f363854dfa8752f593a637b3fd" + ) + + const { clientID, clientSecret, callbackURL } = config + + if (!clientID || !clientSecret || !callbackURL) { + throw new Error( + "Configuration invalid. Must contain google clientID, clientSecret and callbackURL" + ) + } + + return new GoogleStrategy( + { + clientID: config.clientID, + clientSecret: config.clientSecret, + callbackURL: config.callbackURL, + }, + authenticate + ) + } catch (err) { + console.error(err) + throw new Error("Error constructing google authentication strategy", err) + } } diff --git a/packages/builder/src/components/login/LoginForm.svelte b/packages/builder/src/components/login/LoginForm.svelte index 30d903a9d4..888054df1b 100644 --- a/packages/builder/src/components/login/LoginForm.svelte +++ b/packages/builder/src/components/login/LoginForm.svelte @@ -39,7 +39,7 @@ - Sign In with Google + Sign In With Google diff --git a/packages/worker/src/api/controllers/auth.js b/packages/worker/src/api/controllers/auth.js index 05e3256e34..bfc331042e 100644 --- a/packages/worker/src/api/controllers/auth.js +++ b/packages/worker/src/api/controllers/auth.js @@ -1,6 +1,7 @@ const authPkg = require("@budibase/auth") +const { google } = require("@budibase/auth/src/middleware") const { clearCookie } = authPkg.utils -const { Cookies } = authPkg.constants +const { Cookies } = authPkg const { passport } = authPkg.auth exports.authenticate = async (ctx, next) => { @@ -34,18 +35,20 @@ exports.logout = async ctx => { ctx.body = { message: "User logged out" } } -// exports.googleAuth = async (ctx, next) => -// passport.authenticate( -// "google", -// { successRedirect: "/", failureRedirect: "/" }, -// (ctx -// setToken(ctx, next) -// ) +exports.googlePreAuth = async (ctx, next) => { + const strategy = await google.strategyFactory() + + return passport.authenticate(strategy, { + scope: ["profile", "email"], + })(ctx, next) +} exports.googleAuth = async (ctx, next) => { + const strategy = await google.strategyFactory() + return passport.authenticate( - "google", - { successRedirect: "/", failureRedirect: "/" }, + strategy, + { successRedirect: "/", failureRedirect: "/error" }, async (err, user) => { if (err) { return ctx.throw(403, "Unauthorized") diff --git a/packages/worker/src/api/routes/admin/configs.js b/packages/worker/src/api/routes/admin/configs.js index 0399026cf2..0411a9ffa0 100644 --- a/packages/worker/src/api/routes/admin/configs.js +++ b/packages/worker/src/api/routes/admin/configs.js @@ -15,15 +15,10 @@ function buildConfigSaveValidation() { } router - .post( - "/api/admin/configs", - buildConfigSaveValidation(), - authenticated, - controller.save - ) - .post("/api/admin/config/status", controller.configStatus) - .delete("/api/admin/configs/:id", authenticated, controller.destroy) - .get("/api/admin/configs", authenticated, controller.fetch) - .get("/api/admin/configs/:id", authenticated, controller.find) + .post("/api/admin/configs", buildConfigSaveValidation(), controller.save) + .post("/api/admin/configs/status", controller.configStatus) + .delete("/api/admin/configs/:id", controller.destroy) + .get("/api/admin/configs", controller.fetch) + .get("/api/admin/configs/:id", controller.find) module.exports = router diff --git a/packages/worker/src/api/routes/admin/templates.js b/packages/worker/src/api/routes/admin/templates.js index 756b3e7cf0..2207b72458 100644 --- a/packages/worker/src/api/routes/admin/templates.js +++ b/packages/worker/src/api/routes/admin/templates.js @@ -21,11 +21,7 @@ function buildTemplateSaveValidation() { router .get("/api/admin/template/definitions", controller.definitions) - .post( - "/api/admin/template", - buildTemplateSaveValidation(), - controller.save - ) + .post("/api/admin/template", buildTemplateSaveValidation(), controller.save) .get("/api/admin/template", controller.fetch) .get("/api/admin/template/:type", controller.fetchByType) .get("/api/admin/template/:ownerId", controller.fetchByOwner) diff --git a/packages/worker/src/api/routes/auth.js b/packages/worker/src/api/routes/auth.js index ac7c7c0737..72fddec399 100644 --- a/packages/worker/src/api/routes/auth.js +++ b/packages/worker/src/api/routes/auth.js @@ -1,16 +1,11 @@ const Router = require("@koa/router") -const { passport } = require("@budibase/auth").auth const authController = require("../controllers/auth") -const context = require("koa/lib/context") const router = Router() router .post("/api/admin/auth", authController.authenticate) - .get( - "/api/admin/auth/google", - passport.authenticate("google", { scope: ["profile", "email"] }) - ) + .get("/api/admin/auth/google", authController.googlePreAuth) .get("/api/admin/auth/google/callback", authController.googleAuth) .post("/api/admin/auth/logout", authController.logout) diff --git a/packages/worker/src/constants/index.js b/packages/worker/src/constants/index.js index 345094206b..5d52ce798f 100644 --- a/packages/worker/src/constants/index.js +++ b/packages/worker/src/constants/index.js @@ -11,6 +11,7 @@ exports.Configs = { SETTINGS: "settings", ACCOUNT: "account", SMTP: "smtp", + GOOGLE: "google", } exports.TemplateTypes = { From 64628481918ade34a8aefe6eeffbd7ee402d7e0b Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 22 Apr 2021 11:45:22 +0100 Subject: [PATCH 08/29] config specificity --- packages/auth/src/db/utils.js | 15 +-- packages/auth/src/environment.js | 3 - packages/auth/src/index.js | 1 - packages/auth/src/middleware/authenticated.js | 7 +- .../auth/src/middleware/passport/google.js | 22 +--- packages/server/src/api/controllers/user.js | 2 +- packages/server/src/middleware/currentapp.js | 4 +- .../src/api/controllers/admin/configs.js | 116 +++++++++++------- packages/worker/src/api/controllers/auth.js | 13 +- .../worker/src/api/routes/admin/configs.js | 4 +- 10 files changed, 107 insertions(+), 80 deletions(-) diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index ab9142eaee..408daf7dd4 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -98,20 +98,21 @@ exports.getTemplateParams = (ownerId, templateId, otherProps = {}) => { * Generates a new configuration ID. * @returns {string} The new configuration ID which the config doc can be stored under. */ -exports.generateConfigID = (type = "", group = "", user = "") => { - // group += SEPARATOR - const scope = [type, group, user].join(SEPARATOR) +exports.generateConfigID = ({ type, group, user }) => { + const scope = [type, group, user].filter(Boolean).join(SEPARATOR) - return `${DocumentTypes.CONFIG}${SEPARATOR}${scope}${newid()}` + return `${DocumentTypes.CONFIG}${SEPARATOR}${scope}` } /** * Gets parameters for retrieving configurations. */ -exports.getConfigParams = (type = "", group = "", otherProps = {}) => { +exports.getConfigParams = ({ type, group, user }, otherProps = {}) => { + const scope = [type, group, user].filter(Boolean).join(SEPARATOR) + return { ...otherProps, - startkey: `${DocumentTypes.CONFIG}${SEPARATOR}${type}${SEPARATOR}${group}`, - endkey: `${DocumentTypes.CONFIG}${SEPARATOR}${type}${SEPARATOR}${group}${UNICODE_MAX}`, + startkey: `${DocumentTypes.CONFIG}${SEPARATOR}${scope}`, + endkey: `${DocumentTypes.CONFIG}${SEPARATOR}${scope}${UNICODE_MAX}`, } } diff --git a/packages/auth/src/environment.js b/packages/auth/src/environment.js index e6d7ddda65..3a5c81ea8b 100644 --- a/packages/auth/src/environment.js +++ b/packages/auth/src/environment.js @@ -2,7 +2,4 @@ module.exports = { JWT_SECRET: process.env.JWT_SECRET, COUCH_DB_URL: process.env.COUCH_DB_URL, SALT_ROUNDS: process.env.SALT_ROUNDS, - GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID, - GOOGLE_CLIENT_SECRET: process.env.GOOGLE_CLIENT_SECRET, - GOOGLE_AUTH_CALLBACK_URL: process.env.GOOGLE_AUTH_CALLBACK_URL, } diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index 1906e20be2..bdc9e16609 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -27,7 +27,6 @@ const { // Strategies passport.use(new LocalStrategy(local.options, local.authenticate)) passport.use(new JwtStrategy(jwt.options, jwt.authenticate)) -// passport.use(new GoogleStrategy(google.options, google.authenticate)) passport.serializeUser((user, done) => done(null, user)) diff --git a/packages/auth/src/middleware/authenticated.js b/packages/auth/src/middleware/authenticated.js index fc3a5b177e..443384ee76 100644 --- a/packages/auth/src/middleware/authenticated.js +++ b/packages/auth/src/middleware/authenticated.js @@ -1,5 +1,7 @@ const { Cookies } = require("../constants") +const database = require("../db") const { getCookie } = require("../utils") +const { StaticDatabases } = require("../db/utils") module.exports = (noAuthPatterns = []) => { const regex = new RegExp(noAuthPatterns.join("|")) @@ -13,8 +15,11 @@ module.exports = (noAuthPatterns = []) => { const authCookie = getCookie(ctx, Cookies.Auth) if (authCookie) { + const db = database.getDB(StaticDatabases.GLOBAL.name) + const user = await db.get(authCookie.userId) + delete user.password ctx.isAuthenticated = true - ctx.user = authCookie + ctx.user = user } return next() diff --git a/packages/auth/src/middleware/passport/google.js b/packages/auth/src/middleware/passport/google.js index ad7c83d189..ea49b2c35c 100644 --- a/packages/auth/src/middleware/passport/google.js +++ b/packages/auth/src/middleware/passport/google.js @@ -2,17 +2,7 @@ const env = require("../../environment") const jwt = require("jsonwebtoken") const database = require("../../db") const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy -const { - StaticDatabases, - generateUserID, - generateGlobalUserID, -} = require("../../db/utils") - -exports.options = { - clientID: env.GOOGLE_CLIENT_ID, - clientSecret: env.GOOGLE_CLIENT_SECRET, - callbackURL: env.GOOGLE_AUTH_CALLBACK_URL, -} +const { StaticDatabases, generateGlobalUserID } = require("../../db/utils") async function authenticate(token, tokenSecret, profile, done) { // Check the user exists in the instance DB by email @@ -58,16 +48,14 @@ async function authenticate(token, tokenSecret, profile, done) { /** * Create an instance of the google passport strategy. This wrapper fetches the configuration - * from couchDB rather than environment variables, and is necessary for dynamically configuring passport. - * @returns Passport Google Strategy + * from couchDB rather than environment variables, using this factory is necessary for dynamically configuring passport. + * @returns Dynamically configured Passport Google Strategy */ -exports.strategyFactory = async function() { +exports.strategyFactory = async function(scope) { try { const db = database.getDB(StaticDatabases.GLOBAL.name) - const config = await db.get( - "config_google__767bd8f363854dfa8752f593a637b3fd" - ) + const config = await db.get(scope) const { clientID, clientSecret, callbackURL } = config diff --git a/packages/server/src/api/controllers/user.js b/packages/server/src/api/controllers/user.js index 4b6c65736a..1f41acc754 100644 --- a/packages/server/src/api/controllers/user.js +++ b/packages/server/src/api/controllers/user.js @@ -72,7 +72,7 @@ exports.createMetadata = async function(ctx) { exports.updateSelfMetadata = async function(ctx) { // overwrite the ID with current users - ctx.request.body._id = ctx.user.userId + ctx.request.body._id = ctx.user._id // make sure no stale rev delete ctx.request.body._rev await exports.updateMetadata(ctx) diff --git a/packages/server/src/middleware/currentapp.js b/packages/server/src/middleware/currentapp.js index f429c74267..d85d2158c2 100644 --- a/packages/server/src/middleware/currentapp.js +++ b/packages/server/src/middleware/currentapp.js @@ -31,7 +31,7 @@ module.exports = async (ctx, next) => { appCookie.roleId === BUILTIN_ROLE_IDS.PUBLIC) ) { // Different App ID means cookie needs reset, or if the same public user has logged in - const globalId = getGlobalIDFromUserMetadataID(ctx.user.userId) + const globalId = getGlobalIDFromUserMetadataID(ctx.user._id) const globalUser = await getGlobalUsers(ctx, requestAppId, globalId) updateCookie = true appId = requestAppId @@ -50,7 +50,7 @@ module.exports = async (ctx, next) => { ctx.appId = appId if (roleId) { ctx.roleId = roleId - const userId = ctx.user ? generateUserMetadataID(ctx.user.userId) : null + const userId = ctx.user ? generateUserMetadataID(ctx.user._id) : null ctx.user = { ...ctx.user, // override userID with metadata one diff --git a/packages/worker/src/api/controllers/admin/configs.js b/packages/worker/src/api/controllers/admin/configs.js index c28f0179ee..5e39ebefc0 100644 --- a/packages/worker/src/api/controllers/admin/configs.js +++ b/packages/worker/src/api/controllers/admin/configs.js @@ -1,53 +1,27 @@ const CouchDB = require("../../../db") -const { StaticDatabases, DocumentTypes } = require("@budibase/auth") +const { StaticDatabases } = require("@budibase/auth") const { generateConfigID, getConfigParams } = require("@budibase/auth") -const { SEPARATOR } = require("@budibase/auth/src/db/utils") -const { Configs } = require("../../../constants") const GLOBAL_DB = StaticDatabases.GLOBAL.name -exports.configStatus = async function(ctx) { - const db = new CouchDB(GLOBAL_DB) - let configured = {} - - // check for super admin user - try { - configured.user = true - } catch (err) { - configured.user = false - } - - // check for SMTP config - try { - const response = await db.allDocs( - getConfigParams(`${DocumentTypes.CONFIG}${SEPARATOR}${Configs.SMTP}`) - ) - console.log(response) - configured.smtp = true - } catch (err) { - configured.smtp = false - } - - ctx.body = configured -} - exports.save = async function(ctx) { const db = new CouchDB(GLOBAL_DB) const configDoc = ctx.request.body + const { type, group, user } = configDoc // Config does not exist yet if (!configDoc._id) { - configDoc._id = generateConfigID( - configDoc.type, - configDoc.group, - configDoc.user - ) + configDoc._id = generateConfigID({ + type, + group, + user, + }) } try { const response = await db.post(configDoc) ctx.body = { - type: configDoc.type, + type, _id: response.id, _rev: response.rev, } @@ -67,18 +41,74 @@ exports.fetch = async function(ctx) { ctx.body = groups } +/** + * Gets the most granular config for a particular configuration type. + * The hierarchy is type -> group -> user. + */ exports.find = async function(ctx) { const db = new CouchDB(GLOBAL_DB) - const response = await db.allDocs( - getConfigParams(undefined, { - include_docs: true, - }) - ) - const groups = response.rows.map(row => row.doc) - ctx.body = groups + const userId = ctx.params.user && ctx.params.user._id + + const { group } = ctx.query + if (group) { + const group = await db.get(group) + const userInGroup = group.users.some(groupUser => groupUser === userId) + if (!ctx.user.admin && !userInGroup) { + ctx.throw(400, `User is not in specified group: ${group}.`) + } + } + try { - const record = await db.get(ctx.params.id) - ctx.body = record + const response = await db.allDocs( + getConfigParams( + { + type: ctx.params.type, + user: userId, + group, + }, + { + include_docs: true, + } + ) + ) + const configs = response.rows.map(row => row.doc) + + // Find the config with the most granular scope based on context + const scopedConfig = configs.find(config => { + // Config is specific to a user and a group + if ( + config._id.includes( + generateConfigID({ type: ctx.params.type, user: userId, group }) + ) + ) { + return config + } + + // Config is specific to a user + if ( + config._id.includes( + generateConfigID({ type: ctx.params.type, user: userId }) + ) + ) { + return config + } + + // Config is specific to a group only + if ( + config._id.includes(generateConfigID({ type: ctx.params.type, group })) + ) { + return config + } + + // Config specific to a config type only + return config + }) + + if (scopedConfig) { + ctx.body = scopedConfig + } else { + ctx.throw(400, "No configuration exists.") + } } catch (err) { ctx.throw(err.status, err) } diff --git a/packages/worker/src/api/controllers/auth.js b/packages/worker/src/api/controllers/auth.js index bfc331042e..61025b1a48 100644 --- a/packages/worker/src/api/controllers/auth.js +++ b/packages/worker/src/api/controllers/auth.js @@ -1,5 +1,6 @@ const authPkg = require("@budibase/auth") const { google } = require("@budibase/auth/src/middleware") +const { Configs } = require("../../constants") const { clearCookie } = authPkg.utils const { Cookies } = authPkg const { passport } = authPkg.auth @@ -35,8 +36,16 @@ exports.logout = async ctx => { ctx.body = { message: "User logged out" } } +/** + * The initial call that google authentication makes to take you to the google login screen. + * On a successful login, you will be redirected to the googleAuth callback route. + */ exports.googlePreAuth = async (ctx, next) => { - const strategy = await google.strategyFactory() + const strategy = await google.strategyFactory({ + type: Configs.GOOGLE, + user: ctx.user._id, + group: ctx.query.group, + }) return passport.authenticate(strategy, { scope: ["profile", "email"], @@ -44,7 +53,7 @@ exports.googlePreAuth = async (ctx, next) => { } exports.googleAuth = async (ctx, next) => { - const strategy = await google.strategyFactory() + const strategy = await google.strategyFactory(ctx) return passport.authenticate( strategy, diff --git a/packages/worker/src/api/routes/admin/configs.js b/packages/worker/src/api/routes/admin/configs.js index 0411a9ffa0..c6ac04619e 100644 --- a/packages/worker/src/api/routes/admin/configs.js +++ b/packages/worker/src/api/routes/admin/configs.js @@ -1,7 +1,6 @@ const Router = require("@koa/router") const controller = require("../../controllers/admin/configs") const joiValidator = require("../../../middleware/joi-validator") -const { authenticated } = require("@budibase/auth") const Joi = require("joi") const { Configs } = require("../../../constants") @@ -16,9 +15,8 @@ function buildConfigSaveValidation() { router .post("/api/admin/configs", buildConfigSaveValidation(), controller.save) - .post("/api/admin/configs/status", controller.configStatus) .delete("/api/admin/configs/:id", controller.destroy) .get("/api/admin/configs", controller.fetch) - .get("/api/admin/configs/:id", controller.find) + .get("/api/admin/configs/:type", controller.find) module.exports = router From f7085a57c7d3e7d99957fca61f7a4027c5bfeb26 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 22 Apr 2021 11:48:37 +0100 Subject: [PATCH 09/29] lint --- packages/worker/src/api/controllers/admin/templates.js | 8 ++++++-- packages/worker/src/api/controllers/auth.js | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/worker/src/api/controllers/admin/templates.js b/packages/worker/src/api/controllers/admin/templates.js index 25360bd1e5..2b4f6f8284 100644 --- a/packages/worker/src/api/controllers/admin/templates.js +++ b/packages/worker/src/api/controllers/admin/templates.js @@ -1,4 +1,8 @@ -const { generateTemplateID, getTemplateParams, StaticDatabases } = require("@budibase/auth").db +const { + generateTemplateID, + getTemplateParams, + StaticDatabases, +} = require("@budibase/auth").db const { CouchDB } = require("../../../db") const { TemplatePurposePretty } = require("../../../constants") @@ -42,7 +46,7 @@ exports.save = async ctx => { exports.definitions = async ctx => { ctx.body = { - purpose: TemplatePurposePretty + purpose: TemplatePurposePretty, } } diff --git a/packages/worker/src/api/controllers/auth.js b/packages/worker/src/api/controllers/auth.js index 61025b1a48..f9e5e212de 100644 --- a/packages/worker/src/api/controllers/auth.js +++ b/packages/worker/src/api/controllers/auth.js @@ -53,7 +53,11 @@ exports.googlePreAuth = async (ctx, next) => { } exports.googleAuth = async (ctx, next) => { - const strategy = await google.strategyFactory(ctx) + const strategy = await google.strategyFactory({ + type: Configs.GOOGLE, + user: ctx.user._id, + group: ctx.query.group, + }) return passport.authenticate( strategy, From 2555d711b23d5045e2096eba6042b6f26b3aae8a Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 22 Apr 2021 13:46:54 +0100 Subject: [PATCH 10/29] scoped configuration management --- packages/auth/src/db/utils.js | 49 ++++++++++++++++++- packages/auth/src/index.js | 2 + .../auth/src/middleware/passport/google.js | 6 +-- .../src/api/controllers/admin/configs.js | 48 ++---------------- .../src/api/controllers/admin/templates.js | 2 +- packages/worker/src/api/controllers/auth.js | 15 ++++-- 6 files changed, 67 insertions(+), 55 deletions(-) diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index 408daf7dd4..2f34bc0c51 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -98,7 +98,7 @@ exports.getTemplateParams = (ownerId, templateId, otherProps = {}) => { * Generates a new configuration ID. * @returns {string} The new configuration ID which the config doc can be stored under. */ -exports.generateConfigID = ({ type, group, user }) => { +const generateConfigID = ({ type, group, user }) => { const scope = [type, group, user].filter(Boolean).join(SEPARATOR) return `${DocumentTypes.CONFIG}${SEPARATOR}${scope}` @@ -107,7 +107,7 @@ exports.generateConfigID = ({ type, group, user }) => { /** * Gets parameters for retrieving configurations. */ -exports.getConfigParams = ({ type, group, user }, otherProps = {}) => { +const getConfigParams = ({ type, group, user }, otherProps = {}) => { const scope = [type, group, user].filter(Boolean).join(SEPARATOR) return { @@ -116,3 +116,48 @@ exports.getConfigParams = ({ type, group, user }, otherProps = {}) => { endkey: `${DocumentTypes.CONFIG}${SEPARATOR}${scope}${UNICODE_MAX}`, } } + +/** + * Returns the most granular configuration document from the DB based on the type, group and userID passed. + * @param {*} db - db instance to quer + * @param {Object} scopes - the type, group and userID scopes of the configuration. + * @returns The most granular configuration document based on the scope. + */ +const determineScopedConfig = async function(db, { type, user, group }) { + const response = await db.allDocs( + getConfigParams( + { type, user, group }, + { + include_docs: true, + } + ) + ) + const configs = response.rows.map(row => row.doc) + + // Find the config with the most granular scope based on context + const scopedConfig = configs.find(config => { + // Config is specific to a user and a group + if (config._id.includes(generateConfigID({ type, user, group }))) { + return config + } + + // Config is specific to a user + if (config._id.includes(generateConfigID({ type, user }))) { + return config + } + + // Config is specific to a group only + if (config._id.includes(generateConfigID({ type, group }))) { + return config + } + + // Config specific to a config type only + return config + }) + + return scopedConfig +} + +exports.generateConfigID = generateConfigID +exports.getConfigParams = getConfigParams +exports.determineScopedConfig = determineScopedConfig diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index bdc9e16609..4149314b4d 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -22,6 +22,7 @@ const { getEmailFromUserID, generateConfigID, getConfigParams, + determineScopedConfig, } = require("./db/utils") // Strategies @@ -71,6 +72,7 @@ module.exports = { getEmailFromUserID, generateConfigID, getConfigParams, + determineScopedConfig, hash, compare, getAppId, diff --git a/packages/auth/src/middleware/passport/google.js b/packages/auth/src/middleware/passport/google.js index ea49b2c35c..968dfa3e93 100644 --- a/packages/auth/src/middleware/passport/google.js +++ b/packages/auth/src/middleware/passport/google.js @@ -51,12 +51,8 @@ async function authenticate(token, tokenSecret, profile, done) { * from couchDB rather than environment variables, using this factory is necessary for dynamically configuring passport. * @returns Dynamically configured Passport Google Strategy */ -exports.strategyFactory = async function(scope) { +exports.strategyFactory = async function(config) { try { - const db = database.getDB(StaticDatabases.GLOBAL.name) - - const config = await db.get(scope) - const { clientID, clientSecret, callbackURL } = config if (!clientID || !clientSecret || !callbackURL) { diff --git a/packages/worker/src/api/controllers/admin/configs.js b/packages/worker/src/api/controllers/admin/configs.js index 5e39ebefc0..08c2b6df7d 100644 --- a/packages/worker/src/api/controllers/admin/configs.js +++ b/packages/worker/src/api/controllers/admin/configs.js @@ -1,5 +1,5 @@ const CouchDB = require("../../../db") -const { StaticDatabases } = require("@budibase/auth") +const { StaticDatabases, determineScopedConfig } = require("@budibase/auth") const { generateConfigID, getConfigParams } = require("@budibase/auth") const GLOBAL_DB = StaticDatabases.GLOBAL.name @@ -59,49 +59,11 @@ exports.find = async function(ctx) { } try { - const response = await db.allDocs( - getConfigParams( - { - type: ctx.params.type, - user: userId, - group, - }, - { - include_docs: true, - } - ) - ) - const configs = response.rows.map(row => row.doc) - // Find the config with the most granular scope based on context - const scopedConfig = configs.find(config => { - // Config is specific to a user and a group - if ( - config._id.includes( - generateConfigID({ type: ctx.params.type, user: userId, group }) - ) - ) { - return config - } - - // Config is specific to a user - if ( - config._id.includes( - generateConfigID({ type: ctx.params.type, user: userId }) - ) - ) { - return config - } - - // Config is specific to a group only - if ( - config._id.includes(generateConfigID({ type: ctx.params.type, group })) - ) { - return config - } - - // Config specific to a config type only - return config + const scopedConfig = await determineScopedConfig(db, { + type: ctx.params.type, + user: userId, + group, }) if (scopedConfig) { diff --git a/packages/worker/src/api/controllers/admin/templates.js b/packages/worker/src/api/controllers/admin/templates.js index 2b4f6f8284..d91323e0a1 100644 --- a/packages/worker/src/api/controllers/admin/templates.js +++ b/packages/worker/src/api/controllers/admin/templates.js @@ -74,6 +74,6 @@ exports.find = async ctx => { exports.destroy = async ctx => { // TODO - const db = new CouchDB(GLOBAL_DB) + // const db = new CouchDB(GLOBAL_DB) ctx.body = {} } diff --git a/packages/worker/src/api/controllers/auth.js b/packages/worker/src/api/controllers/auth.js index f9e5e212de..a58a7abdab 100644 --- a/packages/worker/src/api/controllers/auth.js +++ b/packages/worker/src/api/controllers/auth.js @@ -1,10 +1,14 @@ +const { determineScopedConfig } = require("@budibase/auth") const authPkg = require("@budibase/auth") const { google } = require("@budibase/auth/src/middleware") const { Configs } = require("../../constants") +const CouchDB = require("../../db") const { clearCookie } = authPkg.utils const { Cookies } = authPkg const { passport } = authPkg.auth +const GLOBAL_DB = authPkg.StaticDatabases.GLOBAL.name + exports.authenticate = async (ctx, next) => { return passport.authenticate("local", async (err, user) => { if (err) { @@ -41,11 +45,12 @@ exports.logout = async ctx => { * On a successful login, you will be redirected to the googleAuth callback route. */ exports.googlePreAuth = async (ctx, next) => { - const strategy = await google.strategyFactory({ + const db = new CouchDB(GLOBAL_DB) + const config = await determineScopedConfig(db, { type: Configs.GOOGLE, - user: ctx.user._id, group: ctx.query.group, }) + const strategy = await google.strategyFactory(config) return passport.authenticate(strategy, { scope: ["profile", "email"], @@ -53,11 +58,13 @@ exports.googlePreAuth = async (ctx, next) => { } exports.googleAuth = async (ctx, next) => { - const strategy = await google.strategyFactory({ + const db = new CouchDB(GLOBAL_DB) + + const config = await determineScopedConfig(db, { type: Configs.GOOGLE, - user: ctx.user._id, group: ctx.query.group, }) + const strategy = await google.strategyFactory(config) return passport.authenticate( strategy, From a071d7b365eb448952fe0fb111382cf614b8914d Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 22 Apr 2021 14:07:00 +0100 Subject: [PATCH 11/29] tidy up --- packages/auth/src/db/utils.js | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index 2f34bc0c51..d80d1f0662 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -132,29 +132,28 @@ const determineScopedConfig = async function(db, { type, user, group }) { } ) ) - const configs = response.rows.map(row => row.doc) + const configs = response.rows.map(row => { + const config = row.doc - // Find the config with the most granular scope based on context - const scopedConfig = configs.find(config => { // Config is specific to a user and a group if (config._id.includes(generateConfigID({ type, user, group }))) { - return config + config.score = 4 + } else if (config._id.includes(generateConfigID({ type, user }))) { + // Config is specific to a user only + config.score = 3 + } else if (config._id.includes(generateConfigID({ type, group }))) { + // Config is specific to a group only + config.score = 2 + } else if (config._id.includes(generateConfigID({ type }))) { + // Config is specific to a type only + config.score = 1 } - - // Config is specific to a user - if (config._id.includes(generateConfigID({ type, user }))) { - return config - } - - // Config is specific to a group only - if (config._id.includes(generateConfigID({ type, group }))) { - return config - } - - // Config specific to a config type only return config }) + // Find the config with the most granular scope based on context + const scopedConfig = configs.sort((a, b) => b.score - a.score)[0] + return scopedConfig } From 9fdff36b54ec279c99d931c7569b7d133b5ab266 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 22 Apr 2021 14:53:19 +0100 Subject: [PATCH 12/29] only keep userId in payload --- packages/auth/src/db/utils.js | 2 +- packages/auth/src/middleware/passport/local.js | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/auth/src/db/utils.js b/packages/auth/src/db/utils.js index d80d1f0662..393e03e492 100644 --- a/packages/auth/src/db/utils.js +++ b/packages/auth/src/db/utils.js @@ -119,7 +119,7 @@ const getConfigParams = ({ type, group, user }, otherProps = {}) => { /** * Returns the most granular configuration document from the DB based on the type, group and userID passed. - * @param {*} db - db instance to quer + * @param {Object} db - db instance to query * @param {Object} scopes - the type, group and userID scopes of the configuration. * @returns The most granular configuration document based on the scope. */ diff --git a/packages/auth/src/middleware/passport/local.js b/packages/auth/src/middleware/passport/local.js index 1942d0c424..5b8bf307d7 100644 --- a/packages/auth/src/middleware/passport/local.js +++ b/packages/auth/src/middleware/passport/local.js @@ -33,8 +33,6 @@ exports.authenticate = async function(email, password, done) { if (await compare(password, dbUser.password)) { const payload = { userId: dbUser._id, - builder: dbUser.builder, - email: dbUser.email, } dbUser.token = jwt.sign(payload, env.JWT_SECRET, { From 086d8f0b144ab7520417c6e55c1779c54438c32d Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 22 Apr 2021 15:26:32 +0100 Subject: [PATCH 13/29] Adding some base templates which will be returned based on purpose, need to create a list of options that will be exposed/made available via configuration. --- .../src/api/controllers/admin/templates.js | 35 ++- .../worker/src/api/routes/admin/templates.js | 2 +- packages/worker/src/constants/index.js | 56 ++-- .../src/constants/templates/footer.html | 48 ++++ .../src/constants/templates/header.html | 36 +++ .../worker/src/constants/templates/index.js | 19 ++ .../src/constants/templates/invitation.html | 14 + .../constants/templates/passwordRecovery.html | 15 + .../worker/src/constants/templates/style.css | 269 ++++++++++++++++++ packages/worker/src/utilities/email.js | 0 packages/worker/src/utilities/fileSystem.js | 5 + 11 files changed, 478 insertions(+), 21 deletions(-) create mode 100644 packages/worker/src/constants/templates/footer.html create mode 100644 packages/worker/src/constants/templates/header.html create mode 100644 packages/worker/src/constants/templates/index.js create mode 100644 packages/worker/src/constants/templates/invitation.html create mode 100644 packages/worker/src/constants/templates/passwordRecovery.html create mode 100644 packages/worker/src/constants/templates/style.css create mode 100644 packages/worker/src/utilities/email.js create mode 100644 packages/worker/src/utilities/fileSystem.js diff --git a/packages/worker/src/api/controllers/admin/templates.js b/packages/worker/src/api/controllers/admin/templates.js index 25360bd1e5..b18bc4e5bb 100644 --- a/packages/worker/src/api/controllers/admin/templates.js +++ b/packages/worker/src/api/controllers/admin/templates.js @@ -1,10 +1,31 @@ const { generateTemplateID, getTemplateParams, StaticDatabases } = require("@budibase/auth").db const { CouchDB } = require("../../../db") -const { TemplatePurposePretty } = require("../../../constants") +const { TemplatePurposePretty, TemplateTypes, EmailTemplatePurpose, TemplatePurpose } = require("../../../constants") +const { getTemplateByPurpose } = require("../../../constants/templates") const GLOBAL_DB = StaticDatabases.GLOBAL.name const GLOBAL_OWNER = "global" +function addBaseTemplates(templates, type = null) { + let purposeList + switch (type) { + case TemplateTypes.EMAIL: + purposeList = Object.values(EmailTemplatePurpose) + break + default: + purposeList = Object.values(TemplatePurpose) + break + } + for (let purpose of purposeList) { + // check if a template exists already for purpose + if (templates.find(template => template.purpose === purpose)) { + continue + } + templates.push(getTemplateByPurpose(purpose)) + } + return templates +} + async function getTemplates({ ownerId, type, id } = {}) { const db = new CouchDB(GLOBAL_DB) const response = await db.allDocs( @@ -13,10 +34,15 @@ async function getTemplates({ ownerId, type, id } = {}) { }) ) let templates = response.rows.map(row => row.doc) + // should only be one template with ID + if (id) { + return templates[0] + } if (type) { templates = templates.filter(template => template.type === type) } - return templates + + return addBaseTemplates(templates, type) } exports.save = async ctx => { @@ -69,7 +95,8 @@ exports.find = async ctx => { } exports.destroy = async ctx => { - // TODO const db = new CouchDB(GLOBAL_DB) - ctx.body = {} + await db.remove(ctx.params.id, ctx.params.rev) + ctx.message = `Template ${ctx.params.id} deleted.` + ctx.status = 200 } diff --git a/packages/worker/src/api/routes/admin/templates.js b/packages/worker/src/api/routes/admin/templates.js index 756b3e7cf0..6f089cc0f3 100644 --- a/packages/worker/src/api/routes/admin/templates.js +++ b/packages/worker/src/api/routes/admin/templates.js @@ -29,5 +29,5 @@ router .get("/api/admin/template", controller.fetch) .get("/api/admin/template/:type", controller.fetchByType) .get("/api/admin/template/:ownerId", controller.fetchByOwner) - .delete("/api/admin/template/:id", controller.destroy) .get("/api/admin/template/:id", controller.find) + .delete("/api/admin/template/:id/:rev", controller.destroy) diff --git a/packages/worker/src/constants/index.js b/packages/worker/src/constants/index.js index dcdad2bb3e..ec9ce7b013 100644 --- a/packages/worker/src/constants/index.js +++ b/packages/worker/src/constants/index.js @@ -7,28 +7,52 @@ exports.Groups = { ALL_USERS: "all_users", } -exports.TemplateTypes = { +const TemplateTypes = { EMAIL: "email", } -exports.TemplatePurpose = { +const EmailTemplatePurpose = { + HEADER: "header", + FOOTER: "footer", + STYLES: "styles", PASSWORD_RECOVERY: "password_recovery", INVITATION: "invitation", CUSTOM: "custom", } -exports.TemplatePurposePretty = [ - { - name: "Password Recovery", - value: exports.TemplatePurpose.PASSWORD_RECOVERY - }, - { - name: "New User Invitation", - value: exports.TemplatePurpose.INVITATION, - }, - { - name: "Custom", - value: exports.TemplatePurpose.CUSTOM, - } -] +const TemplatePurposePretty = { + [TemplateTypes.EMAIL]: [ + { + name: "Styling", + value: EmailTemplatePurpose.STYLES, + }, + { + name: "Header", + value: EmailTemplatePurpose.HEADER, + }, + { + name: "Footer", + value: EmailTemplatePurpose.FOOTER, + }, + { + name: "Password Recovery", + value: EmailTemplatePurpose.PASSWORD_RECOVERY + }, + { + name: "New User Invitation", + value: EmailTemplatePurpose.INVITATION, + }, + { + name: "Custom", + value: EmailTemplatePurpose.CUSTOM, + } + ] +} +// all purpose combined +exports.TemplatePurpose = { + ...EmailTemplatePurpose, +} +exports.TemplateTypes = TemplateTypes +exports.EmailTemplatePurpose = EmailTemplatePurpose +exports.TemplatePurposePretty = TemplatePurposePretty diff --git a/packages/worker/src/constants/templates/footer.html b/packages/worker/src/constants/templates/footer.html new file mode 100644 index 0000000000..693fd3c0c0 --- /dev/null +++ b/packages/worker/src/constants/templates/footer.html @@ -0,0 +1,48 @@ + + + + + + + + +
\ No newline at end of file diff --git a/packages/worker/src/constants/templates/header.html b/packages/worker/src/constants/templates/header.html new file mode 100644 index 0000000000..7709bd30a8 --- /dev/null +++ b/packages/worker/src/constants/templates/header.html @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ \ No newline at end of file diff --git a/packages/worker/src/constants/templates/index.js b/packages/worker/src/constants/templates/index.js new file mode 100644 index 0000000000..42fbcf70ab --- /dev/null +++ b/packages/worker/src/constants/templates/index.js @@ -0,0 +1,19 @@ +const { readStaticFile } = require("../../utilities/fileSystem") +const { EmailTemplatePurpose } = require("../index") +const { join } = require("path") + +const TEMPLATE_PATH = join(__dirname, "..", "constants", "templates") + +exports.EmailTemplates = { + [EmailTemplatePurpose.PASSWORD_RECOVERY]: readStaticFile(join(TEMPLATE_PATH, "passwordRecovery.html")), + [EmailTemplatePurpose.INVITATION]: readStaticFile(join(TEMPLATE_PATH, "invitation.html")), + [EmailTemplatePurpose.HEADER]: readStaticFile(join(TEMPLATE_PATH, "header.html")), + [EmailTemplatePurpose.FOOTER]: readStaticFile(join(TEMPLATE_PATH, "footer.html")), + [EmailTemplatePurpose.STYLES]: readStaticFile(join(TEMPLATE_PATH, "style.css")), +} + +exports.getTemplateByPurpose = purpose => { + if (exports.EmailTemplates[purpose]) { + return exports.EmailTemplates[purpose] + } +} diff --git a/packages/worker/src/constants/templates/invitation.html b/packages/worker/src/constants/templates/invitation.html new file mode 100644 index 0000000000..8e154fe189 --- /dev/null +++ b/packages/worker/src/constants/templates/invitation.html @@ -0,0 +1,14 @@ + + + + + + +
\ No newline at end of file diff --git a/packages/worker/src/constants/templates/passwordRecovery.html b/packages/worker/src/constants/templates/passwordRecovery.html new file mode 100644 index 0000000000..e6b179ec81 --- /dev/null +++ b/packages/worker/src/constants/templates/passwordRecovery.html @@ -0,0 +1,15 @@ + + + + + + +
\ No newline at end of file diff --git a/packages/worker/src/constants/templates/style.css b/packages/worker/src/constants/templates/style.css new file mode 100644 index 0000000000..abcd797830 --- /dev/null +++ b/packages/worker/src/constants/templates/style.css @@ -0,0 +1,269 @@ +@font-face { + font-family: 'Playfair Display'; + font-style: italic; + font-weight: 400; + src: url(/fonts.gstatic.com/s/playfairdisplay/v22/nuFkD-vYSZviVYUb_rj3ij__anPXDTnohkk72xU.woff2) format('woff2'); + unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; +} +html, +body { + margin: 0 auto !important; + padding: 0 !important; + height: 100% !important; + width: 100% !important; + background: #f1f1f1; +} +* { + -ms-text-size-adjust: 100%; + -webkit-text-size-adjust: 100%; +} +div[style*="margin: 16px 0"] { + margin: 0 !important; +} +table, +td { + mso-table-lspace: 0pt !important; + mso-table-rspace: 0pt !important; +} +table { + border-spacing: 0 !important; + border-collapse: collapse !important; + table-layout: fixed !important; + margin: 0 auto !important; +} +img { + -ms-interpolation-mode:bicubic; +} +a { + text-decoration: none; +} +*[x-apple-data-detectors], /* iOS */ +.unstyle-auto-detected-links *, +.aBn { + border-bottom: 0 !important; + cursor: default !important; + color: inherit !important; + text-decoration: none !important; + font-size: inherit !important; + font-family: inherit !important; + font-weight: inherit !important; + line-height: inherit !important; +} +.a6S { + display: none !important; + opacity: 0.01 !important; +} +.im { + color: inherit !important; +} +img.g-img + div { + display: none !important; +} +@media only screen and (min-device-width: 320px) and (max-device-width: 374px) { + u ~ div .email-container { + min-width: 320px !important; + } +} +@media only screen and (min-device-width: 375px) and (max-device-width: 413px) { + u ~ div .email-container { + min-width: 375px !important; + } +} +@media only screen and (min-device-width: 414px) { + u ~ div .email-container { + min-width: 414px !important; + } +} +.primary{ + background: #f3a333; +} +.bg_white{ + background: #ffffff; +} +.bg_light{ + background: #fafafa; +} +.bg_black{ + background: #000000; +} +.bg_dark{ + background: rgba(0,0,0,.8); +} +.email-section{ + padding:2.5em; +} +.btn{ + padding: 10px 15px; +} +.btn.btn-primary{ + border-radius: 30px; + background: #f3a333; + color: #ffffff; +} +h1,h2,h3,h4,h5,h6{ + font-family: 'Playfair Display', serif; + color: #000000; + margin-top: 0; +} +body{ + font-family: 'Montserrat', sans-serif; + font-weight: 400; + font-size: 15px; + line-height: 1.8; + color: rgba(0,0,0,.4); +} +a{ + color: #f3a333; +} +table{ +} +.logo h1{ + margin: 0; +} +.logo h1 a{ + color: #000; + font-size: 20px; + font-weight: 700; + text-transform: uppercase; + font-family: 'Montserrat', sans-serif; +} +.hero{ + position: relative; +} +.hero img{ + +} +.hero .text{ + color: rgba(255,255,255,.8); +} +.hero .text h2{ + color: #ffffff; + font-size: 30px; + margin-bottom: 0; +} +.heading-section{ +} +.heading-section h2{ + color: #000000; + font-size: 28px; + margin-top: 0; + line-height: 1.4; +} +.heading-section .subheading{ + margin-bottom: 20px !important; + display: inline-block; + font-size: 13px; + text-transform: uppercase; + letter-spacing: 2px; + color: rgba(0,0,0,.4); + position: relative; +} +.heading-section .subheading::after{ + position: absolute; + left: 0; + right: 0; + bottom: -10px; + content: ''; + width: 100%; + height: 2px; + background: #f3a333; + margin: 0 auto; +} +.heading-section-white{ + color: rgba(255,255,255,.8); +} +.heading-section-white h2{ + font-size: 28px; + line-height: 1; + padding-bottom: 0; +} +.heading-section-white h2{ + color: #ffffff; +} +.heading-section-white .subheading{ + margin-bottom: 0; + display: inline-block; + font-size: 13px; + text-transform: uppercase; + letter-spacing: 2px; + color: rgba(255,255,255,.4); +} +.icon{ + text-align: center; +} +.icon img{ +} +.text-services{ + padding: 10px 10px 0; + text-align: center; +} +.text-services h3{ + font-size: 20px; +} +.text-services .meta{ + text-transform: uppercase; + font-size: 14px; +} +.img{ + width: 100%; + height: auto; + position: relative; +} +.img .icon{ + position: absolute; + top: 50%; + left: 0; + right: 0; + bottom: 0; + margin-top: -25px; +} +.img .icon a{ + display: block; + width: 60px; + position: absolute; + top: 0; + left: 50%; + margin-left: -25px; +} +.counter-text{ + text-align: center; +} +.counter-text .num{ + display: block; + color: #ffffff; + font-size: 34px; + font-weight: 700; +} +.counter-text .name{ + display: block; + color: rgba(255,255,255,.9); + font-size: 13px; +} +.footer{ + color: rgba(255,255,255,.5); +} +.footer .heading{ + color: #ffffff; + font-size: 20px; +} +.footer ul{ + margin: 0; + padding: 0; +} +.footer ul li{ + list-style: none; + margin-bottom: 10px; +} +.footer ul li a{ + color: rgba(255,255,255,1); +} +@media screen and (max-width: 500px) { + .icon{ + text-align: left; + } + .text-services{ + padding-left: 0; + padding-right: 20px; + text-align: left; + } +} \ No newline at end of file diff --git a/packages/worker/src/utilities/email.js b/packages/worker/src/utilities/email.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/packages/worker/src/utilities/fileSystem.js b/packages/worker/src/utilities/fileSystem.js new file mode 100644 index 0000000000..7df21db695 --- /dev/null +++ b/packages/worker/src/utilities/fileSystem.js @@ -0,0 +1,5 @@ +const { readFileSync } = require("fs") + +exports.readStaticFile = path => { + return readFileSync(path, "utf-8") +} \ No newline at end of file From c273152126bbf8147648925e8a02135ecd16e2de Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Thu, 22 Apr 2021 15:27:09 +0100 Subject: [PATCH 14/29] fix imports --- packages/auth/src/index.js | 50 ++----------------- .../src/api/controllers/admin/configs.js | 10 ++-- packages/worker/src/api/controllers/auth.js | 7 ++- 3 files changed, 12 insertions(+), 55 deletions(-) diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index 4149314b4d..c1e0a08242 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -1,29 +1,9 @@ const passport = require("koa-passport") const LocalStrategy = require("passport-local").Strategy const JwtStrategy = require("passport-jwt").Strategy -const constants = require("./constants") -const { StaticDatabases, DocumentTypes } = require("./db/utils") -const { jwt, local, google, authenticated } = require("./middleware") -const { Cookies, UserStatus } = require("./constants") -const { hash, compare } = require("./hashing") -const { - getAppId, - setCookie, - getCookie, - clearCookie, - isClient, -} = require("./utils") +const { StaticDatabases } = require("./db/utils") +const { jwt, local, authenticated, google } = require("./middleware") const { setDB, getDB } = require("./db") -const { - generateUserID, - getUserParams, - generateGroupID, - getGroupParams, - getEmailFromUserID, - generateConfigID, - getConfigParams, - determineScopedConfig, -} = require("./db/utils") // Strategies passport.use(new LocalStrategy(local.options, local.authenticate)) @@ -55,30 +35,8 @@ module.exports = { auth: { buildAuthMiddleware: authenticated, passport, - middlewares: { - google, - }, + google, }, - constants, - passport, - Cookies, - UserStatus, - DocumentTypes, StaticDatabases, - generateUserID, - getUserParams, - generateGroupID, - getGroupParams, - getEmailFromUserID, - generateConfigID, - getConfigParams, - determineScopedConfig, - hash, - compare, - getAppId, - setCookie, - getCookie, - clearCookie, - authenticated, - isClient, + constants: require("./constants"), } diff --git a/packages/worker/src/api/controllers/admin/configs.js b/packages/worker/src/api/controllers/admin/configs.js index 08c2b6df7d..67f3405fa4 100644 --- a/packages/worker/src/api/controllers/admin/configs.js +++ b/packages/worker/src/api/controllers/admin/configs.js @@ -1,6 +1,6 @@ const CouchDB = require("../../../db") -const { StaticDatabases, determineScopedConfig } = require("@budibase/auth") -const { generateConfigID, getConfigParams } = require("@budibase/auth") +const authPkg = require("@budibase/auth") +const { utils, StaticDatabases } = authPkg const GLOBAL_DB = StaticDatabases.GLOBAL.name @@ -11,7 +11,7 @@ exports.save = async function(ctx) { // Config does not exist yet if (!configDoc._id) { - configDoc._id = generateConfigID({ + configDoc._id = utils.generateConfigID({ type, group, user, @@ -33,7 +33,7 @@ exports.save = async function(ctx) { exports.fetch = async function(ctx) { const db = new CouchDB(GLOBAL_DB) const response = await db.allDocs( - getConfigParams(undefined, { + utils.getConfigParams(undefined, { include_docs: true, }) ) @@ -60,7 +60,7 @@ exports.find = async function(ctx) { try { // Find the config with the most granular scope based on context - const scopedConfig = await determineScopedConfig(db, { + const scopedConfig = await authPkg.db.determineScopedConfig(db, { type: ctx.params.type, user: userId, group, diff --git a/packages/worker/src/api/controllers/auth.js b/packages/worker/src/api/controllers/auth.js index a58a7abdab..bcda523a93 100644 --- a/packages/worker/src/api/controllers/auth.js +++ b/packages/worker/src/api/controllers/auth.js @@ -1,10 +1,9 @@ -const { determineScopedConfig } = require("@budibase/auth") const authPkg = require("@budibase/auth") const { google } = require("@budibase/auth/src/middleware") const { Configs } = require("../../constants") const CouchDB = require("../../db") const { clearCookie } = authPkg.utils -const { Cookies } = authPkg +const { Cookies } = authPkg.constants const { passport } = authPkg.auth const GLOBAL_DB = authPkg.StaticDatabases.GLOBAL.name @@ -46,7 +45,7 @@ exports.logout = async ctx => { */ exports.googlePreAuth = async (ctx, next) => { const db = new CouchDB(GLOBAL_DB) - const config = await determineScopedConfig(db, { + const config = await authPkg.db.determineScopedConfig(db, { type: Configs.GOOGLE, group: ctx.query.group, }) @@ -60,7 +59,7 @@ exports.googlePreAuth = async (ctx, next) => { exports.googleAuth = async (ctx, next) => { const db = new CouchDB(GLOBAL_DB) - const config = await determineScopedConfig(db, { + const config = await authPkg.db.determineScopedConfig(db, { type: Configs.GOOGLE, group: ctx.query.group, }) From f445cd4d86343c8fee51828a29c44fa2d58375be Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 22 Apr 2021 16:06:29 +0100 Subject: [PATCH 15/29] Formatting. --- .../src/api/controllers/admin/templates.js | 7 ++++++- packages/worker/src/constants/index.js | 6 +++--- .../worker/src/constants/templates/index.js | 20 ++++++++++++++----- packages/worker/src/utilities/fileSystem.js | 2 +- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/packages/worker/src/api/controllers/admin/templates.js b/packages/worker/src/api/controllers/admin/templates.js index ccf057c485..0314ca6099 100644 --- a/packages/worker/src/api/controllers/admin/templates.js +++ b/packages/worker/src/api/controllers/admin/templates.js @@ -4,7 +4,12 @@ const { StaticDatabases, } = require("@budibase/auth").db const { CouchDB } = require("../../../db") -const { TemplatePurposePretty, TemplateTypes, EmailTemplatePurpose, TemplatePurpose } = require("../../../constants") +const { + TemplatePurposePretty, + TemplateTypes, + EmailTemplatePurpose, + TemplatePurpose, +} = require("../../../constants") const { getTemplateByPurpose } = require("../../../constants/templates") const GLOBAL_DB = StaticDatabases.GLOBAL.name diff --git a/packages/worker/src/constants/index.js b/packages/worker/src/constants/index.js index 8edba58fda..44ca57ea17 100644 --- a/packages/worker/src/constants/index.js +++ b/packages/worker/src/constants/index.js @@ -43,7 +43,7 @@ const TemplatePurposePretty = { }, { name: "Password Recovery", - value: EmailTemplatePurpose.PASSWORD_RECOVERY + value: EmailTemplatePurpose.PASSWORD_RECOVERY, }, { name: "New User Invitation", @@ -52,8 +52,8 @@ const TemplatePurposePretty = { { name: "Custom", value: EmailTemplatePurpose.CUSTOM, - } - ] + }, + ], } // all purpose combined diff --git a/packages/worker/src/constants/templates/index.js b/packages/worker/src/constants/templates/index.js index 42fbcf70ab..53db5f2b42 100644 --- a/packages/worker/src/constants/templates/index.js +++ b/packages/worker/src/constants/templates/index.js @@ -5,11 +5,21 @@ const { join } = require("path") const TEMPLATE_PATH = join(__dirname, "..", "constants", "templates") exports.EmailTemplates = { - [EmailTemplatePurpose.PASSWORD_RECOVERY]: readStaticFile(join(TEMPLATE_PATH, "passwordRecovery.html")), - [EmailTemplatePurpose.INVITATION]: readStaticFile(join(TEMPLATE_PATH, "invitation.html")), - [EmailTemplatePurpose.HEADER]: readStaticFile(join(TEMPLATE_PATH, "header.html")), - [EmailTemplatePurpose.FOOTER]: readStaticFile(join(TEMPLATE_PATH, "footer.html")), - [EmailTemplatePurpose.STYLES]: readStaticFile(join(TEMPLATE_PATH, "style.css")), + [EmailTemplatePurpose.PASSWORD_RECOVERY]: readStaticFile( + join(TEMPLATE_PATH, "passwordRecovery.html") + ), + [EmailTemplatePurpose.INVITATION]: readStaticFile( + join(TEMPLATE_PATH, "invitation.html") + ), + [EmailTemplatePurpose.HEADER]: readStaticFile( + join(TEMPLATE_PATH, "header.html") + ), + [EmailTemplatePurpose.FOOTER]: readStaticFile( + join(TEMPLATE_PATH, "footer.html") + ), + [EmailTemplatePurpose.STYLES]: readStaticFile( + join(TEMPLATE_PATH, "style.css") + ), } exports.getTemplateByPurpose = purpose => { diff --git a/packages/worker/src/utilities/fileSystem.js b/packages/worker/src/utilities/fileSystem.js index 7df21db695..8f0bc8d3ed 100644 --- a/packages/worker/src/utilities/fileSystem.js +++ b/packages/worker/src/utilities/fileSystem.js @@ -2,4 +2,4 @@ const { readFileSync } = require("fs") exports.readStaticFile = path => { return readFileSync(path, "utf-8") -} \ No newline at end of file +} From 85441c6141a41111dd8974383294bb244adf6922 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 22 Apr 2021 17:57:38 +0100 Subject: [PATCH 16/29] Fleshing out the main work behind the email generation. --- packages/worker/package.json | 1 + .../src/api/controllers/admin/configs.js | 17 ++-- .../src/api/controllers/admin/templates.js | 51 ++---------- packages/worker/src/constants/index.js | 41 ++++++---- .../worker/src/constants/templates/base.html | 82 +++++++++++++++++++ .../src/constants/templates/footer.html | 48 ----------- .../src/constants/templates/header.html | 36 -------- .../worker/src/constants/templates/index.js | 60 ++++++++++++-- .../constants/templates/passwordRecovery.html | 2 +- packages/worker/src/utilities/email.js | 36 ++++++++ packages/worker/src/utilities/index.js | 9 ++ packages/worker/src/utilities/templates.js | 29 +++++++ 12 files changed, 251 insertions(+), 161 deletions(-) create mode 100644 packages/worker/src/constants/templates/base.html delete mode 100644 packages/worker/src/constants/templates/footer.html delete mode 100644 packages/worker/src/constants/templates/header.html create mode 100644 packages/worker/src/utilities/index.js create mode 100644 packages/worker/src/utilities/templates.js diff --git a/packages/worker/package.json b/packages/worker/package.json index fd43af7b0f..c81e99acf1 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -20,6 +20,7 @@ "license": "AGPL-3.0-or-later", "dependencies": { "@budibase/auth": "0.0.1", + "@budibase/string-templates": "^0.8.16", "@koa/router": "^8.0.0", "aws-sdk": "^2.811.0", "bcryptjs": "^2.4.3", diff --git a/packages/worker/src/api/controllers/admin/configs.js b/packages/worker/src/api/controllers/admin/configs.js index 67f3405fa4..df19dc9a56 100644 --- a/packages/worker/src/api/controllers/admin/configs.js +++ b/packages/worker/src/api/controllers/admin/configs.js @@ -1,6 +1,10 @@ const CouchDB = require("../../../db") -const authPkg = require("@budibase/auth") -const { utils, StaticDatabases } = authPkg +const { + generateConfigID, + StaticDatabases, + getConfigParams, + determineScopedConfig, +} = require("@budibase/auth").db const GLOBAL_DB = StaticDatabases.GLOBAL.name @@ -11,7 +15,7 @@ exports.save = async function(ctx) { // Config does not exist yet if (!configDoc._id) { - configDoc._id = utils.generateConfigID({ + configDoc._id = generateConfigID({ type, group, user, @@ -33,12 +37,11 @@ exports.save = async function(ctx) { exports.fetch = async function(ctx) { const db = new CouchDB(GLOBAL_DB) const response = await db.allDocs( - utils.getConfigParams(undefined, { + getConfigParams(undefined, { include_docs: true, }) ) - const groups = response.rows.map(row => row.doc) - ctx.body = groups + ctx.body = response.rows.map(row => row.doc) } /** @@ -60,7 +63,7 @@ exports.find = async function(ctx) { try { // Find the config with the most granular scope based on context - const scopedConfig = await authPkg.db.determineScopedConfig(db, { + const scopedConfig = await determineScopedConfig(db, { type: ctx.params.type, user: userId, group, diff --git a/packages/worker/src/api/controllers/admin/templates.js b/packages/worker/src/api/controllers/admin/templates.js index 0314ca6099..f01f8e2176 100644 --- a/packages/worker/src/api/controllers/admin/templates.js +++ b/packages/worker/src/api/controllers/admin/templates.js @@ -1,59 +1,17 @@ const { generateTemplateID, - getTemplateParams, StaticDatabases, } = require("@budibase/auth").db const { CouchDB } = require("../../../db") const { - TemplatePurposePretty, - TemplateTypes, - EmailTemplatePurpose, - TemplatePurpose, + TemplateMetadata, + TemplateBindings, } = require("../../../constants") -const { getTemplateByPurpose } = require("../../../constants/templates") +const { getTemplates } = require("../../../constants/templates") const GLOBAL_DB = StaticDatabases.GLOBAL.name const GLOBAL_OWNER = "global" -function addBaseTemplates(templates, type = null) { - let purposeList - switch (type) { - case TemplateTypes.EMAIL: - purposeList = Object.values(EmailTemplatePurpose) - break - default: - purposeList = Object.values(TemplatePurpose) - break - } - for (let purpose of purposeList) { - // check if a template exists already for purpose - if (templates.find(template => template.purpose === purpose)) { - continue - } - templates.push(getTemplateByPurpose(purpose)) - } - return templates -} - -async function getTemplates({ ownerId, type, id } = {}) { - const db = new CouchDB(GLOBAL_DB) - const response = await db.allDocs( - getTemplateParams(ownerId, id, { - include_docs: true, - }) - ) - let templates = response.rows.map(row => row.doc) - // should only be one template with ID - if (id) { - return templates[0] - } - if (type) { - templates = templates.filter(template => template.type === type) - } - - return addBaseTemplates(templates, type) -} - exports.save = async ctx => { const db = new CouchDB(GLOBAL_DB) const type = ctx.params.type @@ -77,7 +35,8 @@ exports.save = async ctx => { exports.definitions = async ctx => { ctx.body = { - purpose: TemplatePurposePretty, + purpose: TemplateMetadata, + bindings: Object.values(TemplateBindings), } } diff --git a/packages/worker/src/constants/index.js b/packages/worker/src/constants/index.js index 44ca57ea17..bb002bbd6f 100644 --- a/packages/worker/src/constants/index.js +++ b/packages/worker/src/constants/index.js @@ -1,3 +1,6 @@ +exports.LOGO_URL = + "https://d33wubrfki0l68.cloudfront.net/aac32159d7207b5085e74a7ef67afbb7027786c5/2b1fd/img/logo/bb-emblem.svg" + exports.UserStatus = { ACTIVE: "active", INACTIVE: "inactive", @@ -19,39 +22,48 @@ const TemplateTypes = { } const EmailTemplatePurpose = { - HEADER: "header", - FOOTER: "footer", + BASE: "base", STYLES: "styles", PASSWORD_RECOVERY: "password_recovery", INVITATION: "invitation", CUSTOM: "custom", } -const TemplatePurposePretty = { +const TemplateBindings = { + URL: "url", + COMPANY: "company", + LOGO_URL: "logoUrl", + STYLES: "styles", + BODY: "body", + REGISTRATION_URL: "registrationUrl", + EMAIL: "email", + RESET_URL: "resetUrl", + USER: "user", +} + +const TemplateMetadata = { [TemplateTypes.EMAIL]: [ { name: "Styling", - value: EmailTemplatePurpose.STYLES, + purpose: EmailTemplatePurpose.STYLES, + bindings: ["url", "company", "companyUrl", "styles", "body"] }, { - name: "Header", - value: EmailTemplatePurpose.HEADER, - }, - { - name: "Footer", - value: EmailTemplatePurpose.FOOTER, + name: "Base Format", + purpose: EmailTemplatePurpose.BASE, + bindings: ["company", "registrationUrl"] }, { name: "Password Recovery", - value: EmailTemplatePurpose.PASSWORD_RECOVERY, + purpose: EmailTemplatePurpose.PASSWORD_RECOVERY, }, { name: "New User Invitation", - value: EmailTemplatePurpose.INVITATION, + purpose: EmailTemplatePurpose.INVITATION, }, { name: "Custom", - value: EmailTemplatePurpose.CUSTOM, + purpose: EmailTemplatePurpose.CUSTOM, }, ], } @@ -62,4 +74,5 @@ exports.TemplatePurpose = { } exports.TemplateTypes = TemplateTypes exports.EmailTemplatePurpose = EmailTemplatePurpose -exports.TemplatePurposePretty = TemplatePurposePretty +exports.TemplateMetadata = TemplateMetadata +exports.TemplateBindings = TemplateBindings diff --git a/packages/worker/src/constants/templates/base.html b/packages/worker/src/constants/templates/base.html new file mode 100644 index 0000000000..f728404be8 --- /dev/null +++ b/packages/worker/src/constants/templates/base.html @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ \ No newline at end of file diff --git a/packages/worker/src/constants/templates/footer.html b/packages/worker/src/constants/templates/footer.html deleted file mode 100644 index 693fd3c0c0..0000000000 --- a/packages/worker/src/constants/templates/footer.html +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - -
\ No newline at end of file diff --git a/packages/worker/src/constants/templates/header.html b/packages/worker/src/constants/templates/header.html deleted file mode 100644 index 7709bd30a8..0000000000 --- a/packages/worker/src/constants/templates/header.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - -
- \ No newline at end of file diff --git a/packages/worker/src/constants/templates/index.js b/packages/worker/src/constants/templates/index.js index 53db5f2b42..2878a3a4e9 100644 --- a/packages/worker/src/constants/templates/index.js +++ b/packages/worker/src/constants/templates/index.js @@ -1,6 +1,11 @@ const { readStaticFile } = require("../../utilities/fileSystem") -const { EmailTemplatePurpose } = require("../index") +const { EmailTemplatePurpose, TemplateTypes, TemplatePurpose } = require("../index") const { join } = require("path") +const CouchDB = require("../../db") +const { + getTemplateParams, + StaticDatabases, +} = require("@budibase/auth").db const TEMPLATE_PATH = join(__dirname, "..", "constants", "templates") @@ -11,19 +16,56 @@ exports.EmailTemplates = { [EmailTemplatePurpose.INVITATION]: readStaticFile( join(TEMPLATE_PATH, "invitation.html") ), - [EmailTemplatePurpose.HEADER]: readStaticFile( - join(TEMPLATE_PATH, "header.html") - ), - [EmailTemplatePurpose.FOOTER]: readStaticFile( - join(TEMPLATE_PATH, "footer.html") + [EmailTemplatePurpose.BASE]: readStaticFile( + join(TEMPLATE_PATH, "base.html") ), [EmailTemplatePurpose.STYLES]: readStaticFile( join(TEMPLATE_PATH, "style.css") ), } -exports.getTemplateByPurpose = purpose => { - if (exports.EmailTemplates[purpose]) { - return exports.EmailTemplates[purpose] +exports.addBaseTemplates = (templates, type = null) => { + let purposeList + switch (type) { + case TemplateTypes.EMAIL: + purposeList = Object.values(EmailTemplatePurpose) + break + default: + purposeList = Object.values(TemplatePurpose) + break } + for (let purpose of purposeList) { + // check if a template exists already for purpose + if (templates.find(template => template.purpose === purpose)) { + continue + } + if (exports.EmailTemplates[purpose]) { + templates.push(exports.EmailTemplates[purpose]) + } + } + return templates } + +exports.getTemplates = async ({ ownerId, type, id } = {}) => { + const db = new CouchDB(StaticDatabases.GLOBAL.name) + const response = await db.allDocs( + getTemplateParams(ownerId, id, { + include_docs: true, + }) + ) + let templates = response.rows.map(row => row.doc) + // should only be one template with ID + if (id) { + return templates[0] + } + if (type) { + templates = templates.filter(template => template.type === type) + } + return exports.addBaseTemplates(templates, type) +} + +exports.getTemplateByPurpose = async (type, purpose) => { + const templates = await exports.getTemplates({ type }) + return templates.find(template => template.purpose === purpose) +} + diff --git a/packages/worker/src/constants/templates/passwordRecovery.html b/packages/worker/src/constants/templates/passwordRecovery.html index e6b179ec81..11f4eac1f4 100644 --- a/packages/worker/src/constants/templates/passwordRecovery.html +++ b/packages/worker/src/constants/templates/passwordRecovery.html @@ -6,7 +6,7 @@ Budibase Password reset

Please follow the below link to reset your password.

Reset password

-

This password reset was required for {{ user }} if you did not +

This password reset was required for {{ email }} if you did not request this then please contact your administrator.

diff --git a/packages/worker/src/utilities/email.js b/packages/worker/src/utilities/email.js index e69de29bb2..6cab9cc4db 100644 --- a/packages/worker/src/utilities/email.js +++ b/packages/worker/src/utilities/email.js @@ -0,0 +1,36 @@ +const { EmailTemplatePurpose, TemplateTypes } = require("../constants") +const { getTemplateByPurpose } = require("../constants/templates") +const { processString } = require("@budibase/string-templates") +const { getSettingsTemplateContext } = require("./templates") + +const TYPE = TemplateTypes.EMAIL + +const FULL_EMAIL_PURPOSES = [EmailTemplatePurpose.INVITATION, EmailTemplatePurpose.PASSWORD_RECOVERY] + +exports.buildEmail = async (email, user, purpose) => { + // this isn't a full email + if (FULL_EMAIL_PURPOSES.indexOf(purpose) === -1) { + throw `Unable to build an email of type ${purpose}` + } + let [base, styles, body] = await Promise.all([ + getTemplateByPurpose(TYPE, EmailTemplatePurpose.BASE), + getTemplateByPurpose(TYPE, EmailTemplatePurpose.STYLES), + getTemplateByPurpose(TYPE, purpose), + ]) + + // TODO: need to extend the context as much as possible + const context = { + ...await getSettingsTemplateContext(), + email, + user + } + + body = await processString(body, context) + styles = await processString(styles, context) + // this should now be the complete email HTML + return processString(base, { + ...context, + styles, + body, + }) +} \ No newline at end of file diff --git a/packages/worker/src/utilities/index.js b/packages/worker/src/utilities/index.js new file mode 100644 index 0000000000..b402a82cf3 --- /dev/null +++ b/packages/worker/src/utilities/index.js @@ -0,0 +1,9 @@ +/** + * Makes sure that a URL has the correct number of slashes, while maintaining the + * http(s):// double slashes. + * @param {string} url The URL to test and remove any extra double slashes. + * @return {string} The updated url. + */ +exports.checkSlashesInUrl = url => { + return url.replace(/(https?:\/\/)|(\/)+/g, "$1$2") +} diff --git a/packages/worker/src/utilities/templates.js b/packages/worker/src/utilities/templates.js new file mode 100644 index 0000000000..064776647d --- /dev/null +++ b/packages/worker/src/utilities/templates.js @@ -0,0 +1,29 @@ +const CouchDB = require("../../../db") +const { getConfigParams, StaticDatabases } = require("@budibase/auth").db +const { Configs, TemplateBindings, LOGO_URL } = require("../constants") +const { checkSlashesInUrl } = require("./index") +const env = require("../environment") + +const LOCAL_URL = `http://localhost:${env.PORT}` +const BASE_COMPANY = "Budibase" + +exports.getSettingsTemplateContext = async () => { + const db = new CouchDB(StaticDatabases.GLOBAL.name) + const response = await db.allDocs( + getConfigParams(Configs.SETTINGS, { + include_docs: true, + }) + ) + let settings = response.rows.map(row => row.doc)[0] || {} + if (!settings.url) { + settings.url = LOCAL_URL + } + // TODO: need to fully spec out the context + return { + [TemplateBindings.LOGO_URL]: settings.logoUrl || LOGO_URL, + [TemplateBindings.URL]: settings.url, + [TemplateBindings.REGISTRATION_URL]: checkSlashesInUrl(`${settings.url}/registration`), + [TemplateBindings.RESET_URL]: checkSlashesInUrl(`${settings.url}/reset`), + [TemplateBindings.COMPANY]: settings.company || BASE_COMPANY, + } +} \ No newline at end of file From 163035cac718eedc5467db28fda29fa1bfac76ba Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 22 Apr 2021 17:58:14 +0100 Subject: [PATCH 17/29] Formatting. --- .../src/api/controllers/admin/templates.js | 10 ++-------- packages/worker/src/constants/index.js | 4 ++-- packages/worker/src/constants/templates/index.js | 16 +++++++--------- packages/worker/src/utilities/email.js | 11 +++++++---- packages/worker/src/utilities/templates.js | 6 ++++-- 5 files changed, 22 insertions(+), 25 deletions(-) diff --git a/packages/worker/src/api/controllers/admin/templates.js b/packages/worker/src/api/controllers/admin/templates.js index f01f8e2176..8d4065b77d 100644 --- a/packages/worker/src/api/controllers/admin/templates.js +++ b/packages/worker/src/api/controllers/admin/templates.js @@ -1,12 +1,6 @@ -const { - generateTemplateID, - StaticDatabases, -} = require("@budibase/auth").db +const { generateTemplateID, StaticDatabases } = require("@budibase/auth").db const { CouchDB } = require("../../../db") -const { - TemplateMetadata, - TemplateBindings, -} = require("../../../constants") +const { TemplateMetadata, TemplateBindings } = require("../../../constants") const { getTemplates } = require("../../../constants/templates") const GLOBAL_DB = StaticDatabases.GLOBAL.name diff --git a/packages/worker/src/constants/index.js b/packages/worker/src/constants/index.js index bb002bbd6f..7406db0bdd 100644 --- a/packages/worker/src/constants/index.js +++ b/packages/worker/src/constants/index.js @@ -46,12 +46,12 @@ const TemplateMetadata = { { name: "Styling", purpose: EmailTemplatePurpose.STYLES, - bindings: ["url", "company", "companyUrl", "styles", "body"] + bindings: ["url", "company", "companyUrl", "styles", "body"], }, { name: "Base Format", purpose: EmailTemplatePurpose.BASE, - bindings: ["company", "registrationUrl"] + bindings: ["company", "registrationUrl"], }, { name: "Password Recovery", diff --git a/packages/worker/src/constants/templates/index.js b/packages/worker/src/constants/templates/index.js index 2878a3a4e9..16ec84a379 100644 --- a/packages/worker/src/constants/templates/index.js +++ b/packages/worker/src/constants/templates/index.js @@ -1,11 +1,12 @@ const { readStaticFile } = require("../../utilities/fileSystem") -const { EmailTemplatePurpose, TemplateTypes, TemplatePurpose } = require("../index") +const { + EmailTemplatePurpose, + TemplateTypes, + TemplatePurpose, +} = require("../index") const { join } = require("path") const CouchDB = require("../../db") -const { - getTemplateParams, - StaticDatabases, -} = require("@budibase/auth").db +const { getTemplateParams, StaticDatabases } = require("@budibase/auth").db const TEMPLATE_PATH = join(__dirname, "..", "constants", "templates") @@ -16,9 +17,7 @@ exports.EmailTemplates = { [EmailTemplatePurpose.INVITATION]: readStaticFile( join(TEMPLATE_PATH, "invitation.html") ), - [EmailTemplatePurpose.BASE]: readStaticFile( - join(TEMPLATE_PATH, "base.html") - ), + [EmailTemplatePurpose.BASE]: readStaticFile(join(TEMPLATE_PATH, "base.html")), [EmailTemplatePurpose.STYLES]: readStaticFile( join(TEMPLATE_PATH, "style.css") ), @@ -68,4 +67,3 @@ exports.getTemplateByPurpose = async (type, purpose) => { const templates = await exports.getTemplates({ type }) return templates.find(template => template.purpose === purpose) } - diff --git a/packages/worker/src/utilities/email.js b/packages/worker/src/utilities/email.js index 6cab9cc4db..83fb1ff8b6 100644 --- a/packages/worker/src/utilities/email.js +++ b/packages/worker/src/utilities/email.js @@ -5,7 +5,10 @@ const { getSettingsTemplateContext } = require("./templates") const TYPE = TemplateTypes.EMAIL -const FULL_EMAIL_PURPOSES = [EmailTemplatePurpose.INVITATION, EmailTemplatePurpose.PASSWORD_RECOVERY] +const FULL_EMAIL_PURPOSES = [ + EmailTemplatePurpose.INVITATION, + EmailTemplatePurpose.PASSWORD_RECOVERY, +] exports.buildEmail = async (email, user, purpose) => { // this isn't a full email @@ -20,9 +23,9 @@ exports.buildEmail = async (email, user, purpose) => { // TODO: need to extend the context as much as possible const context = { - ...await getSettingsTemplateContext(), + ...(await getSettingsTemplateContext()), email, - user + user, } body = await processString(body, context) @@ -33,4 +36,4 @@ exports.buildEmail = async (email, user, purpose) => { styles, body, }) -} \ No newline at end of file +} diff --git a/packages/worker/src/utilities/templates.js b/packages/worker/src/utilities/templates.js index 064776647d..9a3e2d291b 100644 --- a/packages/worker/src/utilities/templates.js +++ b/packages/worker/src/utilities/templates.js @@ -22,8 +22,10 @@ exports.getSettingsTemplateContext = async () => { return { [TemplateBindings.LOGO_URL]: settings.logoUrl || LOGO_URL, [TemplateBindings.URL]: settings.url, - [TemplateBindings.REGISTRATION_URL]: checkSlashesInUrl(`${settings.url}/registration`), + [TemplateBindings.REGISTRATION_URL]: checkSlashesInUrl( + `${settings.url}/registration` + ), [TemplateBindings.RESET_URL]: checkSlashesInUrl(`${settings.url}/reset`), [TemplateBindings.COMPANY]: settings.company || BASE_COMPANY, } -} \ No newline at end of file +} From f6e25c3792d9f29d833f1b976411b784a074a82a Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 23 Apr 2021 13:10:37 +0100 Subject: [PATCH 18/29] putting together the bulk of the email sending/config options. --- packages/worker/package.json | 1 + .../controllers/admin}/email.js | 31 +- .../worker/src/api/routes/admin/configs.js | 43 +- packages/worker/src/api/routes/admin/email.js | 21 + packages/worker/yarn.lock | 1266 ++++++++++++++++- 5 files changed, 1350 insertions(+), 12 deletions(-) rename packages/worker/src/{utilities => api/controllers/admin}/email.js (51%) create mode 100644 packages/worker/src/api/routes/admin/email.js diff --git a/packages/worker/package.json b/packages/worker/package.json index c81e99acf1..b99b79ecc5 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -36,6 +36,7 @@ "koa-session": "^5.12.0", "koa-static": "^5.0.0", "node-fetch": "^2.6.1", + "nodemailer": "^6.5.0", "passport-google-oauth": "^2.0.0", "passport-jwt": "^4.0.0", "passport-local": "^1.0.0", diff --git a/packages/worker/src/utilities/email.js b/packages/worker/src/api/controllers/admin/email.js similarity index 51% rename from packages/worker/src/utilities/email.js rename to packages/worker/src/api/controllers/admin/email.js index 83fb1ff8b6..6c9343ea5a 100644 --- a/packages/worker/src/utilities/email.js +++ b/packages/worker/src/api/controllers/admin/email.js @@ -1,8 +1,12 @@ -const { EmailTemplatePurpose, TemplateTypes } = require("../constants") -const { getTemplateByPurpose } = require("../constants/templates") +const CouchDB = require("../../../db") +const { StaticDatabases, determineScopedConfig } = require("@budibase/auth").db +const { EmailTemplatePurpose, TemplateTypes, Configs } = require("../../../constants") +const { getTemplateByPurpose } = require("../../../constants/templates") +const { getSettingsTemplateContext } = require("../../../utilities/templates") const { processString } = require("@budibase/string-templates") -const { getSettingsTemplateContext } = require("./templates") +const nodemailer = require("nodemailer") +const GLOBAL_DB = StaticDatabases.GLOBAL.name const TYPE = TemplateTypes.EMAIL const FULL_EMAIL_PURPOSES = [ @@ -10,6 +14,14 @@ const FULL_EMAIL_PURPOSES = [ EmailTemplatePurpose.PASSWORD_RECOVERY, ] +function createSMTPTransport(config) { + const transport = nodemailer.createTransport({ + port: config.port, + host: config.host, + + }) +} + exports.buildEmail = async (email, user, purpose) => { // this isn't a full email if (FULL_EMAIL_PURPOSES.indexOf(purpose) === -1) { @@ -37,3 +49,16 @@ exports.buildEmail = async (email, user, purpose) => { body, }) } + +exports.sendEmail = async ctx => { + const { groupId, email, purpose } = ctx.request.body + const db = new CouchDB(GLOBAL_DB) + const params = {} + if (groupId) { + params.group = groupId + } + params.type = Configs.SMTP + const config = await determineScopedConfig(db, params) + const transport = createSMTPTransport(config) +} + diff --git a/packages/worker/src/api/routes/admin/configs.js b/packages/worker/src/api/routes/admin/configs.js index c6ac04619e..d64900cece 100644 --- a/packages/worker/src/api/routes/admin/configs.js +++ b/packages/worker/src/api/routes/admin/configs.js @@ -6,11 +6,52 @@ const { Configs } = require("../../../constants") const router = Router() +function smtpValidation() { + return Joi.object({ + port: Joi.number().required(), + host: Joi.string().required(), + from: Joi.string().email().required(), + secure: Joi.boolean().optional(), + selfSigned: Joi.boolean().optional(), + auth: Joi.object({ + type: Joi.string().valid("login", "oauth2", null), + user: Joi.string().required(), + pass: Joi.string().valid("", null), + }).optional(), + }).unknown(true) +} + +function settingValidation() { + return Joi.object({ + url: Joi.string().valid("", null), + logoUrl: Joi.string().valid("", null), + company: Joi.string().required(), + }).unknown(true) +} + +function googleValidation() { + return Joi.object({ + clientID: Joi.string().required(), + clientSecret: Joi.string().required(), + callbackURL: Joi.string().required(), + }).unknown(true) +} + function buildConfigSaveValidation() { // prettier-ignore return joiValidator.body(Joi.object({ type: Joi.string().valid(...Object.values(Configs)).required(), - }).required().unknown(true)) + config: Joi.alternatives() + .conditional("type", { + switch: [ + { is: Configs.SMTP, then: smtpValidation() }, + { is: Configs.SETTINGS, then: settingValidation() }, + { is: Configs.ACCOUNT, then: Joi.object().unknown(true) }, + { is: Configs.GOOGLE, then: googleValidation() } + ], + }), + }), + ) } router diff --git a/packages/worker/src/api/routes/admin/email.js b/packages/worker/src/api/routes/admin/email.js new file mode 100644 index 0000000000..4a122f4791 --- /dev/null +++ b/packages/worker/src/api/routes/admin/email.js @@ -0,0 +1,21 @@ +const Router = require("@koa/router") +const controller = require("../../controllers/admin/email") +const { EmailTemplatePurpose } = require("../../../constants") +const joiValidator = require("../../../middleware/joi-validator") +const Joi = require("joi") + +const router = Router() + +function buildEmailSendValidation() { + // prettier-ignore + return joiValidator.body(Joi.object({ + email: Joi.string().email(), + groupId: Joi.string().allow("", null), + purpose: Joi.string().allow(...Object.values(EmailTemplatePurpose)), + }).required().unknown(true)) +} + +router + .post("/api/admin/email/send", buildEmailSendValidation(), controller.sendEmail) + +module.exports = router diff --git a/packages/worker/yarn.lock b/packages/worker/yarn.lock index 2545067d98..4af1c1d9dd 100644 --- a/packages/worker/yarn.lock +++ b/packages/worker/yarn.lock @@ -2,6 +2,49 @@ # yarn lockfile v1 +"@budibase/handlebars-helpers@^0.11.3": + version "0.11.3" + resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.11.3.tgz#b6e5c91b83e8906e7d7ff10ddde277a3d561016e" + integrity sha512-MS1ptZEYq8o9J3tNLM7cZ2RGSSJIer4GiMIUHtbBI3sC9UKqZebao1JYNfmZKpNjntuqhZKgjqc5GfnVIEjsYQ== + dependencies: + arr-flatten "^1.1.0" + array-sort "^0.1.4" + define-property "^1.0.0" + extend-shallow "^3.0.2" + "falsey" "^0.3.2" + for-in "^1.0.2" + for-own "^1.0.0" + get-object "^0.2.0" + get-value "^2.0.6" + handlebars "^4.0.11" + handlebars-utils "^1.0.6" + has-value "^1.0.0" + helper-date "^1.0.1" + helper-markdown "^1.0.0" + helper-md "^0.2.2" + html-tag "^2.0.0" + is-even "^1.0.0" + is-glob "^4.0.0" + is-number "^4.0.0" + kind-of "^6.0.0" + logging-helpers "^1.0.0" + micromatch "^3.1.4" + relative "^3.0.2" + striptags "^3.1.0" + to-gfm-code-block "^0.1.1" + year "^0.2.1" + +"@budibase/string-templates@^0.8.16": + version "0.8.17" + resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.8.17.tgz#107937d1a0d1249fc65b61cc050ee3d54e744b65" + integrity sha512-FTjzF4HdfXUuyHtbJ6jH+xhp+dzYpvwOvvbG6yXnV0WZg3Xj8svm6GqKPkwODyMYqtLVzEoExZU7JaM0ZX0iqg== + dependencies: + "@budibase/handlebars-helpers" "^0.11.3" + dayjs "^1.10.4" + handlebars "^4.7.6" + handlebars-utils "^1.0.6" + lodash "^4.17.20" + "@hapi/bourne@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-2.0.0.tgz#5bb2193eb685c0007540ca61d166d4e1edaf918d" @@ -190,6 +233,186 @@ ansi-align@^3.0.0: dependencies: string-width "^3.0.0" +ansi-bgblack@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bgblack/-/ansi-bgblack-0.1.1.tgz#a68ba5007887701b6aafbe3fa0dadfdfa8ee3ca2" + integrity sha1-poulAHiHcBtqr74/oNrf36juPKI= + dependencies: + ansi-wrap "0.1.0" + +ansi-bgblue@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bgblue/-/ansi-bgblue-0.1.1.tgz#67bdc04edc9b9b5278969da196dea3d75c8c3613" + integrity sha1-Z73ATtybm1J4lp2hlt6j11yMNhM= + dependencies: + ansi-wrap "0.1.0" + +ansi-bgcyan@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bgcyan/-/ansi-bgcyan-0.1.1.tgz#58489425600bde9f5507068dd969ebfdb50fe768" + integrity sha1-WEiUJWAL3p9VBwaN2Wnr/bUP52g= + dependencies: + ansi-wrap "0.1.0" + +ansi-bggreen@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bggreen/-/ansi-bggreen-0.1.1.tgz#4e3191248529943f4321e96bf131d1c13816af49" + integrity sha1-TjGRJIUplD9DIelr8THRwTgWr0k= + dependencies: + ansi-wrap "0.1.0" + +ansi-bgmagenta@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bgmagenta/-/ansi-bgmagenta-0.1.1.tgz#9b28432c076eaa999418672a3efbe19391c2c7a1" + integrity sha1-myhDLAduqpmUGGcqPvvhk5HCx6E= + dependencies: + ansi-wrap "0.1.0" + +ansi-bgred@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bgred/-/ansi-bgred-0.1.1.tgz#a76f92838382ba43290a6c1778424f984d6f1041" + integrity sha1-p2+Sg4OCukMpCmwXeEJPmE1vEEE= + dependencies: + ansi-wrap "0.1.0" + +ansi-bgwhite@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bgwhite/-/ansi-bgwhite-0.1.1.tgz#6504651377a58a6ececd0331994e480258e11ba8" + integrity sha1-ZQRlE3elim7OzQMxmU5IAljhG6g= + dependencies: + ansi-wrap "0.1.0" + +ansi-bgyellow@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bgyellow/-/ansi-bgyellow-0.1.1.tgz#c3fe2eb08cd476648029e6874d15a0b38f61d44f" + integrity sha1-w/4usIzUdmSAKeaHTRWgs49h1E8= + dependencies: + ansi-wrap "0.1.0" + +ansi-black@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-black/-/ansi-black-0.1.1.tgz#f6185e889360b2545a1ec50c0bf063fc43032453" + integrity sha1-9hheiJNgslRaHsUMC/Bj/EMDJFM= + dependencies: + ansi-wrap "0.1.0" + +ansi-blue@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-blue/-/ansi-blue-0.1.1.tgz#15b804990e92fc9ca8c5476ce8f699777c21edbf" + integrity sha1-FbgEmQ6S/JyoxUds6PaZd3wh7b8= + dependencies: + ansi-wrap "0.1.0" + +ansi-bold@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-bold/-/ansi-bold-0.1.1.tgz#3e63950af5acc2ae2e670e6f67deb115d1a5f505" + integrity sha1-PmOVCvWswq4uZw5vZ96xFdGl9QU= + dependencies: + ansi-wrap "0.1.0" + +ansi-colors@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-0.2.0.tgz#72c31de2a0d9a2ccd0cac30cc9823eeb2f6434b5" + integrity sha1-csMd4qDZoszQysMMyYI+6y9kNLU= + dependencies: + ansi-bgblack "^0.1.1" + ansi-bgblue "^0.1.1" + ansi-bgcyan "^0.1.1" + ansi-bggreen "^0.1.1" + ansi-bgmagenta "^0.1.1" + ansi-bgred "^0.1.1" + ansi-bgwhite "^0.1.1" + ansi-bgyellow "^0.1.1" + ansi-black "^0.1.1" + ansi-blue "^0.1.1" + ansi-bold "^0.1.1" + ansi-cyan "^0.1.1" + ansi-dim "^0.1.1" + ansi-gray "^0.1.1" + ansi-green "^0.1.1" + ansi-grey "^0.1.1" + ansi-hidden "^0.1.1" + ansi-inverse "^0.1.1" + ansi-italic "^0.1.1" + ansi-magenta "^0.1.1" + ansi-red "^0.1.1" + ansi-reset "^0.1.1" + ansi-strikethrough "^0.1.1" + ansi-underline "^0.1.1" + ansi-white "^0.1.1" + ansi-yellow "^0.1.1" + lazy-cache "^2.0.1" + +ansi-cyan@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" + integrity sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM= + dependencies: + ansi-wrap "0.1.0" + +ansi-dim@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-dim/-/ansi-dim-0.1.1.tgz#40de4c603aa8086d8e7a86b8ff998d5c36eefd6c" + integrity sha1-QN5MYDqoCG2Oeoa4/5mNXDbu/Ww= + dependencies: + ansi-wrap "0.1.0" + +ansi-gray@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" + integrity sha1-KWLPVOyXksSFEKPetSRDaGHvclE= + dependencies: + ansi-wrap "0.1.0" + +ansi-green@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-green/-/ansi-green-0.1.1.tgz#8a5d9a979e458d57c40e33580b37390b8e10d0f7" + integrity sha1-il2al55FjVfEDjNYCzc5C44Q0Pc= + dependencies: + ansi-wrap "0.1.0" + +ansi-grey@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-grey/-/ansi-grey-0.1.1.tgz#59d98b6ac2ba19f8a51798e9853fba78339a33c1" + integrity sha1-WdmLasK6GfilF5jphT+6eDOaM8E= + dependencies: + ansi-wrap "0.1.0" + +ansi-hidden@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-hidden/-/ansi-hidden-0.1.1.tgz#ed6a4c498d2bb7cbb289dbf2a8d1dcc8567fae0f" + integrity sha1-7WpMSY0rt8uyidvyqNHcyFZ/rg8= + dependencies: + ansi-wrap "0.1.0" + +ansi-inverse@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-inverse/-/ansi-inverse-0.1.1.tgz#b6af45826fe826bfb528a6c79885794355ccd269" + integrity sha1-tq9Fgm/oJr+1KKbHmIV5Q1XM0mk= + dependencies: + ansi-wrap "0.1.0" + +ansi-italic@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-italic/-/ansi-italic-0.1.1.tgz#104743463f625c142a036739cf85eda688986f23" + integrity sha1-EEdDRj9iXBQqA2c5z4XtpoiYbyM= + dependencies: + ansi-wrap "0.1.0" + +ansi-magenta@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-magenta/-/ansi-magenta-0.1.1.tgz#063b5ba16fb3f23e1cfda2b07c0a89de11e430ae" + integrity sha1-BjtboW+z8j4c/aKwfAqJ3hHkMK4= + dependencies: + ansi-wrap "0.1.0" + +ansi-red@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-red/-/ansi-red-0.1.1.tgz#8c638f9d1080800a353c9c28c8a81ca4705d946c" + integrity sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw= + dependencies: + ansi-wrap "0.1.0" + ansi-regex@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" @@ -200,6 +423,20 @@ ansi-regex@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== +ansi-reset@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-reset/-/ansi-reset-0.1.1.tgz#e7e71292c3c7ddcd4d62ef4a6c7c05980911c3b7" + integrity sha1-5+cSksPH3c1NYu9KbHwFmAkRw7c= + dependencies: + ansi-wrap "0.1.0" + +ansi-strikethrough@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-strikethrough/-/ansi-strikethrough-0.1.1.tgz#d84877140b2cff07d1c93ebce69904f68885e568" + integrity sha1-2Eh3FAss/wfRyT685pkE9oiF5Wg= + dependencies: + ansi-wrap "0.1.0" + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -214,6 +451,32 @@ ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-underline@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-underline/-/ansi-underline-0.1.1.tgz#dfc920f4c97b5977ea162df8ffb988308aaa71a4" + integrity sha1-38kg9Ml7WXfqFi34/7mIMIqqcaQ= + dependencies: + ansi-wrap "0.1.0" + +ansi-white@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-white/-/ansi-white-0.1.1.tgz#9c77b7c193c5ee992e6011d36ec4c921b4578944" + integrity sha1-nHe3wZPF7pkuYBHTbsTJIbRXiUQ= + dependencies: + ansi-wrap "0.1.0" + +ansi-wrap@0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf" + integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768= + +ansi-yellow@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/ansi-yellow/-/ansi-yellow-0.1.1.tgz#cb9356f2f46c732f0e3199e6102955a77da83c1d" + integrity sha1-y5NW8vRscy8OMZnmEClVp32oPB0= + dependencies: + ansi-wrap "0.1.0" + any-promise@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" @@ -227,6 +490,13 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" +argparse@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + args@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/args/-/args-5.0.1.tgz#4bf298df90a4799a09521362c579278cc2fdd761" @@ -242,6 +512,40 @@ argsarray@0.0.1: resolved "https://registry.yarnpkg.com/argsarray/-/argsarray-0.0.1.tgz#6e7207b4ecdb39b0af88303fa5ae22bda8df61cb" integrity sha1-bnIHtOzbObCviDA/pa4ivajfYcs= +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-sort@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/array-sort/-/array-sort-0.1.4.tgz#662855eaeb671b4188df4451b2f24a0753992b23" + integrity sha512-BNcM+RXxndPxiZ2rd76k6nyQLRZr2/B/sdi8pQ+Joafr5AH279L40dfokSUTp8O+AaqYjXWhblBWa2st2nc4fQ== + dependencies: + default-compare "^1.0.0" + get-value "^2.0.6" + kind-of "^5.0.2" + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + ast-types@0.8.15: version "0.8.15" resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.8.15.tgz#8eef0827f04dff0ec8857ba925abe3fea6194e52" @@ -252,11 +556,23 @@ ast-types@0.9.6: resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9" integrity sha1-ECyenpAF0+fjgpvwxPok7oYu6bk= +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + atomic-sleep@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== +autolinker@~0.28.0: + version "0.28.1" + resolved "https://registry.yarnpkg.com/autolinker/-/autolinker-0.28.1.tgz#0652b491881879f0775dace0cdca3233942a4e47" + integrity sha1-BlK0kYgYefB3XazgzcoyM5QqTkc= + dependencies: + gulp-header "^1.7.1" + aws-sdk@^2.811.0: version "2.811.0" resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.811.0.tgz#a7e4040b2ee7d8b825b142ed5179d36dc3f315c4" @@ -297,6 +613,19 @@ base64url@3.x.x: resolved "https://registry.yarnpkg.com/base64url/-/base64url-3.0.1.tgz#6399d572e2bc3f90a9a8b22d5dbb0a32d33f788d" integrity sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A== +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + bcryptjs@^2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" @@ -329,6 +658,22 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -368,6 +713,21 @@ bytes@3.1.0, bytes@^3.0.0: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + cache-content-type@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-content-type/-/cache-content-type-1.0.1.tgz#035cde2b08ee2129f4a8315ea8f00a00dba1453c" @@ -462,6 +822,16 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + cli-boxes@^2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" @@ -494,6 +864,14 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + color-convert@^1.9.0: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" @@ -538,6 +916,11 @@ commoner@^0.10.1: q "^1.1.2" recast "^0.11.17" +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + compressible@^2.0.0: version "2.0.18" resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" @@ -550,6 +933,13 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= +concat-with-sourcemaps@*: + version "1.1.0" + resolved "https://registry.yarnpkg.com/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz#d4ea93f05ae25790951b99e7b3b09e3908a4082e" + integrity sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg== + dependencies: + source-map "^0.6.1" + configstore@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96" @@ -582,6 +972,11 @@ cookies@~0.8.0: depd "~2.0.0" keygrip "~1.1.0" +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + core-util-is@^1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -599,12 +994,24 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== +date.js@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/date.js/-/date.js-0.3.3.tgz#ef1e92332f507a638795dbb985e951882e50bbda" + integrity sha512-HgigOS3h3k6HnW011nAb43c5xx5rBXk8P2v/WIT9Zv4koIaVXiH2BURguI78VVp+5Qc076T7OR378JViCnZtBw== + dependencies: + debug "~3.1.0" + dateformat@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -debug@^2.2.0: +dayjs@^1.10.4: + version "1.10.4" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.10.4.tgz#8e544a9b8683f61783f570980a8a80eaf54ab1e2" + integrity sha512-RI/Hh4kqRc1UKLOAf/T5zdMMX5DQIlDxwUe3wSyMMnEbGunnpENCdbUgM+dW7kXidZqCttBrmw7BhN4TMddkCw== + +debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -632,6 +1039,11 @@ debug@~3.1.0: dependencies: ms "2.0.0" +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" @@ -656,6 +1068,13 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== +default-compare@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz#cb61131844ad84d84788fb68fd01681ca7781a2f" + integrity sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ== + dependencies: + kind-of "^5.0.2" + defer-to-connect@^1.0.1: version "1.1.3" resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" @@ -674,6 +1093,28 @@ deferred-leveldown@~5.3.0: abstract-leveldown "~6.2.1" inherits "^2.0.3" +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + defined@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" @@ -780,6 +1221,11 @@ end-stream@~0.1.0: dependencies: write-stream "~0.4.3" +ent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ent/-/ent-2.2.0.tgz#e964219325a21d05f44466a2f686ed6ce5f5dd1d" + integrity sha1-6WQhkyWiHQX0RGai9obtbOX13R0= + errno@~0.1.1: version "0.1.8" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.8.tgz#8bb3e9c7d463be4976ff888f76b4809ebc2e811f" @@ -787,6 +1233,11 @@ errno@~0.1.1: dependencies: prr "~1.0.1" +error-symbol@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/error-symbol/-/error-symbol-0.1.0.tgz#0a4dae37d600d15a29ba453d8ef920f1844333f6" + integrity sha1-Ck2uN9YA0VopukU9jvkg8YRDM/Y= + es3ify@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/es3ify/-/es3ify-0.1.4.tgz#ad9fa5df1ae34f3f31e1211b5818b2d51078dfd1" @@ -860,6 +1311,48 @@ events@1.1.1: resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + falafel@^1.0.1: version "1.2.0" resolved "https://registry.yarnpkg.com/falafel/-/falafel-1.2.0.tgz#c18d24ef5091174a497f318cd24b026a25cddab4" @@ -870,6 +1363,13 @@ falafel@^1.0.1: isarray "0.0.1" object-keys "^1.0.6" +"falsey@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/falsey/-/falsey-0.3.2.tgz#b21c90c5c34660fc192bf909575db95b6880d597" + integrity sha512-lxEuefF5MBIVDmE6XeqCdM4BWk1+vYmGZtkbKZ/VFcg6uBBw6fXNEbWmxCjDdQlFc9hy450nkiWwM3VAW6G1qg== + dependencies: + kind-of "^5.0.2" + fast-redact@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.0.0.tgz#ac2f9e36c9f4976f5db9fb18c6ffbaf308cf316d" @@ -894,6 +1394,16 @@ fetch-cookie@0.10.1: dependencies: tough-cookie "^2.3.3 || ^3.0.1 || ^4.0.0" +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -906,6 +1416,18 @@ flatstr@^1.0.12: resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.12.tgz#c2ba6a08173edbb6c9640e3055b95e287ceb5931" integrity sha512-4zPxDyhCyiN2wIAtSLI6gc82/EjqZc1onI4Mz/l0pWrAlsSfYH/2ZIcU+e3oA2wDwbzIWNKwa23F8rh6+DRWkw== +for-in@^1.0.1, for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +for-own@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/for-own/-/for-own-1.0.0.tgz#c63332f415cedc4b04dbfe70cf836494c53cb44b" + integrity sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs= + dependencies: + for-in "^1.0.1" + foreach@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" @@ -916,11 +1438,23 @@ formidable@^1.1.1: resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.2.tgz#bf69aea2972982675f00865342b982986f6b8dd9" integrity sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q== +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + fresh@~0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= +fs-exists-sync@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" + integrity sha1-mC1ok6+RjnLQjeyehnP/K1qNat0= + fsevents@~2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" @@ -931,6 +1465,14 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +get-object@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/get-object/-/get-object-0.2.0.tgz#d92ff7d5190c64530cda0543dac63a3d47fe8c0c" + integrity sha1-2S/31RkMZFMM2gVD2sY6PUf+jAw= + dependencies: + is-number "^2.0.2" + isobject "^0.2.0" + get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -945,6 +1487,11 @@ get-stream@^5.1.0: dependencies: pump "^3.0.0" +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + glob-parent@~5.1.0: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -1009,6 +1556,35 @@ graceful-fs@^4.1.2: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== +gulp-header@^1.7.1: + version "1.8.12" + resolved "https://registry.yarnpkg.com/gulp-header/-/gulp-header-1.8.12.tgz#ad306be0066599127281c4f8786660e705080a84" + integrity sha512-lh9HLdb53sC7XIZOYzTXM4lFuXElv3EVkSDhsd7DoJBj7hm+Ni7D3qYbb+Rr8DuM8nRanBvkVO9d7askreXGnQ== + dependencies: + concat-with-sourcemaps "*" + lodash.template "^4.4.0" + through2 "^2.0.0" + +handlebars-utils@^1.0.2, handlebars-utils@^1.0.4, handlebars-utils@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/handlebars-utils/-/handlebars-utils-1.0.6.tgz#cb9db43362479054782d86ffe10f47abc76357f9" + integrity sha512-d5mmoQXdeEqSKMtQQZ9WkiUcO1E3tPbWxluCK9hVgIDPzQa9WsKo3Lbe/sGflTe7TomHEeZaOgwIkyIr1kfzkw== + dependencies: + kind-of "^6.0.0" + typeof-article "^0.1.1" + +handlebars@^4.0.11, handlebars@^4.7.6: + version "4.7.7" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" + integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.0" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -1019,11 +1595,83 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + has-yarn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== +helper-date@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/helper-date/-/helper-date-1.0.1.tgz#12fedea3ad8e44a7ca4c4efb0ff4104a5120cffb" + integrity sha512-wU3VOwwTJvGr/w5rZr3cprPHO+hIhlblTJHD6aFBrKLuNbf4lAmkawd2iK3c6NbJEvY7HAmDpqjOFSI5/+Ey2w== + dependencies: + date.js "^0.3.1" + handlebars-utils "^1.0.4" + moment "^2.18.1" + +helper-markdown@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/helper-markdown/-/helper-markdown-1.0.0.tgz#ee7e9fc554675007d37eb90f7853b13ce74f3e10" + integrity sha512-AnDqMS4ejkQK0MXze7pA9TM3pu01ZY+XXsES6gEE0RmCGk5/NIfvTn0NmItfyDOjRAzyo9z6X7YHbHX4PzIvOA== + dependencies: + handlebars-utils "^1.0.2" + highlight.js "^9.12.0" + remarkable "^1.7.1" + +helper-md@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/helper-md/-/helper-md-0.2.2.tgz#c1f59d7e55bbae23362fd8a0e971607aec69d41f" + integrity sha1-wfWdflW7riM2L9ig6XFgeuxp1B8= + dependencies: + ent "^2.2.0" + extend-shallow "^2.0.1" + fs-exists-sync "^0.1.0" + remarkable "^1.6.2" + +highlight.js@^9.12.0: + version "9.18.5" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.5.tgz#d18a359867f378c138d6819edfc2a8acd5f29825" + integrity sha512-a5bFyofd/BHCX52/8i8uJkjr9DYwXIPnM/plwI6W7ezItLGqzt7X2G2nXuYSfsIJdkwwj/g9DG1LkcGJI/dDoA== + +html-tag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/html-tag/-/html-tag-2.0.0.tgz#36c3bc8d816fd30b570d5764a497a641640c2fed" + integrity sha512-XxzooSo6oBoxBEUazgjdXj7VwTn/iSTSZzTYKzYY6I916tkaYzypHxy+pbVU1h+0UQ9JlVf5XkNQyxOAiiQO1g== + dependencies: + is-self-closing "^1.0.1" + kind-of "^6.0.0" + http-assert@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/http-assert/-/http-assert-1.4.1.tgz#c5f725d677aa7e873ef736199b89686cceb37878" @@ -1132,7 +1780,12 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1: +info-symbol@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/info-symbol/-/info-symbol-0.1.0.tgz#27841d72867ddb4242cd612d79c10633881c6a78" + integrity sha1-J4QdcoZ920JCzWEtecEGM4gcang= + +inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.1, 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== @@ -1160,6 +1813,20 @@ inline-process-browser@^1.0.0: falafel "^1.0.1" through2 "^0.6.5" +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -1167,6 +1834,11 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -1179,6 +1851,57 @@ is-class-hotfix@~0.0.6: resolved "https://registry.yarnpkg.com/is-class-hotfix/-/is-class-hotfix-0.0.6.tgz#a527d31fb23279281dde5f385c77b5de70a72435" integrity sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ== +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-even@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-even/-/is-even-1.0.0.tgz#76b5055fbad8d294a86b6a949015e1c97b717c06" + integrity sha1-drUFX7rY0pSoa2qUkBXhyXtxfAY= + dependencies: + is-odd "^0.1.2" + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -1199,7 +1922,7 @@ is-generator-function@^1.0.7: resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.8.tgz#dfb5c2b120e02b0a8d9d2c6806cd5621aa922f7b" integrity sha512-2Omr/twNtufVZFr1GhxjOMFPAj2sjc/dKaIqBhvo4qciXfJmITGH6ZGd8eZYNHza8t1y0e01AuqRhJwfWp26WQ== -is-glob@^4.0.1, is-glob@~4.0.1: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== @@ -1219,6 +1942,25 @@ is-npm@^4.0.0: resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d" integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig== +is-number@^2.0.2: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" + integrity sha1-Afy7s5NGOlSPL0ZszhbezknbkI8= + dependencies: + kind-of "^3.0.2" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" + integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -1229,11 +1971,32 @@ is-obj@^2.0.0: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== +is-odd@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-0.1.2.tgz#bc573b5ce371ef2aad6e6f49799b72bef13978a7" + integrity sha1-vFc7XONx7yqtbm9JeZtyvvE5eKc= + dependencies: + is-number "^3.0.0" + is-path-inside@^3.0.1: version "3.0.3" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-self-closing@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-self-closing/-/is-self-closing-1.0.1.tgz#5f406b527c7b12610176320338af0fa3896416e4" + integrity sha512-E+60FomW7Blv5GXTlYee2KDrnG6srxF7Xt1SjrhWUGUEsTFIqY/nq2y3DaftCsgUMdh89V07IVfhY9KIJhLezg== + dependencies: + self-closing-tags "^1.0.1" + is-type-of@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/is-type-of/-/is-type-of-1.2.1.tgz#e263ec3857aceb4f28c47130ec78db09a920f8c5" @@ -1248,6 +2011,11 @@ is-typedarray@^1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + is-yarn-global@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" @@ -1258,11 +2026,28 @@ isarray@0.0.1: resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= -isarray@^1.0.0: +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +isobject@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-0.2.0.tgz#a3432192f39b910b5f02cc989487836ec70aa85e" + integrity sha1-o0MhkvObkQtfAsyYlIeDbscKqF4= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -1373,6 +2158,30 @@ keyv@^4.0.0: dependencies: json-buffer "3.0.1" +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.1.0, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0, kind-of@^5.0.2: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + koa-body@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/koa-body/-/koa-body-4.2.0.tgz#37229208b820761aca5822d14c5fc55cee31b26f" @@ -1495,6 +2304,13 @@ latest-version@^5.0.0: dependencies: package-json "^6.3.0" +lazy-cache@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264" + integrity sha1-uRkKT5EzVGlIQIWfio9whNiCImQ= + dependencies: + set-getter "^0.1.0" + level-codec@9.0.2, level-codec@^9.0.0: version "9.0.2" resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-9.0.2.tgz#fd60df8c64786a80d44e63423096ffead63d8cbc" @@ -1599,6 +2415,11 @@ lie@3.0.4: inline-process-browser "^1.0.0" unreachable-branch-transform "^0.3.0" +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= + lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" @@ -1634,6 +2455,55 @@ lodash.once@^4.0.0: resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= +lodash.template@^4.4.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" + integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.templatesettings "^4.0.0" + +lodash.templatesettings@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" + integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== + dependencies: + lodash._reinterpolate "^3.0.0" + +lodash@^4.17.20: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== + +log-ok@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/log-ok/-/log-ok-0.1.1.tgz#bea3dd36acd0b8a7240d78736b5b97c65444a334" + integrity sha1-vqPdNqzQuKckDXhza1uXxlREozQ= + dependencies: + ansi-green "^0.1.1" + success-symbol "^0.1.0" + +log-utils@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/log-utils/-/log-utils-0.2.1.tgz#a4c217a0dd9a50515d9b920206091ab3d4e031cf" + integrity sha1-pMIXoN2aUFFdm5ICBgkas9TgMc8= + dependencies: + ansi-colors "^0.2.0" + error-symbol "^0.1.0" + info-symbol "^0.1.0" + log-ok "^0.1.1" + success-symbol "^0.1.0" + time-stamp "^1.0.1" + warning-symbol "^0.1.0" + +logging-helpers@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/logging-helpers/-/logging-helpers-1.0.0.tgz#b5a37b32ad53eb0137c58c7898a47b175ddb7c36" + integrity sha512-qyIh2goLt1sOgQQrrIWuwkRjUx4NUcEqEGAcYqD8VOnOC6ItwkrVE8/tA4smGpjzyp4Svhc6RodDp9IO5ghpyA== + dependencies: + isobject "^3.0.0" + log-utils "^0.2.1" + lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" @@ -1656,6 +2526,18 @@ make-dir@^3.0.0: dependencies: semver "^6.0.0" +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -1678,6 +2560,25 @@ methods@^1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= +micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + mime-db@1.44.0: version "1.44.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" @@ -1717,6 +2618,14 @@ minimist@^1.2.0, minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + mkdirp@^0.5.0: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -1724,6 +2633,11 @@ mkdirp@^0.5.0: dependencies: minimist "^1.2.5" +moment@^2.18.1: + version "2.29.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3" + integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ== + mri@1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/mri/-/mri-1.1.4.tgz#7cb1dd1b9b40905f1fac053abe25b6720f44744a" @@ -1744,6 +2658,23 @@ ms@^2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + napi-macros@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" @@ -1754,6 +2685,11 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +neo-async@^2.6.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== + node-fetch@2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" @@ -1769,6 +2705,11 @@ node-gyp-build@~4.1.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.1.1.tgz#d7270b5d86717068d114cc57fff352f96d745feb" integrity sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ== +nodemailer@^6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.5.0.tgz#d12c28d8d48778918e25f1999d97910231b175d9" + integrity sha512-Tm4RPrrIZbnqDKAvX+/4M+zovEReiKlEXWDzG4iwtpL9X34MJY+D5LnQPH/+eghe8DLlAVshHAJZAZWBGhkguw== + nodemon@^2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.7.tgz#6f030a0a0ebe3ea1ba2a38f71bf9bab4841ced32" @@ -1812,11 +2753,34 @@ object-assign@^2.0.0: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-2.1.1.tgz#43c36e5d569ff8e4816c4efa8be02d26967c18aa" integrity sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo= +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + object-keys@^1.0.6: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + on-finished@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -1861,6 +2825,11 @@ parseurl@^1.3.2: resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + passport-google-oauth1@1.x.x: version "1.0.0" resolved "https://registry.yarnpkg.com/passport-google-oauth1/-/passport-google-oauth1-1.0.0.tgz#af74a803df51ec646f66a44d82282be6f108e0cc" @@ -1996,6 +2965,11 @@ pino@^6.0.0: quick-format-unescaped "^4.0.1" sonic-boom "^1.0.2" +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + pouchdb-adapter-leveldb-core@7.2.2: version "7.2.2" resolved "https://registry.yarnpkg.com/pouchdb-adapter-leveldb-core/-/pouchdb-adapter-leveldb-core-7.2.2.tgz#e0aa6a476e2607d7ae89f4a803c9fba6e6d05a8a" @@ -2144,6 +3118,11 @@ private@^0.1.6, private@~0.1.5: resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" @@ -2268,6 +3247,19 @@ readable-stream@~0.0.2: resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-0.0.4.tgz#f32d76e3fb863344a548d79923007173665b3b8d" integrity sha1-8y124/uGM0SlSNeZIwBxc2ZbO40= +readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + readdirp@~3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" @@ -2295,6 +3287,14 @@ recast@^0.11.17: private "~0.1.5" source-map "~0.5.0" +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + registry-auth-token@^4.0.0: version "4.2.1" resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" @@ -2309,6 +3309,31 @@ registry-url@^5.0.0: dependencies: rc "^1.2.8" +relative@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/relative/-/relative-3.0.2.tgz#0dcd8ec54a5d35a3c15e104503d65375b5a5367f" + integrity sha1-Dc2OxUpdNaPBXhBFA9ZTdbWlNn8= + dependencies: + isobject "^2.0.0" + +remarkable@^1.6.2, remarkable@^1.7.1: + version "1.7.4" + resolved "https://registry.yarnpkg.com/remarkable/-/remarkable-1.7.4.tgz#19073cb960398c87a7d6546eaa5e50d2022fcd00" + integrity sha512-e6NKUXgX95whv7IgddywbeN/ItCkWbISmc2DiqHJb0wTrqZIexqdco5b8Z3XZoo/48IdNVKM9ZCvTPJ4F5uvhg== + dependencies: + argparse "^1.0.10" + autolinker "~0.28.0" + +repeat-element@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" + integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + resolve-alpn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.0.0.tgz#745ad60b3d6aff4b4a48e01b8c0bdc70959e0e8c" @@ -2322,6 +3347,11 @@ resolve-path@^1.4.0: http-errors "~1.6.2" path-is-absolute "1.0.1" +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + responselike@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" @@ -2336,7 +3366,12 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" -safe-buffer@5.1.2, safe-buffer@~5.1.1: +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== @@ -2346,6 +3381,13 @@ safe-buffer@^5.0.1, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + "safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -2361,6 +3403,11 @@ sax@>=0.6.0: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +self-closing-tags@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/self-closing-tags/-/self-closing-tags-1.0.1.tgz#6c5fa497994bb826b484216916371accee490a5d" + integrity sha512-7t6hNbYMxM+VHXTgJmxwgZgLGktuXtVVD5AivWzNTdJBM4DBjnDKDzkf2SrNjihaArpeJYNjxkELBu1evI4lQA== + semver-diff@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b" @@ -2383,6 +3430,23 @@ server-destroy@^1.0.1: resolved "https://registry.yarnpkg.com/server-destroy/-/server-destroy-1.0.1.tgz#f13bf928e42b9c3e79383e61cc3998b5d14e6cdd" integrity sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0= +set-getter@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376" + integrity sha1-12nBgsnVpR9AkUXy+6guXoboA3Y= + dependencies: + to-object-path "^0.3.0" + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" @@ -2403,6 +3467,36 @@ signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + sonic-boom@^1.0.2: version "1.3.0" resolved "https://registry.yarnpkg.com/sonic-boom/-/sonic-boom-1.3.0.tgz#5c77c846ce6c395dddf2eb8e8e65f9cc576f2e76" @@ -2411,6 +3505,22 @@ sonic-boom@^1.0.2: atomic-sleep "^1.0.0" flatstr "^1.0.12" +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-url@^0.4.0: + version "0.4.1" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" + integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== + source-map@0.1.31: version "0.1.31" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.31.tgz#9f704d0d69d9e138a81badf6ebb4fde33d151c61" @@ -2425,16 +3535,28 @@ source-map@^0.4.2: dependencies: amdefine ">=0.0.4" -source-map@~0.5.0: +source-map@^0.5.6, source-map@~0.5.0: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= +source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + spark-md5@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/spark-md5/-/spark-md5-3.0.1.tgz#83a0e255734f2ab4e5c466e5a2cfc9ba2aa2124d" integrity sha512-0tF3AGSD1ppQeuffsLDIOWlKUd3lS92tFxcsrh5Pe3ZphhnoK+oXIBTzOAThZCiuINZLvpiLH/1VS1/ANEJVig== +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + split2@^3.1.1: version "3.2.2" resolved "https://registry.yarnpkg.com/split2/-/split2-3.2.2.tgz#bf2cf2a37d838312c249c89206fd7a17dd12365f" @@ -2442,6 +3564,19 @@ split2@^3.1.1: dependencies: readable-stream "^3.0.0" +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + "statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" @@ -2482,6 +3617,13 @@ string_decoder@~0.10.x: resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ= +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + strip-ansi@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" @@ -2506,6 +3648,11 @@ strip-json-comments@~2.0.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +striptags@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/striptags/-/striptags-3.1.1.tgz#c8c3e7fdd6fb4bb3a32a3b752e5b5e3e38093ebd" + integrity sha1-yMPn/db7S7OjKjt1LltePjgJPr0= + sublevel-pouchdb@7.2.2: version "7.2.2" resolved "https://registry.yarnpkg.com/sublevel-pouchdb/-/sublevel-pouchdb-7.2.2.tgz#49e46cd37883bf7ff5006d7c5b9bcc7bcc1f422f" @@ -2516,6 +3663,11 @@ sublevel-pouchdb@7.2.2: ltgt "2.2.1" readable-stream "1.1.14" +success-symbol@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/success-symbol/-/success-symbol-0.1.0.tgz#24022e486f3bf1cdca094283b769c472d3b72897" + integrity sha1-JAIuSG878c3KCUKDt2nEctO3KJc= + supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -2551,21 +3703,54 @@ through2@^0.6.2, through2@^0.6.5: readable-stream ">=1.0.33-1 <1.1.0-0" xtend ">=4.0.0 <4.1.0-0" +through2@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + through@~2.3.4: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= +time-stamp@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/time-stamp/-/time-stamp-1.1.0.tgz#764a5a11af50561921b133f3b44e618687e0f5c3" + integrity sha1-dkpaEa9QVhkhsTPztE5hhofg9cM= + tiny-queue@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/tiny-queue/-/tiny-queue-0.2.1.tgz#25a67f2c6e253b2ca941977b5ef7442ef97a6046" integrity sha1-JaZ/LG4lOyypQZd7XvdELvl6YEY= +to-gfm-code-block@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/to-gfm-code-block/-/to-gfm-code-block-0.1.1.tgz#25d045a5fae553189e9637b590900da732d8aa82" + integrity sha1-JdBFpfrlUxielje1kJANpzLYqoI= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + to-readable-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -2573,6 +3758,16 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + toidentifier@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" @@ -2619,6 +3814,18 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" +typeof-article@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/typeof-article/-/typeof-article-0.1.1.tgz#9f07e733c3fbb646ffa9e61c08debacd460e06af" + integrity sha1-nwfnM8P7tkb/qeYcCN66zUYOBq8= + dependencies: + kind-of "^3.1.0" + +uglify-js@^3.1.4: + version "3.13.4" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.4.tgz#592588bb9f47ae03b24916e2471218d914955574" + integrity sha512-kv7fCkIXyQIilD5/yQy8O+uagsYIOt5cZvs890W40/e/rvjMSzJw81o9Bg0tkURxzZBROtDQhW2LFjOGoK3RZw== + uid2@0.0.x: version "0.0.3" resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82" @@ -2631,6 +3838,16 @@ undefsafe@^2.0.3: dependencies: debug "^2.2.0" +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + unique-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" @@ -2657,6 +3874,14 @@ unreachable-branch-transform@^0.3.0: recast "^0.10.1" through2 "^0.6.2" +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + update-notifier@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.3.tgz#be86ee13e8ce48fb50043ff72057b5bd598e1ea3" @@ -2681,6 +3906,11 @@ urijs@^1.19.2: resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.2.tgz#f9be09f00c4c5134b7cb3cf475c1dd394526265a" integrity sha512-s/UIq9ap4JPZ7H1EB5ULo/aOUbWqfDi7FKzMC2Nz+0Si8GiT1rIEaprt8hy3Vy2Ex2aJPpOQv4P4DuOZ+K1c6w== +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + url-parse-lax@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" @@ -2696,7 +3926,12 @@ url@0.10.3: punycode "1.3.2" querystring "0.2.0" -util-deprecate@^1.0.1: +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= @@ -2731,6 +3966,11 @@ vuvuzela@1.0.3: resolved "https://registry.yarnpkg.com/vuvuzela/-/vuvuzela-1.0.3.tgz#3be145e58271c73ca55279dd851f12a682114b0b" integrity sha1-O+FF5YJxxzylUnndhR8SpoIRSws= +warning-symbol@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/warning-symbol/-/warning-symbol-0.1.0.tgz#bb31dd11b7a0f9d67ab2ed95f457b65825bbad21" + integrity sha1-uzHdEbeg+dZ6su2V9Fe2WCW7rSE= + widest-line@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" @@ -2738,6 +3978,11 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -2778,11 +4023,16 @@ xmlbuilder@~9.0.1: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= -"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.2, xtend@~4.0.0: +"xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.2, xtend@~4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +year@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/year/-/year-0.2.1.tgz#4083ae520a318b23ec86037f3000cb892bdf9bb0" + integrity sha1-QIOuUgoxiyPshgN/MADLiSvfm7A= + ylru@^1.2.0: version "1.2.1" resolved "https://registry.yarnpkg.com/ylru/-/ylru-1.2.1.tgz#f576b63341547989c1de7ba288760923b27fe84f" From 0a733b7c7a16e8301cc245c786613ddb91abde2e Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 23 Apr 2021 13:49:47 +0100 Subject: [PATCH 19/29] Updating config management for SMTP as well as finalising the work around generating and sending emails. --- .../src/api/controllers/admin/configs.js | 9 +++++ .../worker/src/api/controllers/admin/email.js | 34 +++++++++++-------- .../worker/src/api/routes/admin/configs.js | 4 ++- packages/worker/src/api/routes/admin/email.js | 7 ++-- packages/worker/src/utilities/email.js | 21 ++++++++++++ 5 files changed, 58 insertions(+), 17 deletions(-) create mode 100644 packages/worker/src/utilities/email.js diff --git a/packages/worker/src/api/controllers/admin/configs.js b/packages/worker/src/api/controllers/admin/configs.js index df19dc9a56..5ca216878d 100644 --- a/packages/worker/src/api/controllers/admin/configs.js +++ b/packages/worker/src/api/controllers/admin/configs.js @@ -5,6 +5,8 @@ const { getConfigParams, determineScopedConfig, } = require("@budibase/auth").db +const { Configs } = require("../../../constants") +const email = require("../../../utilities/email") const GLOBAL_DB = StaticDatabases.GLOBAL.name @@ -22,6 +24,13 @@ exports.save = async function(ctx) { }) } + // verify the configuration + switch (type) { + case Configs.SMTP: + await email.verifyConfig(configDoc) + break; + } + try { const response = await db.post(configDoc) ctx.body = { diff --git a/packages/worker/src/api/controllers/admin/email.js b/packages/worker/src/api/controllers/admin/email.js index 6c9343ea5a..0755596841 100644 --- a/packages/worker/src/api/controllers/admin/email.js +++ b/packages/worker/src/api/controllers/admin/email.js @@ -1,10 +1,14 @@ const CouchDB = require("../../../db") const { StaticDatabases, determineScopedConfig } = require("@budibase/auth").db -const { EmailTemplatePurpose, TemplateTypes, Configs } = require("../../../constants") +const { + EmailTemplatePurpose, + TemplateTypes, + Configs, +} = require("../../../constants") const { getTemplateByPurpose } = require("../../../constants/templates") const { getSettingsTemplateContext } = require("../../../utilities/templates") const { processString } = require("@budibase/string-templates") -const nodemailer = require("nodemailer") +const { createSMTPTransport } = require("../../../utilities/email") const GLOBAL_DB = StaticDatabases.GLOBAL.name const TYPE = TemplateTypes.EMAIL @@ -14,15 +18,7 @@ const FULL_EMAIL_PURPOSES = [ EmailTemplatePurpose.PASSWORD_RECOVERY, ] -function createSMTPTransport(config) { - const transport = nodemailer.createTransport({ - port: config.port, - host: config.host, - - }) -} - -exports.buildEmail = async (email, user, purpose) => { +async function buildEmail(purpose, email, user) { // this isn't a full email if (FULL_EMAIL_PURPOSES.indexOf(purpose) === -1) { throw `Unable to build an email of type ${purpose}` @@ -37,7 +33,7 @@ exports.buildEmail = async (email, user, purpose) => { const context = { ...(await getSettingsTemplateContext()), email, - user, + user: user || {}, } body = await processString(body, context) @@ -51,14 +47,24 @@ exports.buildEmail = async (email, user, purpose) => { } exports.sendEmail = async ctx => { - const { groupId, email, purpose } = ctx.request.body + const { groupId, email, userId, purpose } = ctx.request.body const db = new CouchDB(GLOBAL_DB) const params = {} if (groupId) { params.group = groupId } params.type = Configs.SMTP + let user = {} + if (userId) { + user = db.get(userId) + } const config = await determineScopedConfig(db, params) const transport = createSMTPTransport(config) + const message = { + from: config.from, + subject: config.subject, + to: email, + html: await buildEmail(purpose, email, user), + } + await transport.sendMail(message) } - diff --git a/packages/worker/src/api/routes/admin/configs.js b/packages/worker/src/api/routes/admin/configs.js index d64900cece..0b8c9626d1 100644 --- a/packages/worker/src/api/routes/admin/configs.js +++ b/packages/worker/src/api/routes/admin/configs.js @@ -10,7 +10,9 @@ function smtpValidation() { return Joi.object({ port: Joi.number().required(), host: Joi.string().required(), - from: Joi.string().email().required(), + from: Joi.string() + .email() + .required(), secure: Joi.boolean().optional(), selfSigned: Joi.boolean().optional(), auth: Joi.object({ diff --git a/packages/worker/src/api/routes/admin/email.js b/packages/worker/src/api/routes/admin/email.js index 4a122f4791..66079c5fbb 100644 --- a/packages/worker/src/api/routes/admin/email.js +++ b/packages/worker/src/api/routes/admin/email.js @@ -15,7 +15,10 @@ function buildEmailSendValidation() { }).required().unknown(true)) } -router - .post("/api/admin/email/send", buildEmailSendValidation(), controller.sendEmail) +router.post( + "/api/admin/email/send", + buildEmailSendValidation(), + controller.sendEmail +) module.exports = router diff --git a/packages/worker/src/utilities/email.js b/packages/worker/src/utilities/email.js new file mode 100644 index 0000000000..bc3933531a --- /dev/null +++ b/packages/worker/src/utilities/email.js @@ -0,0 +1,21 @@ +const nodemailer = require("nodemailer") + +exports.createSMTPTransport = (config) => { + const options = { + port: config.port, + host: config.host, + secure: config.secure || false, + auth: config.auth, + } + if (config.selfSigned) { + options.tls = { + rejectUnauthorized: false, + } + } + return nodemailer.createTransport(options) +} + +exports.verifyConfig = async config => { + const transport = exports.createSMTPTransport(config) + await transport.verify() +} From ea8e3b7d3f668031816af538bc995c3b99446976 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 23 Apr 2021 14:58:06 +0100 Subject: [PATCH 20/29] Adding testing to worker, still WIP. --- packages/auth/src/index.js | 1 + packages/server/package.json | 1 - .../src/tests/utilities/TestConfiguration.js | 2 +- packages/worker/package.json | 4 +- .../src/api/controllers/admin/configs.js | 14 +- .../worker/src/api/routes/admin/configs.js | 7 +- .../worker/src/api/routes/tests/email.spec.js | 31 + .../tests/utilities/TestConfiguration.js | 78 + .../api/routes/tests/utilities/controllers.js | 7 + .../src/api/routes/tests/utilities/index.js | 30 + packages/worker/yarn.lock | 2738 ++++++++++++++++- 11 files changed, 2874 insertions(+), 39 deletions(-) create mode 100644 packages/worker/src/api/routes/tests/email.spec.js create mode 100644 packages/worker/src/api/routes/tests/utilities/TestConfiguration.js create mode 100644 packages/worker/src/api/routes/tests/utilities/controllers.js create mode 100644 packages/worker/src/api/routes/tests/utilities/index.js diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index c1e0a08242..5be91cc102 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -36,6 +36,7 @@ module.exports = { buildAuthMiddleware: authenticated, passport, google, + jwt, }, StaticDatabases, constants: require("./constants"), diff --git a/packages/server/package.json b/packages/server/package.json index 90b626b6c4..eadef19528 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -103,7 +103,6 @@ "jimp": "0.16.1", "joi": "17.2.1", "jsonschema": "1.4.0", - "jsonwebtoken": "8.5.1", "koa": "2.7.0", "koa-body": "4.2.0", "koa-compress": "4.0.1", diff --git a/packages/server/src/tests/utilities/TestConfiguration.js b/packages/server/src/tests/utilities/TestConfiguration.js index 630ea4256e..0b19a74b90 100644 --- a/packages/server/src/tests/utilities/TestConfiguration.js +++ b/packages/server/src/tests/utilities/TestConfiguration.js @@ -1,5 +1,4 @@ const { BUILTIN_ROLE_IDS } = require("../../utilities/security/roles") -const jwt = require("jsonwebtoken") const env = require("../../environment") const { basicTable, @@ -16,6 +15,7 @@ const controllers = require("./controllers") const supertest = require("supertest") const { cleanup } = require("../../utilities/fileSystem") const { Cookies } = require("@budibase/auth").constants +const { jwt } = require("@budibase/auth").auth const EMAIL = "babs@babs.com" const PASSWORD = "babs_password" diff --git a/packages/worker/package.json b/packages/worker/package.json index b99b79ecc5..f30455ca57 100644 --- a/packages/worker/package.json +++ b/packages/worker/package.json @@ -46,7 +46,9 @@ "server-destroy": "^1.0.1" }, "devDependencies": { + "jest": "^26.6.3", "nodemon": "^2.0.7", - "pouchdb-adapter-memory": "^7.2.2" + "pouchdb-adapter-memory": "^7.2.2", + "supertest": "^6.1.3" } } diff --git a/packages/worker/src/api/controllers/admin/configs.js b/packages/worker/src/api/controllers/admin/configs.js index 5ca216878d..dfd616fc6d 100644 --- a/packages/worker/src/api/controllers/admin/configs.js +++ b/packages/worker/src/api/controllers/admin/configs.js @@ -12,12 +12,14 @@ const GLOBAL_DB = StaticDatabases.GLOBAL.name exports.save = async function(ctx) { const db = new CouchDB(GLOBAL_DB) - const configDoc = ctx.request.body - const { type, group, user } = configDoc + const { type, config } = ctx.request.body + const { group, user } = config + // insert the type into the doc + config.type = type // Config does not exist yet - if (!configDoc._id) { - configDoc._id = generateConfigID({ + if (!config._id) { + config._id = generateConfigID({ type, group, user, @@ -27,12 +29,12 @@ exports.save = async function(ctx) { // verify the configuration switch (type) { case Configs.SMTP: - await email.verifyConfig(configDoc) + await email.verifyConfig(config) break; } try { - const response = await db.post(configDoc) + const response = await db.post(config) ctx.body = { type, _id: response.id, diff --git a/packages/worker/src/api/routes/admin/configs.js b/packages/worker/src/api/routes/admin/configs.js index 0b8c9626d1..826f9535cc 100644 --- a/packages/worker/src/api/routes/admin/configs.js +++ b/packages/worker/src/api/routes/admin/configs.js @@ -7,12 +7,11 @@ const { Configs } = require("../../../constants") const router = Router() function smtpValidation() { + // prettier-ignore return Joi.object({ port: Joi.number().required(), host: Joi.string().required(), - from: Joi.string() - .email() - .required(), + from: Joi.string().email().required(), secure: Joi.boolean().optional(), selfSigned: Joi.boolean().optional(), auth: Joi.object({ @@ -24,6 +23,7 @@ function smtpValidation() { } function settingValidation() { + // prettier-ignore return Joi.object({ url: Joi.string().valid("", null), logoUrl: Joi.string().valid("", null), @@ -32,6 +32,7 @@ function settingValidation() { } function googleValidation() { + // prettier-ignore return Joi.object({ clientID: Joi.string().required(), clientSecret: Joi.string().required(), diff --git a/packages/worker/src/api/routes/tests/email.spec.js b/packages/worker/src/api/routes/tests/email.spec.js new file mode 100644 index 0000000000..2f571e86aa --- /dev/null +++ b/packages/worker/src/api/routes/tests/email.spec.js @@ -0,0 +1,31 @@ +const setup = require("./utilities") +const { EmailTemplatePurpose } = require("../../../constants") + +// mock the email system +const sendMailMock = jest.fn() +jest.mock("nodemailer") +const nodemailer = require("nodemailer") +nodemailer.createTransport.mockReturnValue({"sendMail": sendMailMock}); + +describe("/api/admin/email", () => { + let request = setup.getRequest() + let config = setup.getConfig() + + afterAll(setup.afterAll) + + it("should be able to send an email (with mocking)", async () => { + // initially configure settings + await config.saveSmtpConfig() + await config.saveSettingsConfig() + const res = await request + .post(`/api/admin/email/send`) + .send({ + email: "test@test.com", + purpose: EmailTemplatePurpose.INVITATION, + }) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + expect(res.body._rev).toBeDefined() + }) +}) \ No newline at end of file diff --git a/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js b/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js new file mode 100644 index 0000000000..7266fe4fd7 --- /dev/null +++ b/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js @@ -0,0 +1,78 @@ +const env = require("../../environment") +const controllers = require("./controllers") +const supertest = require("supertest") +const { jwt } = require("@budibase/auth").auth +const { Cookies } = require("@budibase/auth").constants +const { Configs } = require("../../../../constants") + +class TestConfiguration { + constructor(openServer = true) { + if (openServer) { + env.PORT = 4003 + this.server = require("../../../../index") + // we need the request for logging in, involves cookies, hard to fake + this.request = supertest(this.server) + } + } + + getRequest() { + return this.request + } + + async _req(config, params, controlFunc) { + const request = {} + // fake cookies, we don't need them + request.cookies = { set: () => {}, get: () => {} } + request.config = { jwtSecret: env.JWT_SECRET } + request.appId = this.appId + request.user = { appId: this.appId } + request.request = { + body: config, + } + if (params) { + request.params = params + } + await controlFunc(request) + return request.body + } + + defaultHeaders() { + const user = { + userId: "us_uuid1", + builder: { + global: true, + }, + } + const authToken = jwt.sign(user, env.JWT_SECRET) + return { + Accept: "application/json", + Cookie: [ + `${Cookies.Auth}=${authToken}`, + ], + } + } + + async saveSettingsConfig() { + await this._req({ + type: Configs.SETTINGS, + config: { + url: "http://localhost:10000", + logoUrl: "http://localhost:10000/logo", + company: "TestCompany", + } + }, null, controllers.config.save) + } + + async saveSmtpConfig() { + await this._req({ + type: Configs.SMTP, + config: { + url: "http://localhost:10000", + logoUrl: "http://localhost:10000/logo", + company: "TestCompany", + } + }, null, controllers.config.save) + } +} + +module.exports = TestConfiguration \ No newline at end of file diff --git a/packages/worker/src/api/routes/tests/utilities/controllers.js b/packages/worker/src/api/routes/tests/utilities/controllers.js new file mode 100644 index 0000000000..e74e6dc355 --- /dev/null +++ b/packages/worker/src/api/routes/tests/utilities/controllers.js @@ -0,0 +1,7 @@ +module.exports = { + email: require("../../../controllers/admin/email"), + groups: require("../../../controllers/admin/groups"), + config: require("../../../controllers/admin/groups"), + templates: require("../../../controllers/admin/groups"), + users: require("../../../controllers/admin/groups"), +} diff --git a/packages/worker/src/api/routes/tests/utilities/index.js b/packages/worker/src/api/routes/tests/utilities/index.js new file mode 100644 index 0000000000..d63b837f6d --- /dev/null +++ b/packages/worker/src/api/routes/tests/utilities/index.js @@ -0,0 +1,30 @@ +const TestConfig = require("./TestConfiguration") + +let request, config + +exports.beforeAll = () => { + config = new TestConfig() + request = config.getRequest() +} + +exports.afterAll = () => { + if (config) { + config.end() + } + request = null + config = null +} + +exports.getRequest = () => { + if (!request) { + exports.beforeAll() + } + return request +} + +exports.getConfig = () => { + if (!config) { + exports.beforeAll() + } + return config +} diff --git a/packages/worker/yarn.lock b/packages/worker/yarn.lock index 4af1c1d9dd..9510f6cd5c 100644 --- a/packages/worker/yarn.lock +++ b/packages/worker/yarn.lock @@ -2,6 +2,291 @@ # yarn lockfile v1 +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.13.tgz#dcfc826beef65e75c50e21d3837d7d95798dd658" + integrity sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g== + dependencies: + "@babel/highlight" "^7.12.13" + +"@babel/compat-data@^7.13.15": + version "7.13.15" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.13.15.tgz#7e8eea42d0b64fda2b375b22d06c605222e848f4" + integrity sha512-ltnibHKR1VnrU4ymHyQ/CXtNXI6yZC0oJThyW78Hft8XndANwi+9H+UIklBDraIjFEJzw8wmcM427oDd9KS5wA== + +"@babel/core@^7.1.0", "@babel/core@^7.7.5": + version "7.13.16" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.13.16.tgz#7756ab24396cc9675f1c3fcd5b79fcce192ea96a" + integrity sha512-sXHpixBiWWFti0AV2Zq7avpTasr6sIAu7Y396c608541qAU2ui4a193m0KSQmfPSKFZLnQ3cvlKDOm3XkuXm3Q== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.13.16" + "@babel/helper-compilation-targets" "^7.13.16" + "@babel/helper-module-transforms" "^7.13.14" + "@babel/helpers" "^7.13.16" + "@babel/parser" "^7.13.16" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.15" + "@babel/types" "^7.13.16" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.1.2" + semver "^6.3.0" + source-map "^0.5.0" + +"@babel/generator@^7.13.16": + version "7.13.16" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.13.16.tgz#0befc287031a201d84cdfc173b46b320ae472d14" + integrity sha512-grBBR75UnKOcUWMp8WoDxNsWCFl//XCK6HWTrBQKTr5SV9f5g0pNOjdyzi/DTBv12S9GnYPInIXQBTky7OXEMg== + dependencies: + "@babel/types" "^7.13.16" + jsesc "^2.5.1" + source-map "^0.5.0" + +"@babel/helper-compilation-targets@^7.13.16": + version "7.13.16" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.13.16.tgz#6e91dccf15e3f43e5556dffe32d860109887563c" + integrity sha512-3gmkYIrpqsLlieFwjkGgLaSHmhnvlAYzZLlYVjlW+QwI+1zE17kGxuJGmIqDQdYp56XdmGeD+Bswx0UTyG18xA== + dependencies: + "@babel/compat-data" "^7.13.15" + "@babel/helper-validator-option" "^7.12.17" + browserslist "^4.14.5" + semver "^6.3.0" + +"@babel/helper-function-name@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.12.13.tgz#93ad656db3c3c2232559fd7b2c3dbdcbe0eb377a" + integrity sha512-TZvmPn0UOqmvi5G4vvw0qZTpVptGkB1GL61R6lKvrSdIxGm5Pky7Q3fpKiIkQCAtRCBUwB0PaThlx9vebCDSwA== + dependencies: + "@babel/helper-get-function-arity" "^7.12.13" + "@babel/template" "^7.12.13" + "@babel/types" "^7.12.13" + +"@babel/helper-get-function-arity@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583" + integrity sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-member-expression-to-functions@^7.13.12": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz#dfe368f26d426a07299d8d6513821768216e6d72" + integrity sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw== + dependencies: + "@babel/types" "^7.13.12" + +"@babel/helper-module-imports@^7.13.12": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.13.12.tgz#c6a369a6f3621cb25da014078684da9196b61977" + integrity sha512-4cVvR2/1B693IuOvSI20xqqa/+bl7lqAMR59R4iu39R9aOX8/JoYY1sFaNvUMyMBGnHdwvJgUrzNLoUZxXypxA== + dependencies: + "@babel/types" "^7.13.12" + +"@babel/helper-module-transforms@^7.13.14": + version "7.13.14" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.13.14.tgz#e600652ba48ccb1641775413cb32cfa4e8b495ef" + integrity sha512-QuU/OJ0iAOSIatyVZmfqB0lbkVP0kDRiKj34xy+QNsnVZi/PA6BoSoreeqnxxa9EHFAIL0R9XOaAR/G9WlIy5g== + dependencies: + "@babel/helper-module-imports" "^7.13.12" + "@babel/helper-replace-supers" "^7.13.12" + "@babel/helper-simple-access" "^7.13.12" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/helper-validator-identifier" "^7.12.11" + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.13" + "@babel/types" "^7.13.14" + +"@babel/helper-optimise-call-expression@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz#5c02d171b4c8615b1e7163f888c1c81c30a2aaea" + integrity sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.8.0": + version "7.13.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz#806526ce125aed03373bc416a828321e3a6a33af" + integrity sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ== + +"@babel/helper-replace-supers@^7.13.12": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.13.12.tgz#6442f4c1ad912502481a564a7386de0c77ff3804" + integrity sha512-Gz1eiX+4yDO8mT+heB94aLVNCL+rbuT2xy4YfyNqu8F+OI6vMvJK891qGBTqL9Uc8wxEvRW92Id6G7sDen3fFw== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.13.12" + "@babel/helper-optimise-call-expression" "^7.12.13" + "@babel/traverse" "^7.13.0" + "@babel/types" "^7.13.12" + +"@babel/helper-simple-access@^7.13.12": + version "7.13.12" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.13.12.tgz#dd6c538afb61819d205a012c31792a39c7a5eaf6" + integrity sha512-7FEjbrx5SL9cWvXioDbnlYTppcZGuCY6ow3/D5vMggb2Ywgu4dMrpTJX0JdQAIcRRUElOIxF3yEooa9gUb9ZbA== + dependencies: + "@babel/types" "^7.13.12" + +"@babel/helper-split-export-declaration@^7.12.13": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz#e9430be00baf3e88b0e13e6f9d4eaf2136372b05" + integrity sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg== + dependencies: + "@babel/types" "^7.12.13" + +"@babel/helper-validator-identifier@^7.12.11": + version "7.12.11" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed" + integrity sha512-np/lG3uARFybkoHokJUmf1QfEvRVCPbmQeUQpKow5cQ3xWrV9i3rUHodKDJPQfTVX61qKi+UdYk8kik84n7XOw== + +"@babel/helper-validator-option@^7.12.17": + version "7.12.17" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831" + integrity sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw== + +"@babel/helpers@^7.13.16": + version "7.13.17" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.13.17.tgz#b497c7a00e9719d5b613b8982bda6ed3ee94caf6" + integrity sha512-Eal4Gce4kGijo1/TGJdqp3WuhllaMLSrW6XcL0ulyUAQOuxHcCafZE8KHg9857gcTehsm/v7RcOx2+jp0Ryjsg== + dependencies: + "@babel/template" "^7.12.13" + "@babel/traverse" "^7.13.17" + "@babel/types" "^7.13.17" + +"@babel/highlight@^7.12.13": + version "7.13.10" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.13.10.tgz#a8b2a66148f5b27d666b15d81774347a731d52d1" + integrity sha512-5aPpe5XQPzflQrFwL1/QoeHkP2MsA4JCntcXHRhEsdsfPVkvPi2w7Qix4iV7t5S/oC9OodGrggd8aco1g3SZFg== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + chalk "^2.0.0" + js-tokens "^4.0.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.12.13", "@babel/parser@^7.13.16": + version "7.13.16" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.13.16.tgz#0f18179b0448e6939b1f3f5c4c355a3a9bcdfd37" + integrity sha512-6bAg36mCwuqLO0hbR+z7PHuqWiCeP7Dzg73OpQwsAB1Eb8HnGEz5xYBzCfbu+YjoaJsJs+qheDxVAuqbt3ILEw== + +"@babel/plugin-syntax-async-generators@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-bigint@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz#4c9a6f669f5d0cdf1b90a1671e9a146be5300cea" + integrity sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-class-properties@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" + integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/plugin-syntax-import-meta@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" + integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-logical-assignment-operators@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" + integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-numeric-separator@^7.8.3": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz#b9b070b3e33570cd9fd07ba7fa91c0dd37b9af97" + integrity sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" + +"@babel/plugin-syntax-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.12.13.tgz#c5f0fa6e249f5b739727f923540cf7a806130178" + integrity sha512-A81F9pDwyS7yM//KwbCSDqy3Uj4NMIurtplxphWxoYtNPov7cJsDkAFNNyVlIZ3jwGycVsurZ+LtOA8gZ376iQ== + dependencies: + "@babel/helper-plugin-utils" "^7.12.13" + +"@babel/template@^7.12.13", "@babel/template@^7.3.3": + version "7.12.13" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327" + integrity sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/parser" "^7.12.13" + "@babel/types" "^7.12.13" + +"@babel/traverse@^7.1.0", "@babel/traverse@^7.13.0", "@babel/traverse@^7.13.13", "@babel/traverse@^7.13.15", "@babel/traverse@^7.13.17": + version "7.13.17" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.13.17.tgz#c85415e0c7d50ac053d758baec98b28b2ecfeea3" + integrity sha512-BMnZn0R+X6ayqm3C3To7o1j7Q020gWdqdyP50KEoVqaCO2c/Im7sYZSmVgvefp8TTMQ+9CtwuBp0Z1CZ8V3Pvg== + dependencies: + "@babel/code-frame" "^7.12.13" + "@babel/generator" "^7.13.16" + "@babel/helper-function-name" "^7.12.13" + "@babel/helper-split-export-declaration" "^7.12.13" + "@babel/parser" "^7.13.16" + "@babel/types" "^7.13.17" + debug "^4.1.0" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.12.13", "@babel/types@^7.13.12", "@babel/types@^7.13.14", "@babel/types@^7.13.16", "@babel/types@^7.13.17", "@babel/types@^7.3.0", "@babel/types@^7.3.3": + version "7.13.17" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.13.17.tgz#48010a115c9fba7588b4437dd68c9469012b38b4" + integrity sha512-RawydLgxbOPDlTLJNtoIypwdmAy//uQIzlKt2+iBiJaRlVuI6QLUxVAyWGNfOzp8Yu4L4lLIacoCyTNtpb4wiA== + dependencies: + "@babel/helper-validator-identifier" "^7.12.11" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + "@budibase/handlebars-helpers@^0.11.3": version "0.11.3" resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.11.3.tgz#b6e5c91b83e8906e7d7ff10ddde277a3d561016e" @@ -45,6 +330,14 @@ handlebars-utils "^1.0.6" lodash "^4.17.20" +"@cnakazawa/watch@^1.0.3": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" + integrity sha512-v9kIhKwjeZThiWrLmj0y17CWoyddASLj9O2yvbZkbvw/N3rWOYy9zkV66ursAoVr0mV15bL8g0c4QZUE6cdDoQ== + dependencies: + exec-sh "^0.3.2" + minimist "^1.2.0" + "@hapi/bourne@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-2.0.0.tgz#5bb2193eb685c0007540ca61d166d4e1edaf918d" @@ -62,6 +355,193 @@ dependencies: "@hapi/hoek" "^9.0.0" +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/console@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/console/-/console-26.6.2.tgz#4e04bc464014358b03ab4937805ee36a0aeb98f2" + integrity sha512-IY1R2i2aLsLr7Id3S6p2BA82GNWryt4oSvEXLAKc+L2zdi89dSkE8xC1C+0kpATG4JhBJREnQOH7/zmccM2B0g== + dependencies: + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + jest-message-util "^26.6.2" + jest-util "^26.6.2" + slash "^3.0.0" + +"@jest/core@^26.6.3": + version "26.6.3" + resolved "https://registry.yarnpkg.com/@jest/core/-/core-26.6.3.tgz#7639fcb3833d748a4656ada54bde193051e45fad" + integrity sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw== + dependencies: + "@jest/console" "^26.6.2" + "@jest/reporters" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-changed-files "^26.6.2" + jest-config "^26.6.3" + jest-haste-map "^26.6.2" + jest-message-util "^26.6.2" + jest-regex-util "^26.0.0" + jest-resolve "^26.6.2" + jest-resolve-dependencies "^26.6.3" + jest-runner "^26.6.3" + jest-runtime "^26.6.3" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" + jest-watcher "^26.6.2" + micromatch "^4.0.2" + p-each-series "^2.1.0" + rimraf "^3.0.0" + slash "^3.0.0" + strip-ansi "^6.0.0" + +"@jest/environment@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/environment/-/environment-26.6.2.tgz#ba364cc72e221e79cc8f0a99555bf5d7577cf92c" + integrity sha512-nFy+fHl28zUrRsCeMB61VDThV1pVTtlEokBRgqPrcT1JNq4yRNIyTHfyht6PqtUvY9IsuLGTrbG8kPXjSZIZwA== + dependencies: + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + jest-mock "^26.6.2" + +"@jest/fake-timers@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/fake-timers/-/fake-timers-26.6.2.tgz#459c329bcf70cee4af4d7e3f3e67848123535aad" + integrity sha512-14Uleatt7jdzefLPYM3KLcnUl1ZNikaKq34enpb5XG9i81JpppDb5muZvonvKyrl7ftEHkKS5L5/eB/kxJ+bvA== + dependencies: + "@jest/types" "^26.6.2" + "@sinonjs/fake-timers" "^6.0.1" + "@types/node" "*" + jest-message-util "^26.6.2" + jest-mock "^26.6.2" + jest-util "^26.6.2" + +"@jest/globals@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/globals/-/globals-26.6.2.tgz#5b613b78a1aa2655ae908eba638cc96a20df720a" + integrity sha512-85Ltnm7HlB/KesBUuALwQ68YTU72w9H2xW9FjZ1eL1U3lhtefjjl5c2MiUbpXt/i6LaPRvoOFJ22yCBSfQ0JIA== + dependencies: + "@jest/environment" "^26.6.2" + "@jest/types" "^26.6.2" + expect "^26.6.2" + +"@jest/reporters@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/reporters/-/reporters-26.6.2.tgz#1f518b99637a5f18307bd3ecf9275f6882a667f6" + integrity sha512-h2bW53APG4HvkOnVMo8q3QXa6pcaNt1HkwVsOPMBV6LD/q9oSpxNSYZQYkAnjdMjrJ86UuYeLo+aEZClV6opnw== + dependencies: + "@bcoe/v8-coverage" "^0.2.3" + "@jest/console" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + chalk "^4.0.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.2" + graceful-fs "^4.2.4" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-instrument "^4.0.3" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + jest-haste-map "^26.6.2" + jest-resolve "^26.6.2" + jest-util "^26.6.2" + jest-worker "^26.6.2" + slash "^3.0.0" + source-map "^0.6.0" + string-length "^4.0.1" + terminal-link "^2.0.0" + v8-to-istanbul "^7.0.0" + optionalDependencies: + node-notifier "^8.0.0" + +"@jest/source-map@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/source-map/-/source-map-26.6.2.tgz#29af5e1e2e324cafccc936f218309f54ab69d535" + integrity sha512-YwYcCwAnNmOVsZ8mr3GfnzdXDAl4LaenZP5z+G0c8bzC9/dugL8zRmxZzdoTl4IaS3CryS1uWnROLPFmb6lVvA== + dependencies: + callsites "^3.0.0" + graceful-fs "^4.2.4" + source-map "^0.6.0" + +"@jest/test-result@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/test-result/-/test-result-26.6.2.tgz#55da58b62df134576cc95476efa5f7949e3f5f18" + integrity sha512-5O7H5c/7YlojphYNrK02LlDIV2GNPYisKwHm2QTKjNZeEzezCbwYs9swJySv2UfPMyZ0VdsmMv7jIlD/IKYQpQ== + dependencies: + "@jest/console" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/istanbul-lib-coverage" "^2.0.0" + collect-v8-coverage "^1.0.0" + +"@jest/test-sequencer@^26.6.3": + version "26.6.3" + resolved "https://registry.yarnpkg.com/@jest/test-sequencer/-/test-sequencer-26.6.3.tgz#98e8a45100863886d074205e8ffdc5a7eb582b17" + integrity sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw== + dependencies: + "@jest/test-result" "^26.6.2" + graceful-fs "^4.2.4" + jest-haste-map "^26.6.2" + jest-runner "^26.6.3" + jest-runtime "^26.6.3" + +"@jest/transform@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/transform/-/transform-26.6.2.tgz#5ac57c5fa1ad17b2aae83e73e45813894dcf2e4b" + integrity sha512-E9JjhUgNzvuQ+vVAL21vlyfy12gP0GhazGgJC4h6qUt1jSdUXGWJ1wfu/X7Sd8etSgxV4ovT1pb9v5D6QW4XgA== + dependencies: + "@babel/core" "^7.1.0" + "@jest/types" "^26.6.2" + babel-plugin-istanbul "^6.0.0" + chalk "^4.0.0" + convert-source-map "^1.4.0" + fast-json-stable-stringify "^2.0.0" + graceful-fs "^4.2.4" + jest-haste-map "^26.6.2" + jest-regex-util "^26.0.0" + jest-util "^26.6.2" + micromatch "^4.0.2" + pirates "^4.0.1" + slash "^3.0.0" + source-map "^0.6.1" + write-file-atomic "^3.0.0" + +"@jest/types@^26.6.2": + version "26.6.2" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-26.6.2.tgz#bef5a532030e1d88a2f5a6d933f84e97226ed48e" + integrity sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + "@koa/router@^8.0.0": version "8.0.8" resolved "https://registry.yarnpkg.com/@koa/router/-/router-8.0.8.tgz#95f32d11373d03d89dcb63fabe9ac6f471095236" @@ -101,6 +581,20 @@ resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-4.0.0.tgz#2ff674e9611b45b528896d820d3d7a812de2f0e4" integrity sha512-FyD2meJpDPjyNQejSjvnhpgI/azsQkA4lGbuu5BQZfjvJ9cbRZXzeWL2HceCekW4lixO9JPesIIQkSoLjeJHNQ== +"@sinonjs/commons@^1.7.0": + version "1.8.3" + resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.3.tgz#3802ddd21a50a949b6721ddd72da36e67e7f1b2d" + integrity sha512-xkNcLAn/wZaX14RPlwizcKicDk9G3F8m2nU3L7Ukm5zBgTwiT0wsoFAHx9Jq56fJA1z/7uKGtCRu16sOUCLIHQ== + dependencies: + type-detect "4.0.8" + +"@sinonjs/fake-timers@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz#293674fccb3262ac782c7aadfdeca86b10c75c40" + integrity sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA== + dependencies: + "@sinonjs/commons" "^1.7.0" + "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -115,6 +609,39 @@ dependencies: defer-to-connect "^2.0.0" +"@types/babel__core@^7.0.0", "@types/babel__core@^7.1.7": + version "7.1.14" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.14.tgz#faaeefc4185ec71c389f4501ee5ec84b170cc402" + integrity sha512-zGZJzzBUVDo/eV6KgbE0f0ZI7dInEYvo12Rb70uNQDshC3SkRMb67ja0GgRHZgAX3Za6rhaWlvbDO8rrGyAb1g== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.2" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.2.tgz#f3d71178e187858f7c45e30380f8f1b7415a12d8" + integrity sha512-MdSJnBjl+bdwkLskZ3NGFp9YcXGx5ggLpQQPqtgakVhsWK0hTtNYhjpZLlWQTviGTvF8at+Bvli3jV7faPdgeQ== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.0" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.0.tgz#0c888dd70b3ee9eebb6e4f200e809da0076262be" + integrity sha512-NTPErx4/FiPCGScH7foPyr+/1Dkzkni+rHiYHHoTjvwou7AQzJkNeD60A9CXRy+ZEN2B1bggmkTMCDb+Mv5k+A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*", "@types/babel__traverse@^7.0.4", "@types/babel__traverse@^7.0.6": + version "7.11.1" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.11.1.tgz#654f6c4f67568e24c23b367e947098c6206fa639" + integrity sha512-Vs0hm0vPahPMYi9tDjtP66llufgO3ST16WXaSTtDGEl9cewAl3AibmxWw6TINOqHPT9z0uABKAYjT9jNSg4npw== + dependencies: + "@babel/types" "^7.3.0" + "@types/cacheable-request@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.1.tgz#5d22f3dded1fd3a84c0bbeb5039a7419c2c91976" @@ -138,11 +665,37 @@ "@types/events" "*" "@types/node" "*" +"@types/graceful-fs@^4.1.2": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15" + integrity sha512-anKkLmZZ+xm4p8JWBf4hElkM4XR+EZeA2M9BAkkTldmcyDY4mbdIJnRghDJH3Ov5ooY7/UAoENtmdMSkaAd7Cw== + dependencies: + "@types/node" "*" + "@types/http-cache-semantics@*": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.0.tgz#9140779736aa2655635ee756e2467d787cfe8a2a" integrity sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A== +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0", "@types/istanbul-lib-coverage@^2.0.1": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762" + integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz#508b13aa344fa4976234e75dddcc34925737d821" + integrity sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA== + dependencies: + "@types/istanbul-lib-report" "*" + "@types/keyv@*": version "3.1.1" resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.1.tgz#e45a45324fca9dab716ab1230ee249c9fb52cfa7" @@ -155,6 +708,16 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.14.tgz#f7fd5f3cc8521301119f63910f0fb965c7d761ae" integrity sha512-UHnOPWVWV1z+VV8k6L1HhG7UbGBgIdghqF3l9Ny9ApPghbjICXkUJSd/b9gOgQfjM1r+37cipdw/HJ3F6ICEnQ== +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== + +"@types/prettier@^2.0.0": + version "2.2.3" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.2.3.tgz#ef65165aea2924c9359205bf748865b8881753c0" + integrity sha512-PijRCG/K3s3w1We6ynUKdxEc5AcuuH3NBmMDP8uvKVp6X43UY7NQlTzczakXP3DJR0F4dfNQIGjU2cUeRYs2AA== + "@types/responselike@*", "@types/responselike@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/responselike/-/responselike-1.0.0.tgz#251f4fe7d154d2bad125abe1b429b23afd262e29" @@ -162,6 +725,28 @@ dependencies: "@types/node" "*" +"@types/stack-utils@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff" + integrity sha512-RJJrrySY7A8havqpGObOB4W92QXKJo63/jFLLgpvOtsGUqbQZ9Sbgl35KMm1DjC6j7AvmmU2bIno+3IyEaemaw== + +"@types/yargs-parser@*": + version "20.2.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-20.2.0.tgz#dd3e6699ba3237f0348cd085e4698780204842f9" + integrity sha512-37RSHht+gzzgYeobbG+KWryeAW8J33Nhr69cjTqSYymXVZEN9NbRYWoYlRtDhHKPVT1FyNKwaTPC1NynKZpzRA== + +"@types/yargs@^15.0.0": + version "15.0.13" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.13.tgz#34f7fec8b389d7f3c1fd08026a5763e072d3c6dc" + integrity sha512-kQ5JNTrbDv3Rp5X2n/iUu37IJBDU2gsZ5R/g1/KHOOEc5IKfUFjXT6DENPGduh08I/pamwtEq4oul7gUqKTQDQ== + dependencies: + "@types/yargs-parser" "*" + +abab@^2.0.3, abab@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.5.tgz#c0b678fb32d60fc1219c784d6a826fe385aeb79a" + integrity sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q== + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -211,6 +796,19 @@ accepts@^1.3.5: mime-types "~2.1.24" negotiator "0.6.2" +acorn-globals@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-6.0.0.tgz#46cdd39f0f8ff08a876619b55f5ac8a6dc770b45" + integrity sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg== + dependencies: + acorn "^7.1.1" + acorn-walk "^7.1.1" + +acorn-walk@^7.1.1: + version "7.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" + integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== + acorn@^1.0.3: version "1.2.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-1.2.2.tgz#c8ce27de0acc76d896d2b1fad3df588d9e82f014" @@ -221,6 +819,26 @@ acorn@^5.2.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.4.tgz#3e8d8a9947d0599a1796d10225d7432f4a4acf5e" integrity sha512-1D++VG7BhrtvQpNbBzovKNc1FLGGEE/oGe7b9xJm/RFHMBeUaUGpluV9RLjZa47YFdPcDAenEYuq9pQPcMdLJg== +acorn@^7.1.1: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +acorn@^8.1.0: + version "8.1.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.1.1.tgz#fb0026885b9ac9f48bac1e185e4af472971149ff" + integrity sha512-xYiIVjNuqtKXMxlRMDc6mZUhXehod4a3gbZ1qRlM7icK4EbxUFNLhWoPblCvFtB2Y9CIqHP3CF/rdxLItaQv8g== + +ajv@^6.12.3: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + amdefine@>=0.0.4: version "1.0.1" resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" @@ -357,6 +975,13 @@ ansi-dim@^0.1.1: dependencies: ansi-wrap "0.1.0" +ansi-escapes@^4.2.1: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + ansi-gray@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ansi-gray/-/ansi-gray-0.1.1.tgz#2962cf54ec9792c48510a3deb524436861ef7251" @@ -444,7 +1069,7 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -482,6 +1107,22 @@ any-promise@^1.1.0: resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +anymatch@^3.0.3: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + anymatch@~3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" @@ -490,7 +1131,7 @@ anymatch@~3.1.1: normalize-path "^3.0.0" picomatch "^2.0.4" -argparse@^1.0.10: +argparse@^1.0.10, argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== @@ -541,6 +1182,18 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -556,6 +1209,11 @@ ast-types@0.9.6: resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.9.6.tgz#102c9e9e9005d3e7e3829bf0c4fa24ee862ee9b9" integrity sha1-ECyenpAF0+fjgpvwxPok7oYu6bk= +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" @@ -588,6 +1246,77 @@ aws-sdk@^2.811.0: uuid "3.3.2" xml2js "0.4.19" +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== + +babel-jest@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-26.6.3.tgz#d87d25cb0037577a0c89f82e5755c5d293c01056" + integrity sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA== + dependencies: + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/babel__core" "^7.1.7" + babel-plugin-istanbul "^6.0.0" + babel-preset-jest "^26.6.2" + chalk "^4.0.0" + graceful-fs "^4.2.4" + slash "^3.0.0" + +babel-plugin-istanbul@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.0.0.tgz#e159ccdc9af95e0b570c75b4573b7c34d671d765" + integrity sha512-AF55rZXpe7trmEylbaE1Gv54wn6rwU03aptvRoVIGP8YykoSxqdVLV1TfwflBCE/QtHmqtP8SWlTENqbK8GCSQ== + dependencies: + "@babel/helper-plugin-utils" "^7.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-instrument "^4.0.0" + test-exclude "^6.0.0" + +babel-plugin-jest-hoist@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.6.2.tgz#8185bd030348d254c6d7dd974355e6a28b21e62d" + integrity sha512-PO9t0697lNTmcEHH69mdtYiOIkkOlj9fySqfO3K1eCcdISevLAE0xY59VLLUj0SoiPiTX/JU2CYFpILydUa5Lw== + dependencies: + "@babel/template" "^7.3.3" + "@babel/types" "^7.3.3" + "@types/babel__core" "^7.0.0" + "@types/babel__traverse" "^7.0.6" + +babel-preset-current-node-syntax@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz#b4399239b89b2a011f9ddbe3e4f401fc40cff73b" + integrity sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ== + dependencies: + "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/plugin-syntax-bigint" "^7.8.3" + "@babel/plugin-syntax-class-properties" "^7.8.3" + "@babel/plugin-syntax-import-meta" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/plugin-syntax-logical-assignment-operators" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-syntax-numeric-separator" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + +babel-preset-jest@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/babel-preset-jest/-/babel-preset-jest-26.6.2.tgz#747872b1171df032252426586881d62d31798fee" + integrity sha512-YvdtlVm9t3k777c5NPQIv6cxFFFapys25HiUmuSgHwIZhfifweR5c5Sf5nwE3MAbfu327CYSvps8Yx6ANLyleQ== + dependencies: + babel-plugin-jest-hoist "^26.6.2" + babel-preset-current-node-syntax "^1.0.0" + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -626,6 +1355,13 @@ base@^0.11.1: mixin-deep "^1.2.0" pascalcase "^0.1.1" +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + bcryptjs@^2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb" @@ -674,19 +1410,42 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -braces@~3.0.2: +braces@^3.0.1, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: fill-range "^7.0.1" +browser-process-hrtime@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" + integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== + +browserslist@^4.14.5: + version "4.16.5" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.16.5.tgz#952825440bca8913c62d0021334cbe928ef062ae" + integrity sha512-C2HAjrM1AI/djrpAUU/tr4pml1DqLIzJKSLDBXBrNErl9ZCCTXdhwxdJjYc16953+mBWf7Lw+uUJgpgb8cN71A== + dependencies: + caniuse-lite "^1.0.30001214" + colorette "^1.2.2" + electron-to-chromium "^1.3.719" + escalade "^3.1.1" + node-releases "^1.1.71" + +bser@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" + integrity sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ== + dependencies: + node-int64 "^0.4.0" + buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= -buffer-from@1.1.1: +buffer-from@1.1.1, buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== @@ -767,17 +1526,52 @@ cacheable-request@^7.0.1: normalize-url "^4.1.0" responselike "^2.0.0" +call-bind@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + camelcase@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.0.0.tgz#03295527d58bd3cd4aa75363f35b2e8d97be2f42" integrity sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA== -camelcase@^5.3.1: +camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -chalk@2.4.2: +camelcase@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" + integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + +caniuse-lite@^1.0.30001214: + version "1.0.30001214" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001214.tgz#70f153c78223515c6d37a9fde6cd69250da9d872" + integrity sha512-O2/SCpuaU3eASWVaesQirZv1MSjUNOvmugaD8zNSJqw6Vv5SGwoOpA9LJs3pNPfM745nxqPvfZY3MQKY4AKHYg== + +capture-exit@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" + integrity sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g== + dependencies: + rsvp "^4.8.4" + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +chalk@2.4.2, chalk@^2.0.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -802,6 +1596,11 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +char-regex@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" + integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw== + chokidar@^3.2.2: version "3.5.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" @@ -822,6 +1621,11 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +cjs-module-lexer@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-0.6.0.tgz#4186fcca0eae175970aee870b9fe2d6cf8d5655f" + integrity sha512-uc2Vix1frTfnuzxxu1Hp4ktSvM3QaI4oXl4ZUqL1wjTu/BGki9TrCWoqLTg/drR1KwAEarXuRFCG2Svr1GxPFw== + class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -837,6 +1641,15 @@ cli-boxes@^2.2.0: resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + clone-buffer@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" @@ -864,6 +1677,11 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= +collect-v8-coverage@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59" + integrity sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg== + collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" @@ -896,6 +1714,18 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colorette@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-1.2.2.tgz#cbcc79d5e99caea2dbf10eb3a26fd8b3e6acfa94" + integrity sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w== + +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + commander@^2.5.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -916,7 +1746,7 @@ commoner@^0.10.1: q "^1.1.2" recast "^0.11.17" -component-emitter@^1.2.1: +component-emitter@^1.2.1, component-emitter@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== @@ -964,6 +1794,18 @@ content-type@^1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + +cookiejar@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" + integrity sha512-Mw+adcfzPxcPeI+0WlvRrr/3lGVO0bD75SxX6811cxSh1Wbxx7xZBGK1eVtDf6si8rg2lhnUjsVLMFMfbRIuwA== + cookies@~0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/cookies/-/cookies-0.8.0.tgz#1293ce4b391740a8406e3c9870e828c4b54f3f90" @@ -977,7 +1819,7 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= -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" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= @@ -989,11 +1831,64 @@ crc@^3.4.4: dependencies: buffer "^5.1.0" +cross-spawn@^6.0.0: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^7.0.0: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + crypto-random-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== +cssom@^0.4.4: + version "0.4.4" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.4.4.tgz#5a66cf93d2d0b661d80bf6a44fb65f5c2e4e0a10" + integrity sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw== + +cssom@~0.3.6: + version "0.3.8" + resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.8.tgz#9f1276f5b2b463f2114d3f2c75250af8c1a36f4a" + integrity sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg== + +cssstyle@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/cssstyle/-/cssstyle-2.3.0.tgz#ff665a0ddbdc31864b09647f34163443d90b0852" + integrity sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A== + dependencies: + cssom "~0.3.6" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +data-urls@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-2.0.0.tgz#156485a72963a970f5d5821aaf642bef2bf2db9b" + integrity sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ== + dependencies: + abab "^2.0.3" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.0.0" + date.js@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/date.js/-/date.js-0.3.3.tgz#ef1e92332f507a638795dbb985e951882e50bbda" @@ -1025,7 +1920,7 @@ debug@^3.1.0, debug@^3.2.6: dependencies: ms "^2.1.1" -debug@^4.1.1: +debug@^4.1.0, debug@^4.1.1: version "4.3.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== @@ -1039,6 +1934,16 @@ debug@~3.1.0: dependencies: ms "2.0.0" +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decimal.js@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.2.1.tgz#238ae7b0f0c793d3e3cea410108b35a2c01426a3" + integrity sha512-KaL7+6Fw6i5A2XSnsbhm/6B+NuEA7TZ4vqxnd5tXz9sbKtrN9Srj8ab4vKVdK8YAqZO9P1kg45Y6YLoduPf+kw== + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -1068,6 +1973,16 @@ deep-extend@^0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +deepmerge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" + integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== + default-compare@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/default-compare/-/default-compare-1.0.0.tgz#cb61131844ad84d84788fb68fd01681ca7781a2f" @@ -1120,6 +2035,11 @@ defined@^1.0.0: resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" integrity sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" @@ -1140,6 +2060,11 @@ destroy@^1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +detect-newline@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651" + integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA== + detective@^4.3.1: version "4.7.1" resolved "https://registry.yarnpkg.com/detective/-/detective-4.7.1.tgz#0eca7314338442febb6d65da54c10bb1c82b246e" @@ -1148,6 +2073,18 @@ detective@^4.3.1: acorn "^5.2.1" defined "^1.0.0" +diff-sequences@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-26.6.2.tgz#48ba99157de1923412eed41db6b6d4aa9ca7c0b1" + integrity sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q== + +domexception@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domexception/-/domexception-2.0.1.tgz#fb44aefba793e1574b0af6aed2801d057529f304" + integrity sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg== + dependencies: + webidl-conversions "^5.0.0" + dot-prop@^5.2.0: version "5.3.0" resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" @@ -1170,6 +2107,14 @@ duplexer3@^0.1.4: resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + ecdsa-sig-formatter@1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" @@ -1182,6 +2127,16 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= +electron-to-chromium@^1.3.719: + version "1.3.720" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.720.tgz#f5d66df8754d993006b7b2ded15ff7738c58bd94" + integrity sha512-B6zLTxxaOFP4WZm6DrvgRk8kLFYWNhQ5TrHMC0l5WtkMXhU5UbnvWoTfeEwqOruUSlNMhVLfYak7REX6oC5Yfw== + +emittery@^0.7.1: + version "0.7.2" + resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.7.2.tgz#25595908e13af0f5674ab419396e2fb394cdfa82" + integrity sha512-A8OG5SR/ij3SsJdWDJdkkSYUjQdCUx6APQXem0SaEePBSRg4eymGYwBkKo1Y6DU+af/Jn2dBQqDBvjnr9Vi8nQ== + emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -1233,6 +2188,13 @@ errno@~0.1.1: dependencies: prr "~1.0.1" +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + error-symbol@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/error-symbol/-/error-symbol-0.1.0.tgz#0a4dae37d600d15a29ba453d8ef920f1844333f6" @@ -1256,6 +2218,11 @@ es3ify@^0.2.2: jstransform "~11.0.0" through "~2.3.4" +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + escape-goat@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" @@ -1271,6 +2238,23 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +escodegen@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.0.0.tgz#5e32b12833e8aa8fa35e1bf0befa89380484c7dd" + integrity sha512-mmHKys/C8BFUGI+MAWNcSYoORYLMdPzjrknd2Vc+bUsjN5bXcr8EhrNB+UTqfL1y3I9c4fw2ihgtMPQLBRiQxw== + dependencies: + esprima "^4.0.1" + estraverse "^5.2.0" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.6.1" + esmangle-evaluator@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/esmangle-evaluator/-/esmangle-evaluator-1.0.1.tgz#620d866ef4861b3311f75766d52a8572bb3c6336" @@ -1296,11 +2280,26 @@ esprima@^2.7.1: resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= +esprima@^4.0.0, esprima@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + esprima@~3.1.0: version "3.1.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-3.1.3.tgz#fdca51cee6133895e3c88d535ce49dbff62a4633" integrity sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM= +estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + event-target-shim@^5.0.0: version "5.0.1" resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" @@ -1311,6 +2310,44 @@ events@1.1.1: resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= +exec-sh@^0.3.2: + version "0.3.6" + resolved "https://registry.yarnpkg.com/exec-sh/-/exec-sh-0.3.6.tgz#ff264f9e325519a60cb5e273692943483cca63bc" + integrity sha512-nQn+hI3yp+oD0huYhKwvYI32+JFeq+XkNcD1GAo3Y/MjxsfVGmrrzrnzjWiNY6f+pUCP440fThsFh5gZrRAU/w== + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-4.1.0.tgz#4e5491ad1572f2f17a77d388c6c857135b22847a" + integrity sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + +exit@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + integrity sha1-BjJjj42HfMghB9MKD/8aF8uhzQw= + expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -1324,6 +2361,18 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" +expect@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417" + integrity sha512-9/hlOBkQl2l/PLHJx6JjoDF6xPKcJEsUlWKb23rKE7KzeDqUZKXKNMW27KIue5JMdBV9HgmoJPcc8HtO85t9IA== + dependencies: + "@jest/types" "^26.6.2" + ansi-styles "^4.0.0" + jest-get-type "^26.3.0" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-regex-util "^26.0.0" + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -1339,6 +2388,11 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -1353,6 +2407,16 @@ extglob@^2.0.4: snapdragon "^0.8.1" to-regex "^3.0.1" +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + falafel@^1.0.1: version "1.2.0" resolved "https://registry.yarnpkg.com/falafel/-/falafel-1.2.0.tgz#c18d24ef5091174a497f318cd24b026a25cddab4" @@ -1370,6 +2434,21 @@ falafel@^1.0.1: dependencies: kind-of "^5.0.2" +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + fast-redact@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/fast-redact/-/fast-redact-3.0.0.tgz#ac2f9e36c9f4976f5db9fb18c6ffbaf308cf316d" @@ -1387,6 +2466,13 @@ fast-url-parser@^1.1.3: dependencies: punycode "^1.3.2" +fb-watchman@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.1.tgz#fc84fb39d2709cf3ff6d743706157bb5708a8a85" + integrity sha512-DkPJKQeY6kKwmuMretBhr7G6Vodr7bFwDYTXIkfG1gjvNpaxBTQV3PbXg6bR1c1UP4jPOX0jHUbbHANL9vRjVg== + dependencies: + bser "2.1.1" + fetch-cookie@0.10.1: version "0.10.1" resolved "https://registry.yarnpkg.com/fetch-cookie/-/fetch-cookie-0.10.1.tgz#5ea88f3d36950543c87997c27ae2aeafb4b5c4d4" @@ -1411,6 +2497,14 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + flatstr@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/flatstr/-/flatstr-1.0.12.tgz#c2ba6a08173edbb6c9640e3055b95e287ceb5931" @@ -1433,7 +2527,30 @@ foreach@^2.0.5: resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= -formidable@^1.1.1: +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +formidable@^1.1.1, formidable@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/formidable/-/formidable-1.2.2.tgz#bf69aea2972982675f00865342b982986f6b8dd9" integrity sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q== @@ -1455,16 +2572,45 @@ fs-exists-sync@^0.1.0: resolved "https://registry.yarnpkg.com/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz#982d6893af918e72d08dec9e8673ff2b5a8d6add" integrity sha1-mC1ok6+RjnLQjeyehnP/K1qNat0= -fsevents@~2.3.1: +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^2.1.2, fsevents@~2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-intrinsic@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" + integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + get-object@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/get-object/-/get-object-0.2.0.tgz#d92ff7d5190c64530cda0543dac63a3d47fe8c0c" @@ -1473,14 +2619,19 @@ get-object@^0.2.0: is-number "^2.0.2" isobject "^0.2.0" -get-stream@^4.1.0: +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== dependencies: pump "^3.0.0" -get-stream@^5.1.0: +get-stream@^5.0.0, get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== @@ -1492,6 +2643,13 @@ get-value@^2.0.3, get-value@^2.0.6: resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + glob-parent@~5.1.0: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -1510,6 +2668,18 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + global-dirs@^2.0.1: version "2.1.0" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.1.0.tgz#e9046a49c806ff04d6c1825e196c8f0091e8df4d" @@ -1517,6 +2687,11 @@ global-dirs@^2.0.1: dependencies: ini "1.3.7" +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + got@^11.8.1: version "11.8.1" resolved "https://registry.yarnpkg.com/got/-/got-11.8.1.tgz#df04adfaf2e782babb3daabc79139feec2f7e85d" @@ -1556,6 +2731,16 @@ graceful-fs@^4.1.2: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== +graceful-fs@^4.2.4: + version "4.2.6" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" + integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== + +growly@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" + integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= + gulp-header@^1.7.1: version "1.8.12" resolved "https://registry.yarnpkg.com/gulp-header/-/gulp-header-1.8.12.tgz#ad306be0066599127281c4f8786660e705080a84" @@ -1585,6 +2770,19 @@ handlebars@^4.0.11, handlebars@^4.7.6: optionalDependencies: uglify-js "^3.1.4" +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== + dependencies: + ajv "^6.12.3" + har-schema "^2.0.0" + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -1595,6 +2793,11 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has-symbols@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" + integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== + has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" @@ -1631,6 +2834,13 @@ has-yarn@^2.1.0: resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77" integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw== +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + helper-date@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/helper-date/-/helper-date-1.0.1.tgz#12fedea3ad8e44a7ca4c4efb0ff4104a5120cffb" @@ -1664,6 +2874,23 @@ highlight.js@^9.12.0: resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.5.tgz#d18a359867f378c138d6819edfc2a8acd5f29825" integrity sha512-a5bFyofd/BHCX52/8i8uJkjr9DYwXIPnM/plwI6W7ezItLGqzt7X2G2nXuYSfsIJdkwwj/g9DG1LkcGJI/dDoA== +hosted-git-info@^2.1.4: + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== + +html-encoding-sniffer@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/html-encoding-sniffer/-/html-encoding-sniffer-2.0.1.tgz#42a6dc4fd33f00281176e8b23759ca4e4fa185f3" + integrity sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ== + dependencies: + whatwg-encoding "^1.0.5" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + html-tag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/html-tag/-/html-tag-2.0.0.tgz#36c3bc8d816fd30b570d5764a497a641640c2fed" @@ -1717,6 +2944,15 @@ http-errors@~1.6.2: setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + http2-wrapper@^1.0.0-beta.5.2: version "1.0.0-beta.5.2" resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-1.0.0-beta.5.2.tgz#8b923deb90144aea65cf834b016a340fc98556f3" @@ -1725,6 +2961,11 @@ http2-wrapper@^1.0.0-beta.5.2: quick-lru "^5.1.1" resolve-alpn "^1.0.0" +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + iconv-lite@0.4.24, iconv-lite@^0.4.5: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" @@ -1762,6 +3003,14 @@ import-lazy@^2.1.0: resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= +import-local@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.0.2.tgz#a8cfd0431d1de4a2199703d003e3e62364fa6db6" + integrity sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA== + dependencies: + pkg-dir "^4.2.0" + resolve-cwd "^3.0.0" + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -1827,6 +3076,11 @@ is-accessor-descriptor@^1.0.0: dependencies: kind-of "^6.0.0" +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -1851,6 +3105,13 @@ is-class-hotfix@~0.0.6: resolved "https://registry.yarnpkg.com/is-class-hotfix/-/is-class-hotfix-0.0.6.tgz#a527d31fb23279281dde5f385c77b5de70a72435" integrity sha512-0n+pzCC6ICtVr/WXnN2f03TK/3BfXY7me4cjCAqT8TYXEl0+JBRoqBo94JJHXcyDSLUeWbNX8Fvy5g5RJdAstQ== +is-core-module@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.2.0.tgz#97037ef3d52224d85163f5597b2b63d9afed981a" + integrity sha512-XRAfAdyyY5F5cOXn7hYQDqh2Xmii+DEfIcQGxK/uNwMHhIkPWO0g8msXcbzLe+MpGoR951MlqM/2iIlU4vKDdQ== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -1883,6 +3144,11 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + is-even@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-even/-/is-even-1.0.0.tgz#76b5055fbad8d294a86b6a949015e1c97b717c06" @@ -1917,6 +3183,11 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-generator-fn@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== + is-generator-function@^1.0.7: version "1.0.8" resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.8.tgz#dfb5c2b120e02b0a8d9d2c6806cd5621aa922f7b" @@ -1990,6 +3261,11 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-potential-custom-element-name@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" + integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== + is-self-closing@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-self-closing/-/is-self-closing-1.0.1.tgz#5f406b527c7b12610176320338af0fa3896416e4" @@ -1997,6 +3273,16 @@ is-self-closing@^1.0.1: dependencies: self-closing-tags "^1.0.1" +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + is-type-of@^1.0.0: version "1.2.1" resolved "https://registry.yarnpkg.com/is-type-of/-/is-type-of-1.2.1.tgz#e263ec3857aceb4f28c47130ec78db09a920f8c5" @@ -2006,7 +3292,7 @@ is-type-of@^1.0.0: is-class-hotfix "~0.0.6" isstream "~0.1.2" -is-typedarray@^1.0.0: +is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= @@ -2016,6 +3302,13 @@ is-windows@^1.0.2: resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + is-yarn-global@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232" @@ -2031,6 +3324,11 @@ isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + isobject@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-0.2.0.tgz#a3432192f39b910b5f02cc989487836ec70aa85e" @@ -2053,6 +3351,420 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +istanbul-lib-coverage@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz#f5944a37c70b550b02a78a5c3b2055b280cec8ec" + integrity sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg== + +istanbul-lib-instrument@^4.0.0, istanbul-lib-instrument@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== + dependencies: + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz#75743ce6d96bb86dc7ee4352cf6366a23f0b1ad9" + integrity sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.2.tgz#d593210e5000683750cb09fc0644e4b6e27fd53b" + integrity sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jest-changed-files@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.6.2.tgz#f6198479e1cc66f22f9ae1e22acaa0b429c042d0" + integrity sha512-fDS7szLcY9sCtIip8Fjry9oGf3I2ht/QT21bAHm5Dmf0mD4X3ReNUf17y+bO6fR8WgbIZTlbyG1ak/53cbRzKQ== + dependencies: + "@jest/types" "^26.6.2" + execa "^4.0.0" + throat "^5.0.0" + +jest-cli@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-cli/-/jest-cli-26.6.3.tgz#43117cfef24bc4cd691a174a8796a532e135e92a" + integrity sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg== + dependencies: + "@jest/core" "^26.6.3" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + chalk "^4.0.0" + exit "^0.1.2" + graceful-fs "^4.2.4" + import-local "^3.0.2" + is-ci "^2.0.0" + jest-config "^26.6.3" + jest-util "^26.6.2" + jest-validate "^26.6.2" + prompts "^2.0.1" + yargs "^15.4.1" + +jest-config@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-config/-/jest-config-26.6.3.tgz#64f41444eef9eb03dc51d5c53b75c8c71f645349" + integrity sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg== + dependencies: + "@babel/core" "^7.1.0" + "@jest/test-sequencer" "^26.6.3" + "@jest/types" "^26.6.2" + babel-jest "^26.6.3" + chalk "^4.0.0" + deepmerge "^4.2.2" + glob "^7.1.1" + graceful-fs "^4.2.4" + jest-environment-jsdom "^26.6.2" + jest-environment-node "^26.6.2" + jest-get-type "^26.3.0" + jest-jasmine2 "^26.6.3" + jest-regex-util "^26.0.0" + jest-resolve "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" + micromatch "^4.0.2" + pretty-format "^26.6.2" + +jest-diff@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-26.6.2.tgz#1aa7468b52c3a68d7d5c5fdcdfcd5e49bd164394" + integrity sha512-6m+9Z3Gv9wN0WFVasqjCL/06+EFCMTqDEUl/b87HYK2rAPTyfz4ZIuSlPhY51PIQRWx5TaxeF1qmXKe9gfN3sA== + dependencies: + chalk "^4.0.0" + diff-sequences "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + +jest-docblock@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-26.0.0.tgz#3e2fa20899fc928cb13bd0ff68bd3711a36889b5" + integrity sha512-RDZ4Iz3QbtRWycd8bUEPxQsTlYazfYn/h5R65Fc6gOfwozFhoImx+affzky/FFBuqISPTqjXomoIGJVKBWoo0w== + dependencies: + detect-newline "^3.0.0" + +jest-each@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-each/-/jest-each-26.6.2.tgz#02526438a77a67401c8a6382dfe5999952c167cb" + integrity sha512-Mer/f0KaATbjl8MCJ+0GEpNdqmnVmDYqCTJYTvoo7rqmRiDllmp2AYN+06F93nXcY3ur9ShIjS+CO/uD+BbH4A== + dependencies: + "@jest/types" "^26.6.2" + chalk "^4.0.0" + jest-get-type "^26.3.0" + jest-util "^26.6.2" + pretty-format "^26.6.2" + +jest-environment-jsdom@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-26.6.2.tgz#78d09fe9cf019a357009b9b7e1f101d23bd1da3e" + integrity sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q== + dependencies: + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + jest-mock "^26.6.2" + jest-util "^26.6.2" + jsdom "^16.4.0" + +jest-environment-node@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-environment-node/-/jest-environment-node-26.6.2.tgz#824e4c7fb4944646356f11ac75b229b0035f2b0c" + integrity sha512-zhtMio3Exty18dy8ee8eJ9kjnRyZC1N4C1Nt/VShN1apyXc8rWGtJ9lI7vqiWcyyXS4BVSEn9lxAM2D+07/Tag== + dependencies: + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + jest-mock "^26.6.2" + jest-util "^26.6.2" + +jest-get-type@^26.3.0: + version "26.3.0" + resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-26.3.0.tgz#e97dc3c3f53c2b406ca7afaed4493b1d099199e0" + integrity sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig== + +jest-haste-map@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-haste-map/-/jest-haste-map-26.6.2.tgz#dd7e60fe7dc0e9f911a23d79c5ff7fb5c2cafeaa" + integrity sha512-easWIJXIw71B2RdR8kgqpjQrbMRWQBgiBwXYEhtGUTaX+doCjBheluShdDMeR8IMfJiTqH4+zfhtg29apJf/8w== + dependencies: + "@jest/types" "^26.6.2" + "@types/graceful-fs" "^4.1.2" + "@types/node" "*" + anymatch "^3.0.3" + fb-watchman "^2.0.0" + graceful-fs "^4.2.4" + jest-regex-util "^26.0.0" + jest-serializer "^26.6.2" + jest-util "^26.6.2" + jest-worker "^26.6.2" + micromatch "^4.0.2" + sane "^4.0.3" + walker "^1.0.7" + optionalDependencies: + fsevents "^2.1.2" + +jest-jasmine2@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-jasmine2/-/jest-jasmine2-26.6.3.tgz#adc3cf915deacb5212c93b9f3547cd12958f2edd" + integrity sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg== + dependencies: + "@babel/traverse" "^7.1.0" + "@jest/environment" "^26.6.2" + "@jest/source-map" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + co "^4.6.0" + expect "^26.6.2" + is-generator-fn "^2.0.0" + jest-each "^26.6.2" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-runtime "^26.6.3" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + pretty-format "^26.6.2" + throat "^5.0.0" + +jest-leak-detector@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-leak-detector/-/jest-leak-detector-26.6.2.tgz#7717cf118b92238f2eba65054c8a0c9c653a91af" + integrity sha512-i4xlXpsVSMeKvg2cEKdfhh0H39qlJlP5Ex1yQxwF9ubahboQYMgTtz5oML35AVA3B4Eu+YsmwaiKVev9KCvLxg== + dependencies: + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + +jest-matcher-utils@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-26.6.2.tgz#8e6fd6e863c8b2d31ac6472eeb237bc595e53e7a" + integrity sha512-llnc8vQgYcNqDrqRDXWwMr9i7rS5XFiCwvh6DTP7Jqa2mqpcCBBlpCbn+trkG0KNhPu/h8rzyBkriOtBstvWhw== + dependencies: + chalk "^4.0.0" + jest-diff "^26.6.2" + jest-get-type "^26.3.0" + pretty-format "^26.6.2" + +jest-message-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-26.6.2.tgz#58173744ad6fc0506b5d21150b9be56ef001ca07" + integrity sha512-rGiLePzQ3AzwUshu2+Rn+UMFk0pHN58sOG+IaJbk5Jxuqo3NYO1U2/MIR4S1sKgsoYSXSzdtSa0TgrmtUwEbmA== + dependencies: + "@babel/code-frame" "^7.0.0" + "@jest/types" "^26.6.2" + "@types/stack-utils" "^2.0.0" + chalk "^4.0.0" + graceful-fs "^4.2.4" + micromatch "^4.0.2" + pretty-format "^26.6.2" + slash "^3.0.0" + stack-utils "^2.0.2" + +jest-mock@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-mock/-/jest-mock-26.6.2.tgz#d6cb712b041ed47fe0d9b6fc3474bc6543feb302" + integrity sha512-YyFjePHHp1LzpzYcmgqkJ0nm0gg/lJx2aZFzFy1S6eUqNjXsOqTK10zNRff2dNfssgokjkG65OlWNcIlgd3zew== + dependencies: + "@jest/types" "^26.6.2" + "@types/node" "*" + +jest-pnp-resolver@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz#b704ac0ae028a89108a4d040b3f919dfddc8e33c" + integrity sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w== + +jest-regex-util@^26.0.0: + version "26.0.0" + resolved "https://registry.yarnpkg.com/jest-regex-util/-/jest-regex-util-26.0.0.tgz#d25e7184b36e39fd466c3bc41be0971e821fee28" + integrity sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A== + +jest-resolve-dependencies@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-resolve-dependencies/-/jest-resolve-dependencies-26.6.3.tgz#6680859ee5d22ee5dcd961fe4871f59f4c784fb6" + integrity sha512-pVwUjJkxbhe4RY8QEWzN3vns2kqyuldKpxlxJlzEYfKSvY6/bMvxoFrYYzUO1Gx28yKWN37qyV7rIoIp2h8fTg== + dependencies: + "@jest/types" "^26.6.2" + jest-regex-util "^26.0.0" + jest-snapshot "^26.6.2" + +jest-resolve@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-resolve/-/jest-resolve-26.6.2.tgz#a3ab1517217f469b504f1b56603c5bb541fbb507" + integrity sha512-sOxsZOq25mT1wRsfHcbtkInS+Ek7Q8jCHUB0ZUTP0tc/c41QHriU/NunqMfCUWsL4H3MHpvQD4QR9kSYhS7UvQ== + dependencies: + "@jest/types" "^26.6.2" + chalk "^4.0.0" + graceful-fs "^4.2.4" + jest-pnp-resolver "^1.2.2" + jest-util "^26.6.2" + read-pkg-up "^7.0.1" + resolve "^1.18.1" + slash "^3.0.0" + +jest-runner@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-runner/-/jest-runner-26.6.3.tgz#2d1fed3d46e10f233fd1dbd3bfaa3fe8924be159" + integrity sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ== + dependencies: + "@jest/console" "^26.6.2" + "@jest/environment" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + emittery "^0.7.1" + exit "^0.1.2" + graceful-fs "^4.2.4" + jest-config "^26.6.3" + jest-docblock "^26.0.0" + jest-haste-map "^26.6.2" + jest-leak-detector "^26.6.2" + jest-message-util "^26.6.2" + jest-resolve "^26.6.2" + jest-runtime "^26.6.3" + jest-util "^26.6.2" + jest-worker "^26.6.2" + source-map-support "^0.5.6" + throat "^5.0.0" + +jest-runtime@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest-runtime/-/jest-runtime-26.6.3.tgz#4f64efbcfac398331b74b4b3c82d27d401b8fa2b" + integrity sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw== + dependencies: + "@jest/console" "^26.6.2" + "@jest/environment" "^26.6.2" + "@jest/fake-timers" "^26.6.2" + "@jest/globals" "^26.6.2" + "@jest/source-map" "^26.6.2" + "@jest/test-result" "^26.6.2" + "@jest/transform" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/yargs" "^15.0.0" + chalk "^4.0.0" + cjs-module-lexer "^0.6.0" + collect-v8-coverage "^1.0.0" + exit "^0.1.2" + glob "^7.1.3" + graceful-fs "^4.2.4" + jest-config "^26.6.3" + jest-haste-map "^26.6.2" + jest-message-util "^26.6.2" + jest-mock "^26.6.2" + jest-regex-util "^26.0.0" + jest-resolve "^26.6.2" + jest-snapshot "^26.6.2" + jest-util "^26.6.2" + jest-validate "^26.6.2" + slash "^3.0.0" + strip-bom "^4.0.0" + yargs "^15.4.1" + +jest-serializer@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-serializer/-/jest-serializer-26.6.2.tgz#d139aafd46957d3a448f3a6cdabe2919ba0742d1" + integrity sha512-S5wqyz0DXnNJPd/xfIzZ5Xnp1HrJWBczg8mMfMpN78OJ5eDxXyf+Ygld9wX1DnUWbIbhM1YDY95NjR4CBXkb2g== + dependencies: + "@types/node" "*" + graceful-fs "^4.2.4" + +jest-snapshot@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-snapshot/-/jest-snapshot-26.6.2.tgz#f3b0af1acb223316850bd14e1beea9837fb39c84" + integrity sha512-OLhxz05EzUtsAmOMzuupt1lHYXCNib0ECyuZ/PZOx9TrZcC8vL0x+DUG3TL+GLX3yHG45e6YGjIm0XwDc3q3og== + dependencies: + "@babel/types" "^7.0.0" + "@jest/types" "^26.6.2" + "@types/babel__traverse" "^7.0.4" + "@types/prettier" "^2.0.0" + chalk "^4.0.0" + expect "^26.6.2" + graceful-fs "^4.2.4" + jest-diff "^26.6.2" + jest-get-type "^26.3.0" + jest-haste-map "^26.6.2" + jest-matcher-utils "^26.6.2" + jest-message-util "^26.6.2" + jest-resolve "^26.6.2" + natural-compare "^1.4.0" + pretty-format "^26.6.2" + semver "^7.3.2" + +jest-util@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-26.6.2.tgz#907535dbe4d5a6cb4c47ac9b926f6af29576cbc1" + integrity sha512-MDW0fKfsn0OI7MS7Euz6h8HNDXVQ0gaM9uW6RjfDmd1DAFcaxX9OqIakHIqhbnmF08Cf2DLDG+ulq8YQQ0Lp0Q== + dependencies: + "@jest/types" "^26.6.2" + "@types/node" "*" + chalk "^4.0.0" + graceful-fs "^4.2.4" + is-ci "^2.0.0" + micromatch "^4.0.2" + +jest-validate@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-26.6.2.tgz#23d380971587150467342911c3d7b4ac57ab20ec" + integrity sha512-NEYZ9Aeyj0i5rQqbq+tpIOom0YS1u2MVu6+euBsvpgIme+FOfRmoC4R5p0JiAUpaFvFy24xgrpMknarR/93XjQ== + dependencies: + "@jest/types" "^26.6.2" + camelcase "^6.0.0" + chalk "^4.0.0" + jest-get-type "^26.3.0" + leven "^3.1.0" + pretty-format "^26.6.2" + +jest-watcher@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-watcher/-/jest-watcher-26.6.2.tgz#a5b683b8f9d68dbcb1d7dae32172d2cca0592975" + integrity sha512-WKJob0P/Em2csiVthsI68p6aGKTIcsfjH9Gsx1f0A3Italz43e3ho0geSAVsmj09RWOELP1AZ/DXyJgOgDKxXQ== + dependencies: + "@jest/test-result" "^26.6.2" + "@jest/types" "^26.6.2" + "@types/node" "*" + ansi-escapes "^4.2.1" + chalk "^4.0.0" + jest-util "^26.6.2" + string-length "^4.0.1" + +jest-worker@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" + integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^7.0.0" + +jest@^26.6.3: + version "26.6.3" + resolved "https://registry.yarnpkg.com/jest/-/jest-26.6.3.tgz#40e8fdbe48f00dfa1f0ce8121ca74b88ac9148ef" + integrity sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q== + dependencies: + "@jest/core" "^26.6.3" + import-local "^3.0.2" + jest-cli "^26.6.3" + jmespath@0.15.0, jmespath@^0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" @@ -2074,6 +3786,61 @@ joycon@^2.2.5: resolved "https://registry.yarnpkg.com/joycon/-/joycon-2.2.5.tgz#8d4cf4cbb2544d7b7583c216fcdfec19f6be1615" integrity sha512-YqvUxoOcVPnCp0VU1/56f+iKSdvIRJYPznH22BdXV3xMk75SFXhWeJkZ8C9XxUWt1b5x2X1SxuFygW1U0FmkEQ== +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +jsdom@^16.4.0: + version "16.5.3" + resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-16.5.3.tgz#13a755b3950eb938b4482c407238ddf16f0d2136" + integrity sha512-Qj1H+PEvUsOtdPJ056ewXM4UJPCi4hhLA8wpiz9F2YvsRBhuFsXxtrIFAgGBDynQA9isAMGE91PfUYbdMPXuTA== + dependencies: + abab "^2.0.5" + acorn "^8.1.0" + acorn-globals "^6.0.0" + cssom "^0.4.4" + cssstyle "^2.3.0" + data-urls "^2.0.0" + decimal.js "^10.2.1" + domexception "^2.0.1" + escodegen "^2.0.0" + html-encoding-sniffer "^2.0.1" + is-potential-custom-element-name "^1.0.0" + nwsapi "^2.2.0" + parse5 "6.0.1" + request "^2.88.2" + request-promise-native "^1.0.9" + saxes "^5.0.1" + symbol-tree "^3.2.4" + tough-cookie "^4.0.0" + w3c-hr-time "^1.0.2" + w3c-xmlserializer "^2.0.0" + webidl-conversions "^6.1.0" + whatwg-encoding "^1.0.5" + whatwg-mimetype "^2.3.0" + whatwg-url "^8.5.0" + ws "^7.4.4" + xml-name-validator "^3.0.0" + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + json-buffer@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" @@ -2084,6 +3851,33 @@ json-buffer@3.0.1: resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json5@^2.1.2: + version "2.2.0" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" + integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== + dependencies: + minimist "^1.2.5" + jsonwebtoken@^8.2.0: version "8.5.1" resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d" @@ -2100,6 +3894,16 @@ jsonwebtoken@^8.2.0: ms "^2.1.1" semver "^5.6.0" +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + jstransform@~11.0.0: version "11.0.3" resolved "https://registry.yarnpkg.com/jstransform/-/jstransform-11.0.3.tgz#09a78993e0ae4d4ef4487f6155a91f6190cb4223" @@ -2182,6 +3986,11 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== +kleur@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== + koa-body@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/koa-body/-/koa-body-4.2.0.tgz#37229208b820761aca5822d14c5fc55cee31b26f" @@ -2405,6 +4214,19 @@ leven@2.1.0: resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" integrity sha1-wuep93IJTe6dNCAq6KzORoeHVYA= +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + lie@3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/lie/-/lie-3.0.4.tgz#bc7ae1ebe7f1c8de39afdcd4f789076b47b0f634" @@ -2415,6 +4237,18 @@ lie@3.0.4: inline-process-browser "^1.0.0" unreachable-branch-transform "^0.3.0" +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -2470,7 +4304,7 @@ lodash.templatesettings@^4.0.0: dependencies: lodash._reinterpolate "^3.0.0" -lodash@^4.17.20: +lodash@^4.17.19, lodash@^4.17.20, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -2514,6 +4348,13 @@ lowercase-keys@^2.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + ltgt@2.2.1, ltgt@^2.1.2, ltgt@~2.2.0: version "2.2.1" resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" @@ -2526,6 +4367,13 @@ make-dir@^3.0.0: dependencies: semver "^6.0.0" +makeerror@1.0.x: + version "1.0.11" + resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.11.tgz#e01a5c9109f2af79660e4e8b9587790184f5a96c" + integrity sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw= + dependencies: + tmpl "1.0.x" + map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" @@ -2555,6 +4403,11 @@ memdown@1.4.1: ltgt "~2.2.0" safe-buffer "~5.1.1" +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + methods@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -2579,16 +4432,36 @@ micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" +micromatch@^4.0.2: + version "4.0.4" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" + integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== + dependencies: + braces "^3.0.1" + picomatch "^2.2.3" + mime-db@1.44.0: version "1.44.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== +mime-db@1.47.0: + version "1.47.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c" + integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw== + "mime-db@>= 1.43.0 < 2": version "1.45.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.30" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d" + integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg== + dependencies: + mime-db "1.47.0" + mime-types@^2.1.18, mime-types@~2.1.24: version "2.1.27" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" @@ -2596,6 +4469,16 @@ mime-types@^2.1.18, mime-types@~2.1.24: dependencies: mime-db "1.44.0" +mime@^2.4.6: + version "2.5.2" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.5.2.tgz#6e3dc6cc2b9510643830e5f19d5cb753da5eeabe" + integrity sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + mimic-response@^1.0.0, mimic-response@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" @@ -2613,7 +4496,7 @@ mimic-response@^3.1.0: dependencies: brace-expansion "^1.1.7" -minimist@^1.2.0, minimist@^1.2.5: +minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== @@ -2680,6 +4563,11 @@ napi-macros@~2.0.0: resolved "https://registry.yarnpkg.com/napi-macros/-/napi-macros-2.0.0.tgz#2b6bae421e7b96eb687aa6c77a7858640670001b" integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg== +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" @@ -2690,6 +4578,11 @@ neo-async@^2.6.0: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + node-fetch@2.6.0: version "2.6.0" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" @@ -2705,6 +4598,33 @@ node-gyp-build@~4.1.0: resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.1.1.tgz#d7270b5d86717068d114cc57fff352f96d745feb" integrity sha512-dSq1xmcPDKPZ2EED2S6zw/b9NKsqzXRE6dVr8TVQnI3FJOTteUMuqF3Qqs6LZg+mLGYJWqQzMbIjMtJqTv87nQ== +node-int64@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" + integrity sha1-h6kGXNs1XTGC2PlM4RGIuCXGijs= + +node-modules-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz#8d9dbe28964a4ac5712e9131642107c71e90ec40" + integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA= + +node-notifier@^8.0.0: + version "8.0.2" + resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.2.tgz#f3167a38ef0d2c8a866a83e318c1ba0efeb702c5" + integrity sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg== + dependencies: + growly "^1.3.0" + is-wsl "^2.2.0" + semver "^7.3.2" + shellwords "^0.1.1" + uuid "^8.3.0" + which "^2.0.2" + +node-releases@^1.1.71: + version "1.1.71" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.71.tgz#cb1334b179896b1c89ecfdd4b725fb7bbdfc7dbb" + integrity sha512-zR6HoT6LrLCRBwukmrVbHv0EpEQjksO6GmFcZQQuCAy139BEsoVKPYnf3jongYW83fAa1torLGYwxxky/p28sg== + nodemailer@^6.5.0: version "6.5.0" resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.5.0.tgz#d12c28d8d48778918e25f1999d97910231b175d9" @@ -2733,6 +4653,23 @@ nopt@~1.0.10: dependencies: abbrev "1" +normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -2743,6 +4680,30 @@ normalize-url@^4.1.0: resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ== +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +npm-run-path@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +nwsapi@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7" + integrity sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ== + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + oauth@0.9.x: version "0.9.15" resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1" @@ -2762,6 +4723,11 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" +object-inspect@^1.9.0: + version "1.10.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.2.tgz#b6385a3e2b7cae0b5eafcf90cddf85d128767f30" + integrity sha512-gz58rdPpadwztRrPjZE9DZLOABUpTGdcANUgOwBFO1C+HZZhePoP83M65WGDmbpwFYJSWqavbl4SgDn4k8RYTA== + object-keys@^1.0.6: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" @@ -2795,11 +4761,30 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0: dependencies: wrappy "1" +onetime@^5.1.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + only@~0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/only/-/only-0.0.2.tgz#2afde84d03e50b9a8edc444e30610a70295edfb4" integrity sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q= +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + p-cancelable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" @@ -2810,6 +4795,35 @@ p-cancelable@^2.0.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.0.0.tgz#4a3740f5bdaf5ed5d7c3e34882c6fb5d6b266a6e" integrity sha512-wvPXDmbMmu2ksjkB4Z3nZWTSkJEb9lqVdMaCKpZUGJG9TMiNp9XcbG3fn9fPKjem04fJMJnXoyFPk2FmgiaiNg== +p-each-series@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.2.0.tgz#105ab0357ce72b202a8a8b94933672657b5e2a9a" + integrity sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA== + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + package-json@^6.3.0: version "6.5.0" resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0" @@ -2820,6 +4834,21 @@ package-json@^6.3.0: registry-url "^5.0.0" semver "^6.2.0" +parse-json@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" + integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + +parse5@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + parseurl@^1.3.2: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -2900,11 +4929,31 @@ passport@^0.4.0: passport-strategy "1.x.x" pause "0.0.1" +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@1.0.1, path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + path-to-regexp@1.x: version "1.8.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" @@ -2917,11 +4966,21 @@ pause@0.0.1: resolved "https://registry.yarnpkg.com/pause/-/pause-0.0.1.tgz#1d408b3fdb76923b9543d96fb4c9dfd535d9cb5d" integrity sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10= +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + picomatch@^2.0.4, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== +picomatch@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.3.tgz#465547f359ccc206d3c48e46a1bcb89bf7ee619d" + integrity sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg== + pino-http@^5.0.1: version "5.3.0" resolved "https://registry.yarnpkg.com/pino-http/-/pino-http-5.3.0.tgz#8ad9c296a60220b8d7067800a63c8716a622c661" @@ -2965,6 +5024,20 @@ pino@^6.0.0: quick-format-unescaped "^4.0.1" sonic-boom "^1.0.2" +pirates@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.1.tgz#643a92caf894566f91b2b986d2c66950a8e2fb87" + integrity sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA== + dependencies: + node-modules-regexp "^1.0.0" + +pkg-dir@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -3108,11 +5181,26 @@ pouchdb@^7.2.1: uuid "8.1.0" vuvuzela "1.0.3" +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + prepend-http@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= +pretty-format@^26.6.2: + version "26.6.2" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-26.6.2.tgz#e35c2705f14cb7fe2fe94fa078345b444120fc93" + integrity sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg== + dependencies: + "@jest/types" "^26.6.2" + ansi-regex "^5.0.0" + ansi-styles "^4.0.0" + react-is "^17.0.1" + private@^0.1.6, private@~0.1.5: version "0.1.8" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" @@ -3123,12 +5211,20 @@ process-nextick-args@~2.0.0: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +prompts@^2.0.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.1.tgz#befd3b1195ba052f9fd2fde8a486c4e82ee77f61" + integrity sha512-EQyfIuO2hPDsX1L/blblV+H7I0knhgAd82cVneCwcdND9B8AuCDuRcBH6yIcG4dFzlOUqbazQqwGjx5xmsNLuQ== + dependencies: + kleur "^3.0.3" + sisteransi "^1.0.5" + prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= -psl@^1.1.33: +psl@^1.1.28, psl@^1.1.33: version "1.8.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== @@ -3156,7 +5252,7 @@ punycode@^1.3.2: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= -punycode@^2.1.1: +punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== @@ -3178,6 +5274,18 @@ qs@^6.4.0: resolved "https://registry.yarnpkg.com/qs/-/qs-6.9.4.tgz#9090b290d1f91728d3c22e54843ca44aea5ab687" integrity sha512-A1kFqHekCTM7cz0udomYUoYNWjBebHm/5wzU/XqrBRBNWectVH0QIiN+NEcZ0Dte5hvzHwbr8+XQmguPhJ6WdQ== +qs@^6.9.4: + version "6.10.1" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.1.tgz#4931482fa8d647a5aab799c5271d2133b981fb6a" + integrity sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg== + dependencies: + side-channel "^1.0.4" + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + querystring@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" @@ -3213,6 +5321,30 @@ rc@^1.2.8: minimist "^1.2.0" strip-json-comments "~2.0.1" +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + readable-stream@1.1.14: version "1.1.14" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" @@ -3324,6 +5456,11 @@ remarkable@^1.6.2, remarkable@^1.7.1: argparse "^1.0.10" autolinker "~0.28.0" +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + repeat-element@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" @@ -3334,11 +5471,75 @@ repeat-string@^1.6.1: resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= +request-promise-core@1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" + integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== + dependencies: + lodash "^4.17.19" + +request-promise-native@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.9.tgz#e407120526a5efdc9a39b28a5679bf47b9d9dc28" + integrity sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g== + dependencies: + request-promise-core "1.1.4" + stealthy-require "^1.1.1" + tough-cookie "^2.3.3" + +request@^2.88.2: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + resolve-alpn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.0.0.tgz#745ad60b3d6aff4b4a48e01b8c0bdc70959e0e8c" integrity sha512-rTuiIEqFmGxne4IovivKSDzld2lWW9QCjqv80SYjPgf+gS35eaCAjaP54CCwGAwBtnCsvNLYtqxe1Nw+i6JEmA== +resolve-cwd@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" + integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== + dependencies: + resolve-from "^5.0.0" + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-path@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/resolve-path/-/resolve-path-1.4.0.tgz#c4bda9f5efb2fce65247873ab36bb4d834fe16f7" @@ -3352,6 +5553,14 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= +resolve@^1.10.0, resolve@^1.18.1: + version "1.20.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" + integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + dependencies: + is-core-module "^2.2.0" + path-parse "^1.0.6" + responselike@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" @@ -3371,12 +5580,24 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +rimraf@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rsvp@^4.8.4: + version "4.8.5" + resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" + integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@^5.0.1, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -3388,11 +5609,26 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3": +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +sane@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/sane/-/sane-4.1.0.tgz#ed881fd922733a6c461bc189dc2b6c006f3ffded" + integrity sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA== + dependencies: + "@cnakazawa/watch" "^1.0.3" + anymatch "^2.0.0" + capture-exit "^2.0.0" + exec-sh "^0.3.2" + execa "^1.0.0" + fb-watchman "^2.0.0" + micromatch "^3.1.4" + minimist "^1.1.1" + walker "~1.0.5" + sax@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.1.tgz#7b8e656190b228e81a66aea748480d828cd2d37a" @@ -3403,6 +5639,13 @@ sax@>=0.6.0: resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== +saxes@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== + dependencies: + xmlchars "^2.2.0" + self-closing-tags@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/self-closing-tags/-/self-closing-tags-1.0.1.tgz#6c5fa497994bb826b484216916371accee490a5d" @@ -3415,7 +5658,7 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -semver@^5.6.0, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -3425,11 +5668,23 @@ semver@^6.0.0, semver@^6.2.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.3.2: + version "7.3.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" + integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== + dependencies: + lru-cache "^6.0.0" + server-destroy@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/server-destroy/-/server-destroy-1.0.1.tgz#f13bf928e42b9c3e79383e61cc3998b5d14e6cdd" integrity sha1-8Tv5KOQrnD55OD5hzDmYtdFObN0= +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + set-getter@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/set-getter/-/set-getter-0.1.0.tgz#d769c182c9d5a51f409145f2fba82e5e86e80376" @@ -3462,11 +5717,59 @@ setprototypeof@1.2.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -signal-exit@^3.0.2: +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shellwords@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" + integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -3516,6 +5819,14 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" +source-map-support@^0.5.6: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" @@ -3535,21 +5846,52 @@ source-map@^0.4.2: dependencies: amdefine ">=0.0.4" -source-map@^0.5.6, source-map@~0.5.0: +source-map@^0.5.0, source-map@^0.5.6, source-map@~0.5.0: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@^0.6.1: +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +source-map@^0.7.3: + version "0.7.3" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" + integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== + spark-md5@3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/spark-md5/-/spark-md5-3.0.1.tgz#83a0e255734f2ab4e5c466e5a2cfc9ba2aa2124d" integrity sha512-0tF3AGSD1ppQeuffsLDIOWlKUd3lS92tFxcsrh5Pe3ZphhnoK+oXIBTzOAThZCiuINZLvpiLH/1VS1/ANEJVig== +spdx-correct@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + +spdx-expression-parse@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.7" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.7.tgz#e9c18a410e5ed7e12442a549fbd8afa767038d65" + integrity sha512-U+MTEOO0AiDzxwFvoa4JVnMV6mZlJKk2sBLt90s7G0Gd0Mlknc7kxEn3nuDPNZRta7O2uy8oLcZLVT+4sqNZHQ== + split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" @@ -3569,6 +5911,28 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +stack-utils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.3.tgz#cd5f030126ff116b78ccb3c027fe302713b61277" + integrity sha512-gL//fkxfWUsIlFL2Tl42Cl6+HFALEaB1FU76I/Fy+oZjRreP7OPMXFlGbxM7NQsI0ZpUfw76sHnv0WNYuTb7Iw== + dependencies: + escape-string-regexp "^2.0.0" + static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" @@ -3587,6 +5951,19 @@ statuses@^2.0.0: resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.0.tgz#aa7b107e018eb33e08e8aee2e7337e762dda1028" integrity sha512-w9jNUUQdpuVoYqXxnyOakhckBbOxRaoYqJscyIBYCS5ixyCnO7nQn7zBZvP9zf5QOPZcz2DLUpE3KsNPbJBOFA== +stealthy-require@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" + integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks= + +string-length@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" + integrity sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ== + dependencies: + char-regex "^1.0.2" + strip-ansi "^6.0.0" + string-width@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" @@ -3596,7 +5973,7 @@ string-width@^3.0.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.0.0, string-width@^4.1.0: +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0: version "4.2.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== @@ -3638,6 +6015,21 @@ strip-ansi@^6.0.0: dependencies: ansi-regex "^5.0.0" +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" @@ -3668,6 +6060,31 @@ success-symbol@^0.1.0: resolved "https://registry.yarnpkg.com/success-symbol/-/success-symbol-0.1.0.tgz#24022e486f3bf1cdca094283b769c472d3b72897" integrity sha1-JAIuSG878c3KCUKDt2nEctO3KJc= +superagent@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/superagent/-/superagent-6.1.0.tgz#09f08807bc41108ef164cfb4be293cebd480f4a6" + integrity sha512-OUDHEssirmplo3F+1HWKUrUjvnQuA+nZI6i/JJBdXb5eq9IyEQwPyPpqND+SSsxf6TygpBEkUjISVRN4/VOpeg== + dependencies: + component-emitter "^1.3.0" + cookiejar "^2.1.2" + debug "^4.1.1" + fast-safe-stringify "^2.0.7" + form-data "^3.0.0" + formidable "^1.2.2" + methods "^1.1.2" + mime "^2.4.6" + qs "^6.9.4" + readable-stream "^3.6.0" + semver "^7.3.2" + +supertest@^6.1.3: + version "6.1.3" + resolved "https://registry.yarnpkg.com/supertest/-/supertest-6.1.3.tgz#3f49ea964514c206c334073e8dc4e70519c7403f" + integrity sha512-v2NVRyP73XDewKb65adz+yug1XMtmvij63qIWHZzSX8tp6wiq6xBLUy4SUAd2NII6wIipOmHT/FD9eicpJwdgQ== + dependencies: + methods "^1.1.2" + superagent "^6.1.0" + supports-color@^5.3.0, supports-color@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -3675,18 +6092,53 @@ supports-color@^5.3.0, supports-color@^5.5.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0: +supports-color@^7.0.0, supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== dependencies: has-flag "^4.0.0" +supports-hyperlinks@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/supports-hyperlinks/-/supports-hyperlinks-2.2.0.tgz#4f77b42488765891774b70c79babd87f9bd594bb" + integrity sha512-6sXEzV5+I5j8Bmq9/vUphGRM/RJNT9SCURJLjwfOg51heRtguGWDzcaBlgAzKhQa0EVNpPEKzQuBwZ8S8WaCeQ== + dependencies: + has-flag "^4.0.0" + supports-color "^7.0.0" + +symbol-tree@^3.2.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" + integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== + term-size@^2.1.0: version "2.2.1" resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" integrity sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg== +terminal-link@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" + integrity sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ== + dependencies: + ansi-escapes "^4.2.1" + supports-hyperlinks "^2.0.0" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +throat@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/throat/-/throat-5.0.0.tgz#c5199235803aad18754a667d659b5e72ce16764b" + integrity sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA== + through2@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4" @@ -3726,6 +6178,16 @@ tiny-queue@^0.2.0: resolved "https://registry.yarnpkg.com/tiny-queue/-/tiny-queue-0.2.1.tgz#25a67f2c6e253b2ca941977b5ef7442ef97a6046" integrity sha1-JaZ/LG4lOyypQZd7XvdELvl6YEY= +tmpl@1.0.x: + version "1.0.4" + resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" + integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + to-gfm-code-block@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/to-gfm-code-block/-/to-gfm-code-block-0.1.1.tgz#25d045a5fae553189e9637b590900da732d8aa82" @@ -3780,7 +6242,15 @@ touch@^3.1.0: dependencies: nopt "~1.0.10" -"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0": +tough-cookie@^2.3.3, tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +"tough-cookie@^2.3.3 || ^3.0.1 || ^4.0.0", tough-cookie@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4" integrity sha512-tHdtEpQCMrc1YLrMaqXXcj6AxhYi/xgit6mZu1+EDWUn+qhUf8wMQoFIy9NXuq23zAwtcB0t/MjACGR18pcRbg== @@ -3789,11 +6259,52 @@ touch@^3.1.0: punycode "^2.1.1" universalify "^0.1.2" +tr46@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-2.0.2.tgz#03273586def1595ae08fedb38d7733cee91d2479" + integrity sha512-3n1qG+/5kg+jrbTzwAykB5yRYtQCTqOGKq5U5PE3b0a1/mzo6snDhjGS0zJVJunO0NrT3Dg1MLy5TjWP/UJppg== + dependencies: + punycode "^2.1.1" + tsscmp@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/tsscmp/-/tsscmp-1.0.6.tgz#85b99583ac3589ec4bfef825b5000aa911d605eb" integrity sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA== +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type-detect@4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" @@ -3901,6 +6412,13 @@ update-notifier@^4.1.0: semver-diff "^3.1.1" xdg-basedir "^4.0.0" +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + urijs@^1.19.2: version "1.19.2" resolved "https://registry.yarnpkg.com/urijs/-/urijs-1.19.2.tgz#f9be09f00c4c5134b7cb3cf475c1dd394526265a" @@ -3956,21 +6474,123 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +uuid@^8.3.0: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-to-istanbul@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-7.1.1.tgz#04bfd1026ba4577de5472df4f5e89af49de5edda" + integrity sha512-p0BB09E5FRjx0ELN6RgusIPsSPhtgexSRcKETybEs6IGOTXJSZqfwxp7r//55nnu0f1AxltY5VvdVqy2vZf9AA== + dependencies: + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^1.6.0" + source-map "^0.7.3" + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + vary@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + vuvuzela@1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/vuvuzela/-/vuvuzela-1.0.3.tgz#3be145e58271c73ca55279dd851f12a682114b0b" integrity sha1-O+FF5YJxxzylUnndhR8SpoIRSws= +w3c-hr-time@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/w3c-hr-time/-/w3c-hr-time-1.0.2.tgz#0a89cdf5cc15822df9c360543676963e0cc308cd" + integrity sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ== + dependencies: + browser-process-hrtime "^1.0.0" + +w3c-xmlserializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/w3c-xmlserializer/-/w3c-xmlserializer-2.0.0.tgz#3e7104a05b75146cc60f564380b7f683acf1020a" + integrity sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA== + dependencies: + xml-name-validator "^3.0.0" + +walker@^1.0.7, walker@~1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/walker/-/walker-1.0.7.tgz#2f7f9b8fd10d677262b18a884e28d19618e028fb" + integrity sha1-L3+bj9ENZ3JisYqITijRlhjgKPs= + dependencies: + makeerror "1.0.x" + warning-symbol@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/warning-symbol/-/warning-symbol-0.1.0.tgz#bb31dd11b7a0f9d67ab2ed95f457b65825bbad21" integrity sha1-uzHdEbeg+dZ6su2V9Fe2WCW7rSE= +webidl-conversions@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff" + integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA== + +webidl-conversions@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514" + integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w== + +whatwg-encoding@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" + integrity sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw== + dependencies: + iconv-lite "0.4.24" + +whatwg-mimetype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" + integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== + +whatwg-url@^8.0.0, whatwg-url@^8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.5.0.tgz#7752b8464fc0903fec89aa9846fc9efe07351fd3" + integrity sha512-fy+R77xWv0AiqfLl4nuGUlQ3/6b5uNfQ4WAbGQVMYshCTCCPK9psC1nWh3XHuxGVCtlcDDQPQW1csmmIQo+fwg== + dependencies: + lodash "^4.7.0" + tr46 "^2.0.2" + webidl-conversions "^6.1.0" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1, which@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + widest-line@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" @@ -3978,11 +6598,25 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" +word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + wordwrap@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -4005,11 +6639,21 @@ write-stream@~0.4.3: dependencies: readable-stream "~0.0.2" +ws@^7.4.4: + version "7.4.5" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.5.tgz#a484dd851e9beb6fdb420027e3885e8ce48986c1" + integrity sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g== + xdg-basedir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13" integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q== +xml-name-validator@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" + integrity sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw== + xml2js@0.4.19: version "0.4.19" resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7" @@ -4023,11 +6667,51 @@ xmlbuilder@~9.0.1: resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d" integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0= +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + "xtend@>=4.0.0 <4.1.0-0", xtend@^4.0.2, xtend@~4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@^15.4.1: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + year@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/year/-/year-0.2.1.tgz#4083ae520a318b23ec86037f3000cb892bdf9bb0" From d0072c28f828c395545c96322abd33fe15a10232 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 23 Apr 2021 15:14:28 +0100 Subject: [PATCH 21/29] continuing work on smtp testing. --- packages/worker/src/api/routes/tests/email.spec.js | 1 - .../src/api/routes/tests/utilities/TestConfiguration.js | 9 +++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/worker/src/api/routes/tests/email.spec.js b/packages/worker/src/api/routes/tests/email.spec.js index 2f571e86aa..b67bce2bed 100644 --- a/packages/worker/src/api/routes/tests/email.spec.js +++ b/packages/worker/src/api/routes/tests/email.spec.js @@ -26,6 +26,5 @@ describe("/api/admin/email", () => { .set(config.defaultHeaders()) .expect("Content-Type", /json/) .expect(200) - expect(res.body._rev).toBeDefined() }) }) \ No newline at end of file diff --git a/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js b/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js index 7266fe4fd7..18656a0a2a 100644 --- a/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js +++ b/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js @@ -1,4 +1,4 @@ -const env = require("../../environment") +const env = require("../../../../environment") const controllers = require("./controllers") const supertest = require("supertest") const { jwt } = require("@budibase/auth").auth @@ -67,9 +67,10 @@ class TestConfiguration { await this._req({ type: Configs.SMTP, config: { - url: "http://localhost:10000", - logoUrl: "http://localhost:10000/logo", - company: "TestCompany", + port: 12345, + host: "smtptesthost.com", + from: "testfrom@test.com", + } }, null, controllers.config.save) } From 0dd46d12fac5eedcae13617a2664e85549f3a5c4 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 23 Apr 2021 18:07:39 +0100 Subject: [PATCH 22/29] Updating test cases and some re-work of the email system. --- packages/auth/src/index.js | 2 +- packages/auth/src/middleware/authenticated.js | 21 ++++-- packages/auth/src/utils.js | 2 +- .../server/src/api/routes/tests/query.spec.js | 2 +- .../src/api/routes/tests/routing.spec.js | 12 +++- .../server/src/api/routes/tests/user.spec.js | 4 +- .../routes/tests/utilities/TestFunctions.js | 15 +++-- packages/server/src/middleware/currentapp.js | 8 +-- .../src/middleware/tests/currentapp.spec.js | 8 +-- .../src/tests/utilities/TestConfiguration.js | 66 ++++++++++++++----- .../worker/src/api/controllers/admin/email.js | 6 +- packages/worker/src/api/index.js | 7 ++ .../worker/src/api/routes/admin/templates.js | 2 + packages/worker/src/api/routes/index.js | 12 +++- .../tests/utilities/TestConfiguration.js | 16 +++-- .../worker/src/constants/templates/index.js | 10 ++- packages/worker/src/utilities/email.js | 2 +- packages/worker/src/utilities/templates.js | 2 +- 18 files changed, 139 insertions(+), 58 deletions(-) diff --git a/packages/auth/src/index.js b/packages/auth/src/index.js index 5be91cc102..348f911f80 100644 --- a/packages/auth/src/index.js +++ b/packages/auth/src/index.js @@ -36,7 +36,7 @@ module.exports = { buildAuthMiddleware: authenticated, passport, google, - jwt, + jwt: require("jsonwebtoken"), }, StaticDatabases, constants: require("./constants"), diff --git a/packages/auth/src/middleware/authenticated.js b/packages/auth/src/middleware/authenticated.js index 443384ee76..d64c30a70a 100644 --- a/packages/auth/src/middleware/authenticated.js +++ b/packages/auth/src/middleware/authenticated.js @@ -1,6 +1,6 @@ const { Cookies } = require("../constants") const database = require("../db") -const { getCookie } = require("../utils") +const { getCookie, clearCookie } = require("../utils") const { StaticDatabases } = require("../db/utils") module.exports = (noAuthPatterns = []) => { @@ -15,11 +15,20 @@ module.exports = (noAuthPatterns = []) => { const authCookie = getCookie(ctx, Cookies.Auth) if (authCookie) { - const db = database.getDB(StaticDatabases.GLOBAL.name) - const user = await db.get(authCookie.userId) - delete user.password - ctx.isAuthenticated = true - ctx.user = user + try { + const db = database.getDB(StaticDatabases.GLOBAL.name) + const user = await db.get(authCookie.userId) + delete user.password + ctx.isAuthenticated = true + ctx.user = user + } catch (err) { + // remove the cookie as the use does not exist anymore + clearCookie(ctx, Cookies.Auth) + } + } + // be explicit + if (ctx.isAuthenticated !== true) { + ctx.isAuthenticated = false } return next() diff --git a/packages/auth/src/utils.js b/packages/auth/src/utils.js index b9514d059c..10507410b1 100644 --- a/packages/auth/src/utils.js +++ b/packages/auth/src/utils.js @@ -92,7 +92,7 @@ exports.setCookie = (ctx, value, name = "builder") => { * Utility function, simply calls setCookie with an empty string for value */ exports.clearCookie = (ctx, name) => { - exports.setCookie(ctx, "", name) + exports.setCookie(ctx, null, name) } /** diff --git a/packages/server/src/api/routes/tests/query.spec.js b/packages/server/src/api/routes/tests/query.spec.js index 2755c0230e..eadd475ed4 100644 --- a/packages/server/src/api/routes/tests/query.spec.js +++ b/packages/server/src/api/routes/tests/query.spec.js @@ -93,7 +93,7 @@ describe("/queries", () => { const query = await config.createQuery() const res = await request .get(`/api/queries/${query._id}`) - .set(await config.roleHeaders()) + .set(await config.roleHeaders({})) .expect("Content-Type", /json/) .expect(200) expect(res.body.fields).toBeUndefined() diff --git a/packages/server/src/api/routes/tests/routing.spec.js b/packages/server/src/api/routes/tests/routing.spec.js index 5fe0e26f15..d40b35ba8d 100644 --- a/packages/server/src/api/routes/tests/routing.spec.js +++ b/packages/server/src/api/routes/tests/routing.spec.js @@ -35,7 +35,11 @@ describe("/routing", () => { }) const res = await request .get(`/api/routing/client`) - .set(await config.roleHeaders("basic@test.com", BUILTIN_ROLE_IDS.BASIC)) + .set(await config.roleHeaders({ + email: "basic@test.com", + roleId: BUILTIN_ROLE_IDS.BASIC, + builder: false + })) .expect("Content-Type", /json/) .expect(200) expect(res.body.routes).toBeDefined() @@ -59,7 +63,11 @@ describe("/routing", () => { }) const res = await request .get(`/api/routing/client`) - .set(await config.roleHeaders("basic@test.com", BUILTIN_ROLE_IDS.POWER)) + .set(await config.roleHeaders({ + email: "basic@test.com", + roleId: BUILTIN_ROLE_IDS.POWER, + builder: false, + })) .expect("Content-Type", /json/) .expect(200) expect(res.body.routes).toBeDefined() diff --git a/packages/server/src/api/routes/tests/user.spec.js b/packages/server/src/api/routes/tests/user.spec.js index e80672284d..b474e360a8 100644 --- a/packages/server/src/api/routes/tests/user.spec.js +++ b/packages/server/src/api/routes/tests/user.spec.js @@ -5,7 +5,9 @@ const { basicUser } = setup.structures const workerRequests = require("../../../utilities/workerRequests") jest.mock("../../../utilities/workerRequests", () => ({ - getGlobalUsers: jest.fn(), + getGlobalUsers: jest.fn(() => { + return {} + }), saveGlobalUser: jest.fn(() => { const uuid = require("uuid/v4") return { diff --git a/packages/server/src/api/routes/tests/utilities/TestFunctions.js b/packages/server/src/api/routes/tests/utilities/TestFunctions.js index 9ee68c283f..0e11dd2056 100644 --- a/packages/server/src/api/routes/tests/utilities/TestFunctions.js +++ b/packages/server/src/api/routes/tests/utilities/TestFunctions.js @@ -46,7 +46,10 @@ exports.createRequest = (request, method, url, body) => { } exports.checkBuilderEndpoint = async ({ config, method, url, body }) => { - const headers = await config.login() + const headers = await config.login("test@test.com", "test", { + userId: "us_fail", + builder: false, + }) await exports .createRequest(config.request, method, url, body) .set(headers) @@ -62,9 +65,10 @@ exports.checkPermissionsEndpoint = async ({ failRole, }) => { const password = "PASSWORD" - await config.createUser("passUser@budibase.com", password, passRole) - const passHeader = await config.login("passUser@budibase.com", password, { + let user = await config.createUser("pass@budibase.com", password, passRole) + const passHeader = await config.login("pass@budibase.com", password, { roleId: passRole, + userId: user.globalId, }) await exports @@ -72,9 +76,10 @@ exports.checkPermissionsEndpoint = async ({ .set(passHeader) .expect(200) - await config.createUser("failUser@budibase.com", password, failRole) - const failHeader = await config.login("failUser@budibase.com", password, { + user = await config.createUser("fail@budibase.com", password, failRole) + const failHeader = await config.login("fail@budibase.com", password, { roleId: failRole, + userId: user.globalId, }) await exports diff --git a/packages/server/src/middleware/currentapp.js b/packages/server/src/middleware/currentapp.js index d85d2158c2..0828c809c7 100644 --- a/packages/server/src/middleware/currentapp.js +++ b/packages/server/src/middleware/currentapp.js @@ -3,10 +3,7 @@ const { Cookies } = require("@budibase/auth").constants const { getRole } = require("../utilities/security/roles") const { getGlobalUsers } = require("../utilities/workerRequests") const { BUILTIN_ROLE_IDS } = require("../utilities/security/roles") -const { - getGlobalIDFromUserMetadataID, - generateUserMetadataID, -} = require("../db/utils") +const { generateUserMetadataID } = require("../db/utils") module.exports = async (ctx, next) => { // try to get the appID from the request @@ -31,8 +28,7 @@ module.exports = async (ctx, next) => { appCookie.roleId === BUILTIN_ROLE_IDS.PUBLIC) ) { // Different App ID means cookie needs reset, or if the same public user has logged in - const globalId = getGlobalIDFromUserMetadataID(ctx.user._id) - const globalUser = await getGlobalUsers(ctx, requestAppId, globalId) + const globalUser = await getGlobalUsers(ctx, requestAppId, ctx.user._id) updateCookie = true appId = requestAppId if (globalUser.roles && globalUser.roles[requestAppId]) { diff --git a/packages/server/src/middleware/tests/currentapp.spec.js b/packages/server/src/middleware/tests/currentapp.spec.js index 61d5bf018d..e83b364cb5 100644 --- a/packages/server/src/middleware/tests/currentapp.spec.js +++ b/packages/server/src/middleware/tests/currentapp.spec.js @@ -5,7 +5,7 @@ function mockWorker() { jest.mock("../../utilities/workerRequests", () => ({ getGlobalUsers: () => { return { - email: "us_uuid1", + _id: "us_uuid1", roles: { "app_test": "BASIC", } @@ -67,7 +67,8 @@ class TestConfiguration { setUser() { this.ctx.user = { - userId: "ro_ta_user_us_uuid1", + userId: "us_uuid1", + _id: "us_uuid1", } } @@ -159,5 +160,4 @@ describe("Current app middleware", () => { await checkExpected(false) }) }) - -}) \ No newline at end of file +}) diff --git a/packages/server/src/tests/utilities/TestConfiguration.js b/packages/server/src/tests/utilities/TestConfiguration.js index 0b19a74b90..9b4328ba3a 100644 --- a/packages/server/src/tests/utilities/TestConfiguration.js +++ b/packages/server/src/tests/utilities/TestConfiguration.js @@ -16,7 +16,10 @@ const supertest = require("supertest") const { cleanup } = require("../../utilities/fileSystem") const { Cookies } = require("@budibase/auth").constants const { jwt } = require("@budibase/auth").auth +const { StaticDatabases } = require("@budibase/auth").db +const CouchDB = require("../../db") +const GLOBAL_USER_ID = "us_uuid1" const EMAIL = "babs@babs.com" const PASSWORD = "babs_password" @@ -57,7 +60,27 @@ class TestConfiguration { return request.body } + async globalUser(id = GLOBAL_USER_ID, builder = true) { + const db = new CouchDB(StaticDatabases.GLOBAL.name) + let existing + try { + existing = await db.get(id) + } catch (err) { + existing = {} + } + const user = { + _id: id, + ...existing, + roles: {}, + } + if (builder) { + user.builder = { global: true } + } + await db.put(user) + } + async init(appName = "test_application") { + await this.globalUser() return this.createApp(appName) } @@ -69,17 +92,14 @@ class TestConfiguration { } defaultHeaders() { - const user = { - userId: "ro_ta_user_us_uuid1", - builder: { - global: true, - }, + const auth = { + userId: GLOBAL_USER_ID, } const app = { roleId: BUILTIN_ROLE_IDS.BUILDER, appId: this.appId, } - const authToken = jwt.sign(user, env.JWT_SECRET) + const authToken = jwt.sign(auth, env.JWT_SECRET) const appToken = jwt.sign(app, env.JWT_SECRET) const headers = { Accept: "application/json", @@ -104,14 +124,18 @@ class TestConfiguration { return headers } - async roleHeaders(email = EMAIL, roleId = BUILTIN_ROLE_IDS.ADMIN) { + async roleHeaders({ + email = EMAIL, + roleId = BUILTIN_ROLE_IDS.ADMIN, + builder = false, + }) { let user try { user = await this.createUser(email, PASSWORD, roleId) } catch (err) { // allow errors here } - return this.login(email, PASSWORD, { roleId, userId: user._id }) + return this.login(email, PASSWORD, { roleId, userId: user._id, builder }) } async createApp(appName) { @@ -282,7 +306,9 @@ class TestConfiguration { password = PASSWORD, roleId = BUILTIN_ROLE_IDS.POWER ) { - return this._req( + const globalId = `us_${Math.random()}` + await this.globalUser(globalId, roleId === BUILTIN_ROLE_IDS.BUILDER) + const user = await this._req( { email, password, @@ -291,28 +317,34 @@ class TestConfiguration { null, controllers.user.createMetadata ) + return { + ...user, + globalId, + } } - async login(email, password, { roleId, userId } = {}) { - if (!roleId) { - roleId = BUILTIN_ROLE_IDS.BUILDER - } + async login(email, password, { roleId, userId, builder } = {}) { + roleId = !roleId ? BUILTIN_ROLE_IDS.BUILDER : roleId + userId = !userId ? `us_uuid1` : userId if (!this.request) { throw "Server has not been opened, cannot login." } + // make sure the user exists in the global DB + if (roleId !== BUILTIN_ROLE_IDS.PUBLIC) { + await this.globalUser(userId, builder) + } if (!email || !password) { await this.createUser() } // have to fake this - const user = { - userId: userId || `us_uuid1`, - email: email || EMAIL, + const auth = { + userId, } const app = { roleId: roleId, appId: this.appId, } - const authToken = jwt.sign(user, env.JWT_SECRET) + const authToken = jwt.sign(auth, env.JWT_SECRET) const appToken = jwt.sign(app, env.JWT_SECRET) // returning necessary request headers diff --git a/packages/worker/src/api/controllers/admin/email.js b/packages/worker/src/api/controllers/admin/email.js index 0755596841..d735023f7c 100644 --- a/packages/worker/src/api/controllers/admin/email.js +++ b/packages/worker/src/api/controllers/admin/email.js @@ -66,5 +66,9 @@ exports.sendEmail = async ctx => { to: email, html: await buildEmail(purpose, email, user), } - await transport.sendMail(message) + const response = await transport.sendMail(message) + ctx.body = { + ...response, + message: `Email sent to ${email}.`, + } } diff --git a/packages/worker/src/api/index.js b/packages/worker/src/api/index.js index bc3c74aac9..df346c8e0e 100644 --- a/packages/worker/src/api/index.js +++ b/packages/worker/src/api/index.js @@ -23,6 +23,13 @@ router ) .use("/health", ctx => (ctx.status = 200)) .use(buildAuthMiddleware(NO_AUTH_ENDPOINTS)) + // for now no public access is allowed to worker (bar health check) + .use((ctx, next) => { + if (!ctx.isAuthenticated) { + ctx.throw(403, "Unauthorized - no public worker access") + } + return next() + }) // error handling middleware router.use(async (ctx, next) => { diff --git a/packages/worker/src/api/routes/admin/templates.js b/packages/worker/src/api/routes/admin/templates.js index 81bd814cbc..a00278ccac 100644 --- a/packages/worker/src/api/routes/admin/templates.js +++ b/packages/worker/src/api/routes/admin/templates.js @@ -27,3 +27,5 @@ router .get("/api/admin/template/:ownerId", controller.fetchByOwner) .get("/api/admin/template/:id", controller.find) .delete("/api/admin/template/:id/:rev", controller.destroy) + +module.exports = router diff --git a/packages/worker/src/api/routes/index.js b/packages/worker/src/api/routes/index.js index aa1c6874e3..419c80e505 100644 --- a/packages/worker/src/api/routes/index.js +++ b/packages/worker/src/api/routes/index.js @@ -1,7 +1,17 @@ const userRoutes = require("./admin/users") const configRoutes = require("./admin/configs") const groupRoutes = require("./admin/groups") +const templateRoutes = require("./admin/templates") +const emailRoutes = require("./admin/email") const authRoutes = require("./auth") const appRoutes = require("./app") -exports.routes = [configRoutes, userRoutes, groupRoutes, authRoutes, appRoutes] +exports.routes = [ + configRoutes, + userRoutes, + groupRoutes, + authRoutes, + appRoutes, + templateRoutes, + emailRoutes +] diff --git a/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js b/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js index 18656a0a2a..6e499642d7 100644 --- a/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js +++ b/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js @@ -36,12 +36,20 @@ class TestConfiguration { return request.body } - defaultHeaders() { - const user = { - userId: "us_uuid1", + async init() { + // create a test user + await this._req({ + _id: "us_uuid1", builder: { global: true, - }, + } + }, null, controllers.users.save) + } + + defaultHeaders() { + const user = { + _id: "us_uuid1", + userId: "us_uuid1", } const authToken = jwt.sign(user, env.JWT_SECRET) return { diff --git a/packages/worker/src/constants/templates/index.js b/packages/worker/src/constants/templates/index.js index 16ec84a379..1333baa39a 100644 --- a/packages/worker/src/constants/templates/index.js +++ b/packages/worker/src/constants/templates/index.js @@ -8,18 +8,16 @@ const { join } = require("path") const CouchDB = require("../../db") const { getTemplateParams, StaticDatabases } = require("@budibase/auth").db -const TEMPLATE_PATH = join(__dirname, "..", "constants", "templates") - exports.EmailTemplates = { [EmailTemplatePurpose.PASSWORD_RECOVERY]: readStaticFile( - join(TEMPLATE_PATH, "passwordRecovery.html") + join(__dirname, "passwordRecovery.html") ), [EmailTemplatePurpose.INVITATION]: readStaticFile( - join(TEMPLATE_PATH, "invitation.html") + join(__dirname, "invitation.html") ), - [EmailTemplatePurpose.BASE]: readStaticFile(join(TEMPLATE_PATH, "base.html")), + [EmailTemplatePurpose.BASE]: readStaticFile(join(__dirname, "base.html")), [EmailTemplatePurpose.STYLES]: readStaticFile( - join(TEMPLATE_PATH, "style.css") + join(__dirname, "style.css") ), } diff --git a/packages/worker/src/utilities/email.js b/packages/worker/src/utilities/email.js index bc3933531a..b5e64a2793 100644 --- a/packages/worker/src/utilities/email.js +++ b/packages/worker/src/utilities/email.js @@ -1,6 +1,6 @@ const nodemailer = require("nodemailer") -exports.createSMTPTransport = (config) => { +exports.createSMTPTransport = config => { const options = { port: config.port, host: config.host, diff --git a/packages/worker/src/utilities/templates.js b/packages/worker/src/utilities/templates.js index 9a3e2d291b..22a9268366 100644 --- a/packages/worker/src/utilities/templates.js +++ b/packages/worker/src/utilities/templates.js @@ -1,4 +1,4 @@ -const CouchDB = require("../../../db") +const CouchDB = require("../db") const { getConfigParams, StaticDatabases } = require("@budibase/auth").db const { Configs, TemplateBindings, LOGO_URL } = require("../constants") const { checkSlashesInUrl } = require("./index") From 48c1b4b1fef65b0780239b91fd3d4991b3e0b002 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 23 Apr 2021 18:54:12 +0100 Subject: [PATCH 23/29] Major update, fixing email test case. --- .../worker/src/api/controllers/admin/email.js | 9 +++++++++ .../src/api/controllers/admin/templates.js | 7 +++++-- .../worker/src/api/controllers/admin/users.js | 10 +++++----- packages/worker/src/api/routes/admin/configs.js | 2 +- packages/worker/src/api/routes/admin/users.js | 8 ++++---- .../worker/src/api/routes/tests/email.spec.js | 14 +++++++++++++- .../routes/tests/utilities/TestConfiguration.js | 6 ++++-- .../api/routes/tests/utilities/controllers.js | 6 +++--- packages/worker/src/constants/index.js | 3 ++- .../constants/templates/{base.html => base.hbs} | 7 ++++--- .../worker/src/constants/templates/index.js | 17 +++++++++++------ .../{invitation.html => invitation.hbs} | 0 ...sswordRecovery.html => passwordRecovery.hbs} | 0 .../templates/{style.css => style.hbs} | 0 packages/worker/src/utilities/templates.js | 11 ++++++----- 15 files changed, 67 insertions(+), 33 deletions(-) rename packages/worker/src/constants/templates/{base.html => base.hbs} (94%) rename packages/worker/src/constants/templates/{invitation.html => invitation.hbs} (100%) rename packages/worker/src/constants/templates/{passwordRecovery.html => passwordRecovery.hbs} (100%) rename packages/worker/src/constants/templates/{style.css => style.hbs} (100%) diff --git a/packages/worker/src/api/controllers/admin/email.js b/packages/worker/src/api/controllers/admin/email.js index d735023f7c..f11edbd2e7 100644 --- a/packages/worker/src/api/controllers/admin/email.js +++ b/packages/worker/src/api/controllers/admin/email.js @@ -28,6 +28,12 @@ async function buildEmail(purpose, email, user) { getTemplateByPurpose(TYPE, EmailTemplatePurpose.STYLES), getTemplateByPurpose(TYPE, purpose), ]) + if (!base || !styles || !body) { + throw "Unable to build email, missing base components" + } + base = base.contents + styles = styles.contents + body = body.contents // TODO: need to extend the context as much as possible const context = { @@ -59,6 +65,9 @@ exports.sendEmail = async ctx => { user = db.get(userId) } const config = await determineScopedConfig(db, params) + if (!config) { + ctx.throw(400, "Unable to find SMTP configuration") + } const transport = createSMTPTransport(config) const message = { from: config.from, diff --git a/packages/worker/src/api/controllers/admin/templates.js b/packages/worker/src/api/controllers/admin/templates.js index 8d4065b77d..30c90d50bf 100644 --- a/packages/worker/src/api/controllers/admin/templates.js +++ b/packages/worker/src/api/controllers/admin/templates.js @@ -1,10 +1,13 @@ const { generateTemplateID, StaticDatabases } = require("@budibase/auth").db const { CouchDB } = require("../../../db") -const { TemplateMetadata, TemplateBindings } = require("../../../constants") +const { + TemplateMetadata, + TemplateBindings, + GLOBAL_OWNER, +} = require("../../../constants") const { getTemplates } = require("../../../constants/templates") const GLOBAL_DB = StaticDatabases.GLOBAL.name -const GLOBAL_OWNER = "global" exports.save = async ctx => { const db = new CouchDB(GLOBAL_DB) diff --git a/packages/worker/src/api/controllers/admin/users.js b/packages/worker/src/api/controllers/admin/users.js index 95dd474e9a..146373e671 100644 --- a/packages/worker/src/api/controllers/admin/users.js +++ b/packages/worker/src/api/controllers/admin/users.js @@ -11,7 +11,7 @@ const FIRST_USER_EMAIL = "test@test.com" const FIRST_USER_PASSWORD = "test" const GLOBAL_DB = StaticDatabases.GLOBAL.name -exports.userSave = async ctx => { +exports.save = async ctx => { const db = new CouchDB(GLOBAL_DB) const { email, password, _id } = ctx.request.body @@ -69,10 +69,10 @@ exports.firstUser = async ctx => { global: true, }, } - await exports.userSave(ctx) + await exports.save(ctx) } -exports.userDelete = async ctx => { +exports.destroy = async ctx => { const db = new CouchDB(GLOBAL_DB) const dbUser = await db.get(ctx.params.id) await db.remove(dbUser._id, dbUser._rev) @@ -82,7 +82,7 @@ exports.userDelete = async ctx => { } // called internally by app server user fetch -exports.userFetch = async ctx => { +exports.fetch = async ctx => { const db = new CouchDB(GLOBAL_DB) const response = await db.allDocs( getGlobalUserParams(null, { @@ -100,7 +100,7 @@ exports.userFetch = async ctx => { } // called internally by app server user find -exports.userFind = async ctx => { +exports.find = async ctx => { const db = new CouchDB(GLOBAL_DB) let user try { diff --git a/packages/worker/src/api/routes/admin/configs.js b/packages/worker/src/api/routes/admin/configs.js index 826f9535cc..4b9b8396cf 100644 --- a/packages/worker/src/api/routes/admin/configs.js +++ b/packages/worker/src/api/routes/admin/configs.js @@ -25,7 +25,7 @@ function smtpValidation() { function settingValidation() { // prettier-ignore return Joi.object({ - url: Joi.string().valid("", null), + platformUrl: Joi.string().valid("", null), logoUrl: Joi.string().valid("", null), company: Joi.string().required(), }).unknown(true) diff --git a/packages/worker/src/api/routes/admin/users.js b/packages/worker/src/api/routes/admin/users.js index f06153385e..d4bc4b6b62 100644 --- a/packages/worker/src/api/routes/admin/users.js +++ b/packages/worker/src/api/routes/admin/users.js @@ -25,10 +25,10 @@ function buildUserSaveValidation() { } router - .post("/api/admin/users", buildUserSaveValidation(), controller.userSave) - .get("/api/admin/users", controller.userFetch) + .post("/api/admin/users", buildUserSaveValidation(), controller.save) + .get("/api/admin/users", controller.fetch) .post("/api/admin/users/first", controller.firstUser) - .delete("/api/admin/users/:id", controller.userDelete) - .get("/api/admin/users/:id", controller.userFind) + .delete("/api/admin/users/:id", controller.destroy) + .get("/api/admin/users/:id", controller.find) module.exports = router diff --git a/packages/worker/src/api/routes/tests/email.spec.js b/packages/worker/src/api/routes/tests/email.spec.js index b67bce2bed..797b0326ed 100644 --- a/packages/worker/src/api/routes/tests/email.spec.js +++ b/packages/worker/src/api/routes/tests/email.spec.js @@ -5,12 +5,19 @@ const { EmailTemplatePurpose } = require("../../../constants") const sendMailMock = jest.fn() jest.mock("nodemailer") const nodemailer = require("nodemailer") -nodemailer.createTransport.mockReturnValue({"sendMail": sendMailMock}); +nodemailer.createTransport.mockReturnValue({ + sendMail: sendMailMock, + verify: jest.fn() +}) describe("/api/admin/email", () => { let request = setup.getRequest() let config = setup.getConfig() + beforeAll(async () => { + await config.init() + }) + afterAll(setup.afterAll) it("should be able to send an email (with mocking)", async () => { @@ -26,5 +33,10 @@ describe("/api/admin/email", () => { .set(config.defaultHeaders()) .expect("Content-Type", /json/) .expect(200) + expect(res.body.message).toBeDefined() + expect(sendMailMock).toHaveBeenCalled() + const emailCall = sendMailMock.mock.calls[0][0] + expect(emailCall.subject).toBe("Hello!") + expect(emailCall.html).not.toContain("Invalid Binding") }) }) \ No newline at end of file diff --git a/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js b/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js index 6e499642d7..900e5dea13 100644 --- a/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js +++ b/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js @@ -39,6 +39,8 @@ class TestConfiguration { async init() { // create a test user await this._req({ + email: "test@test.com", + password: "test", _id: "us_uuid1", builder: { global: true, @@ -64,7 +66,7 @@ class TestConfiguration { await this._req({ type: Configs.SETTINGS, config: { - url: "http://localhost:10000", + platformUrl: "http://localhost:10000", logoUrl: "http://localhost:10000/logo", company: "TestCompany", } @@ -78,7 +80,7 @@ class TestConfiguration { port: 12345, host: "smtptesthost.com", from: "testfrom@test.com", - + subject: "Hello!", } }, null, controllers.config.save) } diff --git a/packages/worker/src/api/routes/tests/utilities/controllers.js b/packages/worker/src/api/routes/tests/utilities/controllers.js index e74e6dc355..b0d2441c0a 100644 --- a/packages/worker/src/api/routes/tests/utilities/controllers.js +++ b/packages/worker/src/api/routes/tests/utilities/controllers.js @@ -1,7 +1,7 @@ module.exports = { email: require("../../../controllers/admin/email"), groups: require("../../../controllers/admin/groups"), - config: require("../../../controllers/admin/groups"), - templates: require("../../../controllers/admin/groups"), - users: require("../../../controllers/admin/groups"), + config: require("../../../controllers/admin/configs"), + templates: require("../../../controllers/admin/templates"), + users: require("../../../controllers/admin/users"), } diff --git a/packages/worker/src/constants/index.js b/packages/worker/src/constants/index.js index 7406db0bdd..3bc8dbc039 100644 --- a/packages/worker/src/constants/index.js +++ b/packages/worker/src/constants/index.js @@ -30,7 +30,7 @@ const EmailTemplatePurpose = { } const TemplateBindings = { - URL: "url", + PLATFORM_URL: "platformUrl", COMPANY: "company", LOGO_URL: "logoUrl", STYLES: "styles", @@ -76,3 +76,4 @@ exports.TemplateTypes = TemplateTypes exports.EmailTemplatePurpose = EmailTemplatePurpose exports.TemplateMetadata = TemplateMetadata exports.TemplateBindings = TemplateBindings +exports.GLOBAL_OWNER = "global" diff --git a/packages/worker/src/constants/templates/base.html b/packages/worker/src/constants/templates/base.hbs similarity index 94% rename from packages/worker/src/constants/templates/base.html rename to packages/worker/src/constants/templates/base.hbs index f728404be8..1d8ff52700 100644 --- a/packages/worker/src/constants/templates/base.html +++ b/packages/worker/src/constants/templates/base.hbs @@ -47,7 +47,7 @@
-

Budibase Platform

+

Budibase Platform

@@ -64,7 +64,7 @@
-

© 2021 Restobar. All Rights Reserved

+

© 2021 {{ company }}. All Rights Reserved

@@ -79,4 +79,5 @@ - \ No newline at end of file + + \ No newline at end of file diff --git a/packages/worker/src/constants/templates/index.js b/packages/worker/src/constants/templates/index.js index 1333baa39a..dd375d1e86 100644 --- a/packages/worker/src/constants/templates/index.js +++ b/packages/worker/src/constants/templates/index.js @@ -3,6 +3,7 @@ const { EmailTemplatePurpose, TemplateTypes, TemplatePurpose, + GLOBAL_OWNER, } = require("../index") const { join } = require("path") const CouchDB = require("../../db") @@ -10,14 +11,14 @@ const { getTemplateParams, StaticDatabases } = require("@budibase/auth").db exports.EmailTemplates = { [EmailTemplatePurpose.PASSWORD_RECOVERY]: readStaticFile( - join(__dirname, "passwordRecovery.html") + join(__dirname, "passwordRecovery.hbs") ), [EmailTemplatePurpose.INVITATION]: readStaticFile( - join(__dirname, "invitation.html") + join(__dirname, "invitation.hbs") ), - [EmailTemplatePurpose.BASE]: readStaticFile(join(__dirname, "base.html")), + [EmailTemplatePurpose.BASE]: readStaticFile(join(__dirname, "base.hbs")), [EmailTemplatePurpose.STYLES]: readStaticFile( - join(__dirname, "style.css") + join(__dirname, "style.hbs") ), } @@ -37,7 +38,11 @@ exports.addBaseTemplates = (templates, type = null) => { continue } if (exports.EmailTemplates[purpose]) { - templates.push(exports.EmailTemplates[purpose]) + templates.push({ + contents: exports.EmailTemplates[purpose], + purpose, + type, + }) } } return templates @@ -46,7 +51,7 @@ exports.addBaseTemplates = (templates, type = null) => { exports.getTemplates = async ({ ownerId, type, id } = {}) => { const db = new CouchDB(StaticDatabases.GLOBAL.name) const response = await db.allDocs( - getTemplateParams(ownerId, id, { + getTemplateParams(ownerId || GLOBAL_OWNER, id, { include_docs: true, }) ) diff --git a/packages/worker/src/constants/templates/invitation.html b/packages/worker/src/constants/templates/invitation.hbs similarity index 100% rename from packages/worker/src/constants/templates/invitation.html rename to packages/worker/src/constants/templates/invitation.hbs diff --git a/packages/worker/src/constants/templates/passwordRecovery.html b/packages/worker/src/constants/templates/passwordRecovery.hbs similarity index 100% rename from packages/worker/src/constants/templates/passwordRecovery.html rename to packages/worker/src/constants/templates/passwordRecovery.hbs diff --git a/packages/worker/src/constants/templates/style.css b/packages/worker/src/constants/templates/style.hbs similarity index 100% rename from packages/worker/src/constants/templates/style.css rename to packages/worker/src/constants/templates/style.hbs diff --git a/packages/worker/src/utilities/templates.js b/packages/worker/src/utilities/templates.js index 22a9268366..53c492557b 100644 --- a/packages/worker/src/utilities/templates.js +++ b/packages/worker/src/utilities/templates.js @@ -15,17 +15,18 @@ exports.getSettingsTemplateContext = async () => { }) ) let settings = response.rows.map(row => row.doc)[0] || {} - if (!settings.url) { - settings.url = LOCAL_URL + if (!settings.platformUrl) { + settings.platformUrl = LOCAL_URL } // TODO: need to fully spec out the context + const URL = settings.platformUrl return { [TemplateBindings.LOGO_URL]: settings.logoUrl || LOGO_URL, - [TemplateBindings.URL]: settings.url, + [TemplateBindings.PLATFORM_URL]: URL, [TemplateBindings.REGISTRATION_URL]: checkSlashesInUrl( - `${settings.url}/registration` + `${URL}/registration` ), - [TemplateBindings.RESET_URL]: checkSlashesInUrl(`${settings.url}/reset`), + [TemplateBindings.RESET_URL]: checkSlashesInUrl(`${URL}/reset`), [TemplateBindings.COMPANY]: settings.company || BASE_COMPANY, } } From 819d6e79f5712e497754893a88c832832b7e439d Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 26 Apr 2021 14:14:51 +0100 Subject: [PATCH 24/29] Updates after finding a better template to use and adding some real email testing with Ethereal platform. --- .../src/tests/utilities/TestConfiguration.js | 1 + .../src/api/controllers/admin/configs.js | 2 +- .../worker/src/api/controllers/admin/email.js | 1 + .../worker/src/api/routes/admin/configs.js | 1 + .../src/api/routes/tests/realEmail.spec.js | 60 ++ .../tests/utilities/TestConfiguration.js | 39 +- packages/worker/src/constants/index.js | 4 + .../worker/src/constants/templates/base.hbs | 99 +-- .../worker/src/constants/templates/index.js | 1 + .../src/constants/templates/invitation.hbs | 73 ++- .../constants/templates/passwordRecovery.hbs | 69 +- .../worker/src/constants/templates/style.hbs | 619 +++++++++++------- .../src/constants/templates/welcome.hbs | 62 ++ packages/worker/src/utilities/templates.js | 2 + 14 files changed, 693 insertions(+), 340 deletions(-) create mode 100644 packages/worker/src/api/routes/tests/realEmail.spec.js create mode 100644 packages/worker/src/constants/templates/welcome.hbs diff --git a/packages/server/src/tests/utilities/TestConfiguration.js b/packages/server/src/tests/utilities/TestConfiguration.js index 9b4328ba3a..c031cf082d 100644 --- a/packages/server/src/tests/utilities/TestConfiguration.js +++ b/packages/server/src/tests/utilities/TestConfiguration.js @@ -50,6 +50,7 @@ class TestConfiguration { request.config = { jwtSecret: env.JWT_SECRET } request.appId = this.appId request.user = { appId: this.appId } + request.query = {} request.request = { body: config, } diff --git a/packages/worker/src/api/controllers/admin/configs.js b/packages/worker/src/api/controllers/admin/configs.js index dfd616fc6d..c8d1c3d632 100644 --- a/packages/worker/src/api/controllers/admin/configs.js +++ b/packages/worker/src/api/controllers/admin/configs.js @@ -34,7 +34,7 @@ exports.save = async function(ctx) { } try { - const response = await db.post(config) + const response = await db.put(config) ctx.body = { type, _id: response.id, diff --git a/packages/worker/src/api/controllers/admin/email.js b/packages/worker/src/api/controllers/admin/email.js index f11edbd2e7..9f4060d20f 100644 --- a/packages/worker/src/api/controllers/admin/email.js +++ b/packages/worker/src/api/controllers/admin/email.js @@ -16,6 +16,7 @@ const TYPE = TemplateTypes.EMAIL const FULL_EMAIL_PURPOSES = [ EmailTemplatePurpose.INVITATION, EmailTemplatePurpose.PASSWORD_RECOVERY, + EmailTemplatePurpose.WELCOME, ] async function buildEmail(purpose, email, user) { diff --git a/packages/worker/src/api/routes/admin/configs.js b/packages/worker/src/api/routes/admin/configs.js index 4b9b8396cf..5865259a29 100644 --- a/packages/worker/src/api/routes/admin/configs.js +++ b/packages/worker/src/api/routes/admin/configs.js @@ -27,6 +27,7 @@ function settingValidation() { return Joi.object({ platformUrl: Joi.string().valid("", null), logoUrl: Joi.string().valid("", null), + docsUrl: Joi.string().valid("", null), company: Joi.string().required(), }).unknown(true) } diff --git a/packages/worker/src/api/routes/tests/realEmail.spec.js b/packages/worker/src/api/routes/tests/realEmail.spec.js new file mode 100644 index 0000000000..c96b8ab561 --- /dev/null +++ b/packages/worker/src/api/routes/tests/realEmail.spec.js @@ -0,0 +1,60 @@ +const setup = require("./utilities") +const { EmailTemplatePurpose } = require("../../../constants") +const nodemailer = require("nodemailer") +const fetch = require("node-fetch") + +describe("/api/admin/email", () => { + let request = setup.getRequest() + let config = setup.getConfig() + + beforeAll(async () => { + await config.init() + }) + + afterAll(setup.afterAll) + + async function sendRealEmail(purpose) { + await config.saveEtherealSmtpConfig() + await config.saveSettingsConfig() + const res = await request + .post(`/api/admin/email/send`) + .send({ + email: "test@test.com", + purpose, + }) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + expect(res.body.message).toBeDefined() + const testUrl = nodemailer.getTestMessageUrl(res.body) + expect(testUrl).toBeDefined() + const response = await fetch(testUrl) + const text = await response.text() + let toCheckFor + switch (purpose) { + case EmailTemplatePurpose.WELCOME: + toCheckFor = `Thanks for getting started with Budibase's Budibase platform.` + break + case EmailTemplatePurpose.INVITATION: + toCheckFor = `Use the button below to set up your account and get started:` + break + case EmailTemplatePurpose.PASSWORD_RECOVERY: + toCheckFor = `You recently requested to reset your password for your Budibase account in your Budibase platform` + break + } + expect(text).toContain(toCheckFor) + } + + it("should be able to send a welcome email", async () => { + await sendRealEmail(EmailTemplatePurpose.WELCOME) + + }) + + it("should be able to send a invitation email", async () => { + await sendRealEmail(EmailTemplatePurpose.INVITATION) + }) + + it("should be able to send a password recovery email", async () => { + const res = await sendRealEmail(EmailTemplatePurpose.PASSWORD_RECOVERY) + }) +}) \ No newline at end of file diff --git a/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js b/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js index 900e5dea13..7ef4fa9caa 100644 --- a/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js +++ b/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js @@ -3,7 +3,7 @@ const controllers = require("./controllers") const supertest = require("supertest") const { jwt } = require("@budibase/auth").auth const { Cookies } = require("@budibase/auth").constants -const { Configs } = require("../../../../constants") +const { Configs, LOGO_URL } = require("../../../../constants") class TestConfiguration { constructor(openServer = true) { @@ -26,6 +26,7 @@ class TestConfiguration { request.config = { jwtSecret: env.JWT_SECRET } request.appId = this.appId request.user = { appId: this.appId } + request.query = {} request.request = { body: config, } @@ -62,18 +63,34 @@ class TestConfiguration { } } + async deleteConfig(type) { + try { + const cfg = await this._req(null,{ + type, + }, controllers.config.find) + if (cfg) { + await this._req(null, { + id: cfg._id, + rev: cfg._rev, + }, controllers.config.destroy) + } + } catch (err) {} + } + async saveSettingsConfig() { + await this.deleteConfig(Configs.SETTINGS) await this._req({ type: Configs.SETTINGS, config: { platformUrl: "http://localhost:10000", - logoUrl: "http://localhost:10000/logo", - company: "TestCompany", + logoUrl: LOGO_URL, + company: "Budibase", } }, null, controllers.config.save) } async saveSmtpConfig() { + await this.deleteConfig(Configs.SMTP) await this._req({ type: Configs.SMTP, config: { @@ -84,6 +101,22 @@ class TestConfiguration { } }, null, controllers.config.save) } + + async saveEtherealSmtpConfig() { + await this.deleteConfig(Configs.SMTP) + await this._req({ + type: Configs.SMTP, + config: { + port: 587, + host: "smtp.ethereal.email", + secure: false, + auth: { + user: "don.bahringer@ethereal.email", + pass: "yCKSH8rWyUPbnhGYk9", + }, + } + }, null, controllers.config.save) + } } module.exports = TestConfiguration \ No newline at end of file diff --git a/packages/worker/src/constants/index.js b/packages/worker/src/constants/index.js index 3bc8dbc039..141a742ce0 100644 --- a/packages/worker/src/constants/index.js +++ b/packages/worker/src/constants/index.js @@ -26,6 +26,7 @@ const EmailTemplatePurpose = { STYLES: "styles", PASSWORD_RECOVERY: "password_recovery", INVITATION: "invitation", + WELCOME: "welcome", CUSTOM: "custom", } @@ -39,6 +40,9 @@ const TemplateBindings = { EMAIL: "email", RESET_URL: "resetUrl", USER: "user", + REQUEST: "request", + DOCS_URL: "docsUrl", + LOGIN_URL: "loginUrl", } const TemplateMetadata = { diff --git a/packages/worker/src/constants/templates/base.hbs b/packages/worker/src/constants/templates/base.hbs index 1d8ff52700..f804605020 100644 --- a/packages/worker/src/constants/templates/base.hbs +++ b/packages/worker/src/constants/templates/base.hbs @@ -1,83 +1,32 @@ - - + + + - - - - - - - - - - + + + + + + + + + - - +{{ body }} +
- - - - - - - - \ No newline at end of file diff --git a/packages/worker/src/constants/templates/index.js b/packages/worker/src/constants/templates/index.js index dd375d1e86..7ddb85af47 100644 --- a/packages/worker/src/constants/templates/index.js +++ b/packages/worker/src/constants/templates/index.js @@ -20,6 +20,7 @@ exports.EmailTemplates = { [EmailTemplatePurpose.STYLES]: readStaticFile( join(__dirname, "style.hbs") ), + [EmailTemplatePurpose.WELCOME]: readStaticFile(join(__dirname, "welcome.hbs")), } exports.addBaseTemplates = (templates, type = null) => { diff --git a/packages/worker/src/constants/templates/invitation.hbs b/packages/worker/src/constants/templates/invitation.hbs index 8e154fe189..16b011a17f 100644 --- a/packages/worker/src/constants/templates/invitation.hbs +++ b/packages/worker/src/constants/templates/invitation.hbs @@ -1,14 +1,67 @@ - - + +You've been invited to use {{ company }}'s Budibase platform! +
- - \ No newline at end of file diff --git a/packages/worker/src/constants/templates/passwordRecovery.hbs b/packages/worker/src/constants/templates/passwordRecovery.hbs index 11f4eac1f4..838e8f816c 100644 --- a/packages/worker/src/constants/templates/passwordRecovery.hbs +++ b/packages/worker/src/constants/templates/passwordRecovery.hbs @@ -1,15 +1,62 @@ - - + +Use this link to reset your password. The link is only valid for 24 hours. +
- - \ No newline at end of file diff --git a/packages/worker/src/constants/templates/style.hbs b/packages/worker/src/constants/templates/style.hbs index abcd797830..244e901787 100644 --- a/packages/worker/src/constants/templates/style.hbs +++ b/packages/worker/src/constants/templates/style.hbs @@ -1,269 +1,408 @@ -@font-face { - font-family: 'Playfair Display'; - font-style: italic; - font-weight: 400; - src: url(/fonts.gstatic.com/s/playfairdisplay/v22/nuFkD-vYSZviVYUb_rj3ij__anPXDTnohkk72xU.woff2) format('woff2'); - unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; -} -html, -body { - margin: 0 auto !important; - padding: 0 !important; - height: 100% !important; - width: 100% !important; - background: #f1f1f1; -} -* { - -ms-text-size-adjust: 100%; - -webkit-text-size-adjust: 100%; -} -div[style*="margin: 16px 0"] { - margin: 0 !important; -} -table, -td { - mso-table-lspace: 0pt !important; - mso-table-rspace: 0pt !important; -} -table { - border-spacing: 0 !important; - border-collapse: collapse !important; - table-layout: fixed !important; - margin: 0 auto !important; -} -img { - -ms-interpolation-mode:bicubic; -} -a { - text-decoration: none; -} -*[x-apple-data-detectors], /* iOS */ -.unstyle-auto-detected-links *, -.aBn { - border-bottom: 0 !important; - cursor: default !important; - color: inherit !important; - text-decoration: none !important; - font-size: inherit !important; - font-family: inherit !important; - font-weight: inherit !important; - line-height: inherit !important; -} -.a6S { - display: none !important; - opacity: 0.01 !important; -} -.im { - color: inherit !important; -} -img.g-img + div { - display: none !important; -} -@media only screen and (min-device-width: 320px) and (max-device-width: 374px) { - u ~ div .email-container { - min-width: 320px !important; - } -} -@media only screen and (min-device-width: 375px) and (max-device-width: 413px) { - u ~ div .email-container { - min-width: 375px !important; - } -} -@media only screen and (min-device-width: 414px) { - u ~ div .email-container { - min-width: 414px !important; - } -} -.primary{ - background: #f3a333; -} -.bg_white{ - background: #ffffff; -} -.bg_light{ - background: #fafafa; -} -.bg_black{ - background: #000000; -} -.bg_dark{ - background: rgba(0,0,0,.8); -} -.email-section{ - padding:2.5em; -} -.btn{ - padding: 10px 15px; -} -.btn.btn-primary{ - border-radius: 30px; - background: #f3a333; - color: #ffffff; -} -h1,h2,h3,h4,h5,h6{ - font-family: 'Playfair Display', serif; - color: #000000; - margin-top: 0; -} -body{ - font-family: 'Montserrat', sans-serif; - font-weight: 400; - font-size: 15px; - line-height: 1.8; - color: rgba(0,0,0,.4); -} -a{ - color: #f3a333; -} -table{ -} -.logo h1{ - margin: 0; -} -.logo h1 a{ - color: #000; - font-size: 20px; - font-weight: 700; - text-transform: uppercase; - font-family: 'Montserrat', sans-serif; -} -.hero{ - position: relative; -} -.hero img{ +/* Based on templates: https://github.com/wildbit/postmark-templates/blob/master/templates/plain */ +/* Base ------------------------------ */ +@import url('https://fonts.googleapis.com/css2?family=Source+Sans+Pro&display=swap'); +body { +width: 100% !important; +height: 100%; +margin: 0; +-webkit-text-size-adjust: none; } -.hero .text{ - color: rgba(255,255,255,.8); + +a { +color: #3869D4; } -.hero .text h2{ - color: #ffffff; - font-size: 30px; - margin-bottom: 0; + +a img { +border: none; } -.heading-section{ + +td { +word-break: break-word; } -.heading-section h2{ - color: #000000; - font-size: 28px; - margin-top: 0; - line-height: 1.4; + +.preheader { +display: none !important; +visibility: hidden; +mso-hide: all; +font-size: 1px; +line-height: 1px; +max-height: 0; +max-width: 0; +opacity: 0; +overflow: hidden; } -.heading-section .subheading{ - margin-bottom: 20px !important; - display: inline-block; - font-size: 13px; - text-transform: uppercase; - letter-spacing: 2px; - color: rgba(0,0,0,.4); - position: relative; +/* Type ------------------------------ */ + +body, +td, +th { +font-family: "Source Sans Pro", Helvetica, Arial, sans-serif; } -.heading-section .subheading::after{ - position: absolute; - left: 0; - right: 0; - bottom: -10px; - content: ''; - width: 100%; - height: 2px; - background: #f3a333; - margin: 0 auto; + +h1 { +margin-top: 0; +color: #333333; +font-size: 22px; +font-weight: bold; +text-align: left; } -.heading-section-white{ - color: rgba(255,255,255,.8); + +h2 { +margin-top: 0; +color: #333333; +font-size: 16px; +font-weight: bold; +text-align: left; } -.heading-section-white h2{ - font-size: 28px; - line-height: 1; - padding-bottom: 0; + +h3 { +margin-top: 0; +color: #333333; +font-size: 14px; +font-weight: bold; +text-align: left; } -.heading-section-white h2{ - color: #ffffff; + +td, +th { +font-size: 16px; } -.heading-section-white .subheading{ - margin-bottom: 0; - display: inline-block; - font-size: 13px; - text-transform: uppercase; - letter-spacing: 2px; - color: rgba(255,255,255,.4); + +p, +ul, +ol, +blockquote { +margin: .4em 0 1.1875em; +font-size: 16px; +line-height: 1.625; } -.icon{ - text-align: center; + +p.sub { +font-size: 13px; } -.icon img{ +/* Utilities ------------------------------ */ + +.align-right { +text-align: right; } -.text-services{ - padding: 10px 10px 0; - text-align: center; + +.align-left { +text-align: left; } -.text-services h3{ - font-size: 20px; + +.align-center { +text-align: center; } -.text-services .meta{ - text-transform: uppercase; - font-size: 14px; +/* Buttons ------------------------------ */ + +.button { +background-color: #3869D4; +border-top: 10px solid #3869D4; +border-right: 18px solid #3869D4; +border-bottom: 10px solid #3869D4; +border-left: 18px solid #3869D4; +display: inline-block; +color: #FFF; +text-decoration: none; +border-radius: 3px; +box-shadow: 0 2px 3px rgba(0, 0, 0, 0.16); +-webkit-text-size-adjust: none; +box-sizing: border-box; } -.img{ - width: 100%; - height: auto; - position: relative; + +.button--green { +background-color: #22BC66; +border-top: 10px solid #22BC66; +border-right: 18px solid #22BC66; +border-bottom: 10px solid #22BC66; +border-left: 18px solid #22BC66; } -.img .icon{ - position: absolute; - top: 50%; - left: 0; - right: 0; - bottom: 0; - margin-top: -25px; + +.button--red { +background-color: #FF6136; +border-top: 10px solid #FF6136; +border-right: 18px solid #FF6136; +border-bottom: 10px solid #FF6136; +border-left: 18px solid #FF6136; } -.img .icon a{ - display: block; - width: 60px; - position: absolute; - top: 0; - left: 50%; - margin-left: -25px; + +@media only screen and (max-width: 500px) { +.button { +width: 100% !important; +text-align: center !important; } -.counter-text{ - text-align: center; } -.counter-text .num{ - display: block; - color: #ffffff; - font-size: 34px; - font-weight: 700; +/* Attribute list ------------------------------ */ + +.attributes { +margin: 0 0 21px; } -.counter-text .name{ - display: block; - color: rgba(255,255,255,.9); - font-size: 13px; + +.attributes_content { +background-color: #F4F4F7; +padding: 16px; } -.footer{ - color: rgba(255,255,255,.5); + +.attributes_item { +padding: 0; } -.footer .heading{ - color: #ffffff; - font-size: 20px; +/* Related Items ------------------------------ */ + +.related { +width: 100%; +margin: 0; +padding: 25px 0 0 0; +-premailer-width: 100%; +-premailer-cellpadding: 0; +-premailer-cellspacing: 0; } -.footer ul{ - margin: 0; - padding: 0; + +.related_item { +padding: 10px 0; +color: #CBCCCF; +font-size: 15px; +line-height: 18px; } -.footer ul li{ - list-style: none; - margin-bottom: 10px; + +.related_item-title { +display: block; +margin: .5em 0 0; } -.footer ul li a{ - color: rgba(255,255,255,1); + +.related_item-thumb { +display: block; +padding-bottom: 10px; } -@media screen and (max-width: 500px) { - .icon{ - text-align: left; - } - .text-services{ - padding-left: 0; - padding-right: 20px; - text-align: left; - } + +.related_heading { +border-top: 1px solid #CBCCCF; +text-align: center; +padding: 25px 0 10px; +} +/* Discount Code ------------------------------ */ + +.discount { +width: 100%; +margin: 0; +padding: 24px; +-premailer-width: 100%; +-premailer-cellpadding: 0; +-premailer-cellspacing: 0; +background-color: #F4F4F7; +border: 2px dashed #CBCCCF; +} + +.discount_heading { +text-align: center; +} + +.discount_body { +text-align: center; +font-size: 15px; +} +/* Social Icons ------------------------------ */ + +.social { +width: auto; +} + +.social td { +padding: 0; +width: auto; +} + +.social_icon { +height: 20px; +margin: 0 8px 10px 8px; +padding: 0; +} +/* Data table ------------------------------ */ + +.purchase { +width: 100%; +margin: 0; +padding: 35px 0; +-premailer-width: 100%; +-premailer-cellpadding: 0; +-premailer-cellspacing: 0; +} + +.purchase_content { +width: 100%; +margin: 0; +padding: 25px 0 0 0; +-premailer-width: 100%; +-premailer-cellpadding: 0; +-premailer-cellspacing: 0; +} + +.purchase_item { +padding: 10px 0; +color: #51545E; +font-size: 15px; +line-height: 18px; +} + +.purchase_heading { +padding-bottom: 8px; +border-bottom: 1px solid #EAEAEC; +} + +.purchase_heading p { +margin: 0; +color: #85878E; +font-size: 12px; +} + +.purchase_footer { +padding-top: 15px; +border-top: 1px solid #EAEAEC; +} + +.purchase_total { +margin: 0; +text-align: right; +font-weight: bold; +color: #333333; +} + +.purchase_total--label { +padding: 0 15px 0 0; +} + +body { +background-color: #FFF; +color: #333; +} + +p { +color: #333; +} + +.email-wrapper { +width: 100%; +margin: 0; +padding: 0; +-premailer-width: 100%; +-premailer-cellpadding: 0; +-premailer-cellspacing: 0; +} + +.email-content { +width: 100%; +margin: 0; +padding: 0; +-premailer-width: 100%; +-premailer-cellpadding: 0; +-premailer-cellspacing: 0; +} +/* Masthead ----------------------- */ + +.email-masthead { +padding: 25px 0; +text-align: center; +} + +.email-masthead_logo { +width: 94px; +} + +.email-masthead_name { +font-size: 16px; +font-weight: bold; +color: #A8AAAF; +text-decoration: none; +text-shadow: 0 1px 0 white; +} +/* Body ------------------------------ */ + +.email-body { +width: 100%; +margin: 0; +padding: 0; +-premailer-width: 100%; +-premailer-cellpadding: 0; +-premailer-cellspacing: 0; +} + +.email-body_inner { +width: 570px; +margin: 0 auto; +padding: 0; +-premailer-width: 570px; +-premailer-cellpadding: 0; +-premailer-cellspacing: 0; +} + +.email-footer { +width: 570px; +margin: 0 auto; +padding: 0; +-premailer-width: 570px; +-premailer-cellpadding: 0; +-premailer-cellspacing: 0; +text-align: center; +} + +.email-footer p { +color: #A8AAAF; +} + +.body-action { +width: 100%; +margin: 30px auto; +padding: 0; +-premailer-width: 100%; +-premailer-cellpadding: 0; +-premailer-cellspacing: 0; +text-align: center; +} + +.body-sub { +margin-top: 25px; +padding-top: 25px; +border-top: 1px solid #EAEAEC; +} + +.content-cell { +padding: 35px; +} +/*Media Queries ------------------------------ */ + +@media only screen and (max-width: 600px) { +.email-body_inner, +.email-footer { +width: 100% !important; +} +} + +@media (prefers-color-scheme: dark) { +body { +background-color: #333333 !important; +color: #FFF !important; +} +p, +ul, +ol, +blockquote, +h1, +h2, +h3, +span, +.purchase_item { +color: #FFF !important; +} +.attributes_content, +.discount { +background-color: #222 !important; +} +.email-masthead_name { +text-shadow: none !important; +} +} + +:root { +color-scheme: light dark; +supported-color-schemes: light dark; } \ No newline at end of file diff --git a/packages/worker/src/constants/templates/welcome.hbs b/packages/worker/src/constants/templates/welcome.hbs new file mode 100644 index 0000000000..89d4136121 --- /dev/null +++ b/packages/worker/src/constants/templates/welcome.hbs @@ -0,0 +1,62 @@ + +Thanks for trying out [Product Name]. We’ve pulled together some information and resources to help you get started. + + + + + \ No newline at end of file diff --git a/packages/worker/src/utilities/templates.js b/packages/worker/src/utilities/templates.js index 53c492557b..56c4340a77 100644 --- a/packages/worker/src/utilities/templates.js +++ b/packages/worker/src/utilities/templates.js @@ -28,5 +28,7 @@ exports.getSettingsTemplateContext = async () => { ), [TemplateBindings.RESET_URL]: checkSlashesInUrl(`${URL}/reset`), [TemplateBindings.COMPANY]: settings.company || BASE_COMPANY, + [TemplateBindings.DOCS_URL]: settings.docsUrl || "https://docs.budibase.com/", + [TemplateBindings.LOGIN_URL]: checkSlashesInUrl(`${URL}/login`), } } From cba2b9a27de4d75a90235b1a440ea39684a9b6d8 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 26 Apr 2021 14:16:05 +0100 Subject: [PATCH 25/29] Formatting. --- .../src/api/controllers/admin/configs.js | 2 +- packages/worker/src/api/routes/index.js | 2 +- .../tests/utilities/TestConfiguration.js | 116 +++++++++++------- .../worker/src/constants/templates/index.js | 6 +- packages/worker/src/utilities/templates.js | 3 +- 5 files changed, 76 insertions(+), 53 deletions(-) diff --git a/packages/worker/src/api/controllers/admin/configs.js b/packages/worker/src/api/controllers/admin/configs.js index c8d1c3d632..107c0c8fa8 100644 --- a/packages/worker/src/api/controllers/admin/configs.js +++ b/packages/worker/src/api/controllers/admin/configs.js @@ -30,7 +30,7 @@ exports.save = async function(ctx) { switch (type) { case Configs.SMTP: await email.verifyConfig(config) - break; + break } try { diff --git a/packages/worker/src/api/routes/index.js b/packages/worker/src/api/routes/index.js index 419c80e505..412d8c255a 100644 --- a/packages/worker/src/api/routes/index.js +++ b/packages/worker/src/api/routes/index.js @@ -13,5 +13,5 @@ exports.routes = [ authRoutes, appRoutes, templateRoutes, - emailRoutes + emailRoutes, ] diff --git a/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js b/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js index 7ef4fa9caa..06a0d8e548 100644 --- a/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js +++ b/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js @@ -39,14 +39,18 @@ class TestConfiguration { async init() { // create a test user - await this._req({ - email: "test@test.com", - password: "test", - _id: "us_uuid1", - builder: { - global: true, - } - }, null, controllers.users.save) + await this._req( + { + email: "test@test.com", + password: "test", + _id: "us_uuid1", + builder: { + global: true, + }, + }, + null, + controllers.users.save + ) } defaultHeaders() { @@ -57,66 +61,84 @@ class TestConfiguration { const authToken = jwt.sign(user, env.JWT_SECRET) return { Accept: "application/json", - Cookie: [ - `${Cookies.Auth}=${authToken}`, - ], + Cookie: [`${Cookies.Auth}=${authToken}`], } } async deleteConfig(type) { try { - const cfg = await this._req(null,{ - type, - }, controllers.config.find) + const cfg = await this._req( + null, + { + type, + }, + controllers.config.find + ) if (cfg) { - await this._req(null, { - id: cfg._id, - rev: cfg._rev, - }, controllers.config.destroy) + await this._req( + null, + { + id: cfg._id, + rev: cfg._rev, + }, + controllers.config.destroy + ) } } catch (err) {} } async saveSettingsConfig() { await this.deleteConfig(Configs.SETTINGS) - await this._req({ - type: Configs.SETTINGS, - config: { - platformUrl: "http://localhost:10000", - logoUrl: LOGO_URL, - company: "Budibase", - } - }, null, controllers.config.save) + await this._req( + { + type: Configs.SETTINGS, + config: { + platformUrl: "http://localhost:10000", + logoUrl: LOGO_URL, + company: "Budibase", + }, + }, + null, + controllers.config.save + ) } async saveSmtpConfig() { await this.deleteConfig(Configs.SMTP) - await this._req({ - type: Configs.SMTP, - config: { - port: 12345, - host: "smtptesthost.com", - from: "testfrom@test.com", - subject: "Hello!", - } - }, null, controllers.config.save) + await this._req( + { + type: Configs.SMTP, + config: { + port: 12345, + host: "smtptesthost.com", + from: "testfrom@test.com", + subject: "Hello!", + }, + }, + null, + controllers.config.save + ) } async saveEtherealSmtpConfig() { await this.deleteConfig(Configs.SMTP) - await this._req({ - type: Configs.SMTP, - config: { - port: 587, - host: "smtp.ethereal.email", - secure: false, - auth: { - user: "don.bahringer@ethereal.email", - pass: "yCKSH8rWyUPbnhGYk9", + await this._req( + { + type: Configs.SMTP, + config: { + port: 587, + host: "smtp.ethereal.email", + secure: false, + auth: { + user: "don.bahringer@ethereal.email", + pass: "yCKSH8rWyUPbnhGYk9", + }, }, - } - }, null, controllers.config.save) + }, + null, + controllers.config.save + ) } } -module.exports = TestConfiguration \ No newline at end of file +module.exports = TestConfiguration diff --git a/packages/worker/src/constants/templates/index.js b/packages/worker/src/constants/templates/index.js index 7ddb85af47..23e5508341 100644 --- a/packages/worker/src/constants/templates/index.js +++ b/packages/worker/src/constants/templates/index.js @@ -17,10 +17,10 @@ exports.EmailTemplates = { join(__dirname, "invitation.hbs") ), [EmailTemplatePurpose.BASE]: readStaticFile(join(__dirname, "base.hbs")), - [EmailTemplatePurpose.STYLES]: readStaticFile( - join(__dirname, "style.hbs") + [EmailTemplatePurpose.STYLES]: readStaticFile(join(__dirname, "style.hbs")), + [EmailTemplatePurpose.WELCOME]: readStaticFile( + join(__dirname, "welcome.hbs") ), - [EmailTemplatePurpose.WELCOME]: readStaticFile(join(__dirname, "welcome.hbs")), } exports.addBaseTemplates = (templates, type = null) => { diff --git a/packages/worker/src/utilities/templates.js b/packages/worker/src/utilities/templates.js index 56c4340a77..8bb2ba9e95 100644 --- a/packages/worker/src/utilities/templates.js +++ b/packages/worker/src/utilities/templates.js @@ -28,7 +28,8 @@ exports.getSettingsTemplateContext = async () => { ), [TemplateBindings.RESET_URL]: checkSlashesInUrl(`${URL}/reset`), [TemplateBindings.COMPANY]: settings.company || BASE_COMPANY, - [TemplateBindings.DOCS_URL]: settings.docsUrl || "https://docs.budibase.com/", + [TemplateBindings.DOCS_URL]: + settings.docsUrl || "https://docs.budibase.com/", [TemplateBindings.LOGIN_URL]: checkSlashesInUrl(`${URL}/login`), } } From b3933103a8001062fcd2281fa9bd4b16b559b0ff Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 26 Apr 2021 14:24:07 +0100 Subject: [PATCH 26/29] Formatting, linting and handling year copyright properly. --- .../src/api/routes/tests/utilities/TestConfiguration.js | 4 +++- packages/worker/src/constants/index.js | 2 ++ packages/worker/src/constants/templates/base.hbs | 2 +- packages/worker/src/utilities/templates.js | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js b/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js index 06a0d8e548..0f97b50c82 100644 --- a/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js +++ b/packages/worker/src/api/routes/tests/utilities/TestConfiguration.js @@ -84,7 +84,9 @@ class TestConfiguration { controllers.config.destroy ) } - } catch (err) {} + } catch (err) { + // don't need to handle error + } } async saveSettingsConfig() { diff --git a/packages/worker/src/constants/index.js b/packages/worker/src/constants/index.js index 141a742ce0..f5702d3e96 100644 --- a/packages/worker/src/constants/index.js +++ b/packages/worker/src/constants/index.js @@ -43,6 +43,8 @@ const TemplateBindings = { REQUEST: "request", DOCS_URL: "docsUrl", LOGIN_URL: "loginUrl", + CURRENT_YEAR: "currentYear", + CURRENT_DATE: "currentDate", } const TemplateMetadata = { diff --git a/packages/worker/src/constants/templates/base.hbs b/packages/worker/src/constants/templates/base.hbs index f804605020..ba0571db0b 100644 --- a/packages/worker/src/constants/templates/base.hbs +++ b/packages/worker/src/constants/templates/base.hbs @@ -24,7 +24,7 @@ diff --git a/packages/worker/src/utilities/templates.js b/packages/worker/src/utilities/templates.js index 8bb2ba9e95..3035dc2bbc 100644 --- a/packages/worker/src/utilities/templates.js +++ b/packages/worker/src/utilities/templates.js @@ -31,5 +31,7 @@ exports.getSettingsTemplateContext = async () => { [TemplateBindings.DOCS_URL]: settings.docsUrl || "https://docs.budibase.com/", [TemplateBindings.LOGIN_URL]: checkSlashesInUrl(`${URL}/login`), + [TemplateBindings.CURRENT_DATE]: new Date().toISOString(), + [TemplateBindings.CURRENT_YEAR]: new Date().getFullYear(), } } From 65914d7cfaafc958d7c35e04717322bccc6088da Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 26 Apr 2021 14:39:18 +0100 Subject: [PATCH 27/29] Moving header/footer and presentational tables to the base hbs email template. --- .../worker/src/constants/templates/base.hbs | 25 +++- .../src/constants/templates/invitation.hbs | 107 ++++++++---------- .../constants/templates/passwordRecovery.hbs | 97 +++++++--------- .../src/constants/templates/welcome.hbs | 91 ++++++--------- 4 files changed, 143 insertions(+), 177 deletions(-) diff --git a/packages/worker/src/constants/templates/base.hbs b/packages/worker/src/constants/templates/base.hbs index ba0571db0b..38ceff023a 100644 --- a/packages/worker/src/constants/templates/base.hbs +++ b/packages/worker/src/constants/templates/base.hbs @@ -20,11 +20,28 @@ -{{ body }} - + - + diff --git a/packages/worker/src/constants/templates/invitation.hbs b/packages/worker/src/constants/templates/invitation.hbs index 16b011a17f..fcaf7e7ca1 100644 --- a/packages/worker/src/constants/templates/invitation.hbs +++ b/packages/worker/src/constants/templates/invitation.hbs @@ -1,67 +1,50 @@ -You've been invited to use {{ company }}'s Budibase platform! - - - + \ No newline at end of file diff --git a/packages/worker/src/constants/templates/passwordRecovery.hbs b/packages/worker/src/constants/templates/passwordRecovery.hbs index 838e8f816c..6ebe606467 100644 --- a/packages/worker/src/constants/templates/passwordRecovery.hbs +++ b/packages/worker/src/constants/templates/passwordRecovery.hbs @@ -1,62 +1,45 @@ -Use this link to reset your password. The link is only valid for 24 hours. - - - + \ No newline at end of file diff --git a/packages/worker/src/constants/templates/welcome.hbs b/packages/worker/src/constants/templates/welcome.hbs index 89d4136121..6d4dcbd5e8 100644 --- a/packages/worker/src/constants/templates/welcome.hbs +++ b/packages/worker/src/constants/templates/welcome.hbs @@ -1,62 +1,45 @@ -Thanks for trying out [Product Name]. We’ve pulled together some information and resources to help you get started. - - - + \ No newline at end of file From 9e73a75512b05972e865edd5499d75f3403bb0be Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Mon, 26 Apr 2021 14:53:47 +0100 Subject: [PATCH 28/29] Updating welcome to make it clear no login credentials in it. --- packages/worker/src/constants/templates/welcome.hbs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/worker/src/constants/templates/welcome.hbs b/packages/worker/src/constants/templates/welcome.hbs index 6d4dcbd5e8..b509ad5e31 100644 --- a/packages/worker/src/constants/templates/welcome.hbs +++ b/packages/worker/src/constants/templates/welcome.hbs @@ -8,7 +8,7 @@

Welcome, {{ email }}!

Thanks for getting started with {{ company }}'s Budibase platform.

-

For reference, here's your login information:

+

For reference, here's how to login: