diff --git a/config/test.ts b/config/test.ts index 649dec2..5b56d75 100644 --- a/config/test.ts +++ b/config/test.ts @@ -3,7 +3,7 @@ export default { host: "localhost", user: "root", password: "", - database: "wms2_test", + database: "wms2_core_test", create_database_automatically: true } }; \ No newline at end of file diff --git a/package.json b/package.json index d5d67fc..7d04bfe 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "wms-core", - "version": "0.10.20", + "version": "0.10.21", "description": "Node web framework", "repository": "git@gitlab.com:ArisuOngaku/wms-core.git", "author": "Alice Gaudon ", @@ -26,9 +26,12 @@ "@types/geoip-lite": "^1.1.31", "@types/jest": "^25.2.1", "@types/mjml": "^4.0.4", + "@types/node-fetch": "^2.5.7", "@types/on-finished": "^2.3.1", "@types/uuid": "^7.0.2", "jest": "^25.4.0", + "maildev": "^1.1.0", + "node-fetch": "^2.6.0", "ts-jest": "^25.4.0", "typescript": "^3.8.3" }, diff --git a/src/components/CsrfProtectionComponent.ts b/src/components/CsrfProtectionComponent.ts index 94aa260..780d299 100644 --- a/src/components/CsrfProtectionComponent.ts +++ b/src/components/CsrfProtectionComponent.ts @@ -5,7 +5,7 @@ import {BadRequestError} from "../HttpError"; export default class CsrfProtectionComponent extends ApplicationComponent { public async start(app: Express, router: Router): Promise { - router.use((req, res, next) => { + router.use(async (req, res, next) => { if (!req.session) { throw new Error('Session is unavailable.'); } @@ -17,13 +17,20 @@ export default class CsrfProtectionComponent extends ApplicationComponent return req.session!.csrf; }; - if (!['GET', 'HEAD', 'OPTIONS'].find(s => s === req.method) && !req.authGuard.isAuthenticatedViaRequest(req)) { - if (req.session.csrf === undefined) { - throw new InvalidCsrfTokenError(req.baseUrl, `You weren't assigned any CSRF token.`); - } else if (req.body.csrf === undefined) { - throw new InvalidCsrfTokenError(req.baseUrl, `You didn't provide any CSRF token.`); - } else if (req.session.csrf !== req.body.csrf) { - throw new InvalidCsrfTokenError(req.baseUrl, `Tokens don't match.`); + if (!['GET', 'HEAD', 'OPTIONS'].find(s => s === req.method)) { + try { + if (!(await req.authGuard.isAuthenticatedViaRequest(req))) { + if (req.session.csrf === undefined) { + throw new InvalidCsrfTokenError(req.baseUrl, `You weren't assigned any CSRF token.`); + } else if (req.body.csrf === undefined) { + throw new InvalidCsrfTokenError(req.baseUrl, `You didn't provide any CSRF token.`); + } else if (req.session.csrf !== req.body.csrf) { + throw new InvalidCsrfTokenError(req.baseUrl, `Tokens don't match.`); + } + } + } catch (e) { + next(e); + return; } } next(); diff --git a/src/components/NunjucksComponent.ts b/src/components/NunjucksComponent.ts index 7dda1ce..ce356e8 100644 --- a/src/components/NunjucksComponent.ts +++ b/src/components/NunjucksComponent.ts @@ -6,8 +6,15 @@ import Controller from "../Controller"; import {ServerError} from "../HttpError"; export default class NunjucksComponent extends ApplicationComponent { + private readonly viewsPath: string; + + constructor(viewsPath: string = 'views') { + super(); + this.viewsPath = viewsPath; + } + public async start(app: Express, router: Router): Promise { - const env = nunjucks.configure('views', { + const env = nunjucks.configure(this.viewsPath, { autoescape: true, express: app, noCache: !config.get('view.cache'), @@ -19,7 +26,7 @@ export default class NunjucksComponent extends ApplicationComponent { return path; }) .addGlobal('app_version', this.app!.getVersion()) - .addGlobal('core_version', require('../package.json').version) + .addGlobal('core_version', require('../../package.json').version) .addFilter('hex', (v: number) => { return v.toString(16); }); diff --git a/test/CsrfProtectionComponent.test.ts b/test/CsrfProtectionComponent.test.ts new file mode 100644 index 0000000..70f539a --- /dev/null +++ b/test/CsrfProtectionComponent.test.ts @@ -0,0 +1,117 @@ +import fetch, {Response} from "node-fetch"; +import useApp, {DEFAULT_ADDR, TestApp} from "./_app"; +import Controller from "../src/Controller"; +import CsrfProtectionComponent from "../src/components/CsrfProtectionComponent"; + +useApp(port => { + return new class extends TestApp { + protected async init(): Promise { + this.use(new class extends Controller { + routes(): void { + this.get('/', (req, res, next) => { + res.render('test/csrf.njk'); + }, 'csrf_test'); + + this.post('/', (req, res, next) => { + res.json({ + status: 'ok', + }); + }, 'csrf_test'); + } + }()); + + await super.init(); + } + + + protected registerComponents() { + super.registerComponents(); + this.use(new CsrfProtectionComponent()); + } + }(port); +}); + +describe('Test CSRF protection', () => { + let res: Response; + + test('no csrf token should be in session at first', async () => { + res = await fetch(DEFAULT_ADDR, { + method: 'POST', + }); + expect(res.status).toBe(401); + expect(await res.text()).toContain(`You weren't assigned any CSRF token.`); + }); + + let cookies: string | null; + + test('sending no csrf token should fail', async () => { + cookies = res.headers.get('set-cookie'); + expect(cookies).toBeDefined(); + + res = await fetch(`${DEFAULT_ADDR}${Controller.route('csrf_test')}`, { + headers: { + 'Cookie': cookies!, + } + }); + expect(res.ok).toBe(true); + + res = await fetch(DEFAULT_ADDR, { + method: 'POST', + headers: { + 'Cookie': cookies!, + } + }); + expect(res.status).toBe(401); + expect(await res.text()).toContain(`You didn't provide any CSRF token.`); + }); + + test('sending an invalid csrf token should fail', async () => { + cookies = res.headers.get('set-cookie'); + expect(cookies).toBeDefined(); + + res = await fetch(`${DEFAULT_ADDR}${Controller.route('csrf_test')}`, { + headers: { + 'Cookie': cookies!, + } + }); + expect(res.ok).toBe(true); + + res = await fetch(DEFAULT_ADDR, { + method: 'POST', + body: JSON.stringify({ + csrf: 'not_a_valid_csrf', + }), + headers: { + 'Content-Type': 'application/json', + 'Cookie': cookies!, + } + }); + expect(res.status).toBe(401); + expect(await res.text()).toContain(`Tokens don't match.`); + }); + + test('sending a valid csrf token should success', async () => { + cookies = res.headers.get('set-cookie'); + expect(cookies).toBeDefined(); + + res = await fetch(`${DEFAULT_ADDR}${Controller.route('csrf_test')}`, { + headers: { + 'Cookie': cookies!, + } + }); + expect(res.ok).toBe(true); + let csrf = await res.text(); + + res = await fetch(DEFAULT_ADDR, { + method: 'POST', + body: JSON.stringify({ + csrf: csrf, + }), + headers: { + 'Content-Type': 'application/json', + 'Cookie': cookies!, + } + }); + expect(res.ok).toBe(true); + }); +}); \ No newline at end of file diff --git a/test/_app.ts b/test/_app.ts new file mode 100644 index 0000000..254352b --- /dev/null +++ b/test/_app.ts @@ -0,0 +1,91 @@ +import {setupMailServer, teardownMailServer} from "./_mail_server"; +import Application from "../src/Application"; +import Migration from "../src/db/Migration"; +import {Type} from "../src/Utils"; +import {MIGRATIONS} from "./_migrations"; +import ExpressAppComponent from "../src/components/ExpressAppComponent"; +import RedisComponent from "../src/components/RedisComponent"; +import MysqlComponent from "../src/components/MysqlComponent"; +import NunjucksComponent from "../src/components/NunjucksComponent"; +import LogRequestsComponent from "../src/components/LogRequestsComponent"; +import MailComponent from "../src/components/MailComponent"; +import SessionComponent from "../src/components/SessionComponent"; +import AuthComponent from "../src/auth/AuthComponent"; +import AuthGuard from "../src/auth/AuthGuard"; +import MagicLink from "../src/auth/models/MagicLink"; +import FormHelperComponent from "../src/components/FormHelperComponent"; + +export default function useApp(appSupplier?: (port: number) => TestApp) { + let app: Application; + + beforeAll(async (done) => { + await setupMailServer(); + app = appSupplier ? appSupplier(8966) : new TestApp(8966); + + await app.start(); + done(); + }); + + afterAll(async (done) => { + await app.stop(); + await teardownMailServer(); + done(); + }); +} + +export class TestApp extends Application { + private readonly port: number; + + constructor(port: number) { + super(require('../package.json').version, true); + this.port = port; + } + + protected getMigrations(): Type[] { + return MIGRATIONS; + } + + protected async init(): Promise { + this.registerComponents(); + this.registerWebSocketListeners(); + this.registerControllers(); + } + + protected registerComponents() { + const redisComponent = new RedisComponent(); + const mysqlComponent = new MysqlComponent(); + + const expressAppComponent = new ExpressAppComponent(this.port); + this.use(expressAppComponent); + + // Base + this.use(new NunjucksComponent('test/views')); + this.use(new LogRequestsComponent()); + + // Services + this.use(mysqlComponent); + this.use(new MailComponent()); + + // Session + this.use(redisComponent); + this.use(new SessionComponent(redisComponent)); + + // Auth + this.use(new AuthComponent(new class extends AuthGuard { + public async getProofForSession(session: Express.Session): Promise { + return await MagicLink.bySessionID(session.id, ['login', 'register']); + } + })); + + // Utils + this.use(new FormHelperComponent()); + } + + protected registerWebSocketListeners() { + } + + protected registerControllers() { + } +} + +export const DEFAULT_ADDR = 'http://localhost:8966'; \ No newline at end of file diff --git a/test/_mail_server.ts b/test/_mail_server.ts new file mode 100644 index 0000000..da2110d --- /dev/null +++ b/test/_mail_server.ts @@ -0,0 +1,19 @@ +const MailDev = require("maildev"); + +export const MAIL_SERVER = new MailDev({ + ip: 'localhost', +}); + +export async function setupMailServer() { + await new Promise((resolve, reject) => MAIL_SERVER.listen((err: Error) => { + if (err) reject(err); + else resolve(); + })); +}; + +export async function teardownMailServer() { + await new Promise((resolve, reject) => MAIL_SERVER.close((err: Error) => { + if (err) reject(err); + else resolve(); + })); +}; \ No newline at end of file diff --git a/test/views/errors/400.njk b/test/views/errors/400.njk new file mode 100644 index 0000000..a5bc022 --- /dev/null +++ b/test/views/errors/400.njk @@ -0,0 +1,2 @@ +{% extends './error.njk' %} +{% import 'macros.njk' as macros %} diff --git a/test/views/errors/401.njk b/test/views/errors/401.njk new file mode 100644 index 0000000..a5bc022 --- /dev/null +++ b/test/views/errors/401.njk @@ -0,0 +1,2 @@ +{% extends './error.njk' %} +{% import 'macros.njk' as macros %} diff --git a/test/views/errors/403.njk b/test/views/errors/403.njk new file mode 100644 index 0000000..a5bc022 --- /dev/null +++ b/test/views/errors/403.njk @@ -0,0 +1,2 @@ +{% extends './error.njk' %} +{% import 'macros.njk' as macros %} diff --git a/test/views/errors/404.njk b/test/views/errors/404.njk new file mode 100644 index 0000000..a5bc022 --- /dev/null +++ b/test/views/errors/404.njk @@ -0,0 +1,2 @@ +{% extends './error.njk' %} +{% import 'macros.njk' as macros %} diff --git a/test/views/errors/429.njk b/test/views/errors/429.njk new file mode 100644 index 0000000..a5bc022 --- /dev/null +++ b/test/views/errors/429.njk @@ -0,0 +1,2 @@ +{% extends './error.njk' %} +{% import 'macros.njk' as macros %} diff --git a/test/views/errors/500.njk b/test/views/errors/500.njk new file mode 100644 index 0000000..a5bc022 --- /dev/null +++ b/test/views/errors/500.njk @@ -0,0 +1,2 @@ +{% extends './error.njk' %} +{% import 'macros.njk' as macros %} diff --git a/test/views/errors/503.njk b/test/views/errors/503.njk new file mode 100644 index 0000000..a5bc022 --- /dev/null +++ b/test/views/errors/503.njk @@ -0,0 +1,2 @@ +{% extends './error.njk' %} +{% import 'macros.njk' as macros %} diff --git a/test/views/errors/error.njk b/test/views/errors/error.njk new file mode 100644 index 0000000..3d05ea9 --- /dev/null +++ b/test/views/errors/error.njk @@ -0,0 +1,36 @@ +{% extends '../layouts/barebone.njk' %} + +{% set title = error_code + ' - ' + error_message %} + +{% block _stylesheets %} + +{% endblock %} + +{% block _body %} + + +
+ {% if flash %} + {{ macros.messages(flash) }} + {% endif %} + +
{{ error_code }}
+
{{ error_message }}
+
{{ error_instructions|safe }}
+ + +
+ +
+ Error ID: {{ error_id }} +
+ If you think this isn't right, please contact us with the above error ID at + {{ app.contact_email }}. +
+{% endblock %} \ No newline at end of file diff --git a/test/views/layouts/barebone.njk b/test/views/layouts/barebone.njk new file mode 100644 index 0000000..3a82d94 --- /dev/null +++ b/test/views/layouts/barebone.njk @@ -0,0 +1,37 @@ + + + + + {{ title }} + + + + + + + + {% if description %} + + {% endif %} + + {% if refresh_after %} + + {% endif %} + + {% block _stylesheets %}{% endblock %} + {% block _scripts %} + + {% endblock %} + + + +
+ {% block header %}{% endblock %} +
+ +{% block _body %}{% endblock %} + +
{% block footer %}{% endblock %}
+ + + \ No newline at end of file diff --git a/test/views/layouts/base.njk b/test/views/layouts/base.njk new file mode 100644 index 0000000..d73ca22 --- /dev/null +++ b/test/views/layouts/base.njk @@ -0,0 +1,51 @@ +{% extends './barebone.njk' %} + +{% block _stylesheets %} + {{ super() }} + + {% block stylesheets %}{% endblock %} +{% endblock %} +{% block _scripts %} + {{ super() }} + {% block scripts %}{% endblock %} +{% endblock %} + +{% block header %} + + +{% endblock %} + +{% block _body %} +
+ {{ macros.messages(flash) }} +
+ +
+ {% if h1 %} +

{{ h1 }}

+ {% endif %} + {% if subtitle %} +

{{ subtitle }}

+ {% endif %} + + {% block body %}{% endblock %} +
+{% endblock %} + +{% block footer %}{{ app.name }} v{{ app_version }} - all rights reserved.{% endblock %} \ No newline at end of file diff --git a/test/views/layouts/widget.njk b/test/views/layouts/widget.njk new file mode 100644 index 0000000..9f467fc --- /dev/null +++ b/test/views/layouts/widget.njk @@ -0,0 +1,18 @@ +{% extends './barebone.njk' %} + +{% block _stylesheets %} + {{ super() }} + {% block stylesheets %}{% endblock %} +{% endblock %} +{% block _scripts %} + {{ super() }} + {% block scripts %}{% endblock %} +{% endblock %} + +{% block header %}{% endblock %} + +{% block _body %} + {% block body %}{% endblock %} +{% endblock %} + +{% block footer %}{% endblock %} \ No newline at end of file diff --git a/test/views/macros.njk b/test/views/macros.njk new file mode 100644 index 0000000..789700a --- /dev/null +++ b/test/views/macros.njk @@ -0,0 +1,142 @@ +{% macro message(type, content, raw=false, discreet=false) %} +
+ + + {{ content|safe if raw else content }} + +
+{% endmacro %} + +{% macro messages(flash) %} + {% set flashed = flash() %} + {% set display = 0 %} + + {% for type, bag in flashed %} + {% if bag|length %} + {% set display = 1 %} + {% endif %} + {% endfor %} + + {% if display %} +
+ {% for type, bag in flashed %} + {% for content in bag %} + {{ message(type, content) }} + {% endfor %} + {% endfor %} +
+ {% endif %} +{% endmacro %} + +{% macro csrf(getCSRFToken) %} + +{% endmacro %} + +{% macro field(_locals, type, name, value, placeholder, hint, validation_attributes='', extraData='') %} + {% set validation = _locals.validation() %} + {% set validation = validation[name] if validation[name] or null %} + {% set previousFormData = _locals.previousFormData() %} + {% set value = previousFormData[name] or value or validation.value or '' %} + + {% if type == 'hidden' %} + {% if validation %} + {{ message('error', validation.message) }} + {% endif %} + + {% else %} +
+ {% if type == 'duration' %} +
+ {% for f in extraData %} +
+ {% if previousFormData[name] %} + {% set v = value[f] %} + {% else %} + {% set v = (value % 60) if f == 's' else (((value - value % 60) / 60 % 60) if f == 'm' else ((value - value % 3600) / 3600 if f == 'h')) %} + {% endif %} + + +
+ {% endfor %} +
+ {% elseif type == 'select' %} + + + {% else %} + + {% endif %} + + + {{ fieldError(_locals, name) }} + {% if hint %} +
{{ hint }}
+ {% endif %} +
+ {% endif %} +{% endmacro %} + +{% macro fieldError(_locals, name) %} + {% set validation = _locals.validation() %} + {% set validation = validation[name] if validation[name] or null %} + {% if validation %} +
{{ validation.message }}
+ {% endif %} +{% endmacro %} + +{% macro websocket(websocketUrl, listener, reconnectOnClose = 1, checkFunction = 0) %} + +{% endmacro %} + +{% macro paginate(pagination, routeName) %} + {% if pagination.hasPrevious() or pagination.hasNext() %} + + {% endif %} +{% endmacro %} \ No newline at end of file diff --git a/test/views/test/csrf.njk b/test/views/test/csrf.njk new file mode 100644 index 0000000..1df1416 --- /dev/null +++ b/test/views/test/csrf.njk @@ -0,0 +1 @@ +{{ getCSRFToken() }} \ No newline at end of file diff --git a/test/views/test/throws_error.njk b/test/views/test/throws_error.njk new file mode 100644 index 0000000..6106ee8 --- /dev/null +++ b/test/views/test/throws_error.njk @@ -0,0 +1,3 @@ +{{ route('non-existing-fake-route') }} + +This should never be distributed. \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index e7564c6..67f0539 100644 --- a/yarn.lock +++ b/yarn.lock @@ -668,6 +668,14 @@ dependencies: "@types/node" "*" +"@types/node-fetch@^2.5.7": + version "2.5.7" + resolved "https://registry.toot.party/@types%2fnode-fetch/-/node-fetch-2.5.7.tgz#20a2afffa882ab04d44ca786449a276f9f6bbf3c" + integrity sha512-o2WVNf5UhWRkxlf6eq+jMZDu7kjgpgJfl4xVNlvryc95O/6F2ld8ztKX+qu+Rjyet93WAWm5LjeX9H5FGkODvw== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node@*": version "14.0.14" resolved "https://registry.toot.party/@types%2fnode/-/node-14.0.14.tgz#24a0b5959f16ac141aeb0c5b3cd7a15b7c64cbce" @@ -771,7 +779,7 @@ abbrev@1: resolved "https://registry.toot.party/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -accepts@~1.3.7: +accepts@~1.3.4, accepts@~1.3.7: version "1.3.7" resolved "https://registry.toot.party/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== @@ -802,6 +810,16 @@ acorn@^7.1.0: resolved "https://registry.toot.party/acorn/-/acorn-7.3.1.tgz#85010754db53c3fbaf3b9ea3e083aa5c5d147ffd" integrity sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA== +addressparser@^1.0.1: + version "1.0.1" + resolved "https://registry.toot.party/addressparser/-/addressparser-1.0.1.tgz#47afbe1a2a9262191db6838e4fd1d39b40821746" + integrity sha1-R6++GiqSYhkdtoOOT9HTm0CCF0Y= + +after@0.8.2: + version "0.8.2" + resolved "https://registry.toot.party/after/-/after-0.8.2.tgz#fedb394f9f0e02aa9768e702bda23b505fae7e1f" + integrity sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8= + ajv@^6.5.5: version "6.12.2" resolved "https://registry.toot.party/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" @@ -934,6 +952,11 @@ array-unique@^0.3.2: resolved "https://registry.toot.party/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +arraybuffer.slice@~0.0.7: + version "0.0.7" + resolved "https://registry.toot.party/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz#3bbc4275dd584cc1b10809b89d4e8b63a69e7675" + integrity sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog== + asap@^2.0.3: version "2.0.6" resolved "https://registry.toot.party/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" @@ -961,6 +984,11 @@ astral-regex@^1.0.0: resolved "https://registry.toot.party/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.toot.party/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + async@^2.1.1: version "2.6.3" resolved "https://registry.toot.party/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" @@ -1060,11 +1088,31 @@ babel-runtime@^6.26.0: core-js "^2.4.0" regenerator-runtime "^0.11.0" +backo2@1.0.2: + version "1.0.2" + resolved "https://registry.toot.party/backo2/-/backo2-1.0.2.tgz#31ab1ac8b129363463e35b3ebb69f4dfcfba7947" + integrity sha1-MasayLEpNjRj41s+u2n038+6eUc= + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.toot.party/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +base32.js@0.1.0: + version "0.1.0" + resolved "https://registry.toot.party/base32.js/-/base32.js-0.1.0.tgz#b582dec693c2f11e893cf064ee6ac5b6131a2202" + integrity sha1-tYLexpPC8R6JPPBk7mrFthMaIgI= + +base64-arraybuffer@0.1.5: + version "0.1.5" + resolved "https://registry.toot.party/base64-arraybuffer/-/base64-arraybuffer-0.1.5.tgz#73926771923b5a19747ad666aa5cd4bf9c6e9ce8" + integrity sha1-c5JncZI7Whl0etZmqlzUv5xunOg= + +base64id@1.0.0: + version "1.0.0" + resolved "https://registry.toot.party/base64id/-/base64id-1.0.0.tgz#47688cb99bb6804f0e06d3e763b1c32e57d8e6b6" + integrity sha1-R2iMuZu2gE8OBtPnY7HDLlfY5rY= + base@^0.11.1: version "0.11.2" resolved "https://registry.toot.party/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" @@ -1085,6 +1133,13 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" +better-assert@~1.0.0: + version "1.0.2" + resolved "https://registry.toot.party/better-assert/-/better-assert-1.0.2.tgz#40866b9e1b9e0b55b481894311e68faffaebc522" + integrity sha1-QIZrnhueC1W0gYlDEeaPr/rrxSI= + dependencies: + callsite "1.0.0" + bignumber.js@9.0.0: version "9.0.0" resolved "https://registry.toot.party/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075" @@ -1095,6 +1150,11 @@ binary-extensions@^2.0.0: resolved "https://registry.toot.party/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== +blob@0.0.5: + version "0.0.5" + resolved "https://registry.toot.party/blob/-/blob-0.0.5.tgz#d680eeef25f8cd91ad533f5b01eed48e64caf683" + integrity sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig== + body-parser@1.19.0: version "1.19.0" resolved "https://registry.toot.party/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" @@ -1203,6 +1263,11 @@ cache-base@^1.0.1: union-value "^1.0.0" unset-value "^1.0.0" +callsite@1.0.0: + version "1.0.0" + resolved "https://registry.toot.party/callsite/-/callsite-1.0.0.tgz#280398e5d664bd74038b6f0905153e6e8af1bc20" + integrity sha1-KAOY5dZkvXQDi28JBRU+borxvCA= + callsites@^3.0.0: version "3.1.0" resolved "https://registry.toot.party/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -1384,7 +1449,7 @@ colors@^1.1.2: resolved "https://registry.toot.party/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== -combined-stream@^1.0.6, combined-stream@~1.0.6: +combined-stream@^1.0.6, combined-stream@^1.0.8, combined-stream@~1.0.6: version "1.0.8" resolved "https://registry.toot.party/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -1396,7 +1461,7 @@ commander@2.17.x: resolved "https://registry.toot.party/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== -commander@^2.11.0, commander@^2.15.1, commander@^2.19.0: +commander@^2.11.0, commander@^2.15.1, commander@^2.19.0, commander@^2.20.0: version "2.20.3" resolved "https://registry.toot.party/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== @@ -1411,11 +1476,26 @@ commander@~2.19.0: resolved "https://registry.toot.party/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg== +component-bind@1.0.0: + version "1.0.0" + resolved "https://registry.toot.party/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" + integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= + +component-emitter@1.2.1: + version "1.2.1" + resolved "https://registry.toot.party/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" + integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= + component-emitter@^1.2.1: version "1.3.0" resolved "https://registry.toot.party/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== +component-inherit@0.0.3: + version "0.0.3" + resolved "https://registry.toot.party/component-inherit/-/component-inherit-0.0.3.tgz#645fc4adf58b72b649d5cae65135619db26ff143" + integrity sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM= + concat-map@0.0.1: version "0.0.1" resolved "https://registry.toot.party/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -1483,6 +1563,11 @@ cookie-signature@1.0.6: resolved "https://registry.toot.party/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= +cookie@0.3.1: + version "0.3.1" + resolved "https://registry.toot.party/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" + integrity sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s= + cookie@0.4.0: version "0.4.0" resolved "https://registry.toot.party/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" @@ -1508,6 +1593,14 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.toot.party/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= +cors@^2.8.5: + version "2.8.5" + resolved "https://registry.toot.party/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" + integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== + dependencies: + object-assign "^4" + vary "^1" + cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.toot.party/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -1598,13 +1691,20 @@ debug@^3.2.6: dependencies: ms "^2.1.1" -debug@^4.1.0, debug@^4.1.1: +debug@^4.1.0, debug@^4.1.1, debug@~4.1.0: version "4.1.1" resolved "https://registry.toot.party/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== dependencies: ms "^2.1.1" +debug@~3.1.0: + version "3.1.0" + resolved "https://registry.toot.party/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.toot.party/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -1819,6 +1919,46 @@ end-of-stream@^1.1.0: dependencies: once "^1.4.0" +engine.io-client@~3.3.1: + version "3.3.2" + resolved "https://registry.toot.party/engine.io-client/-/engine.io-client-3.3.2.tgz#04e068798d75beda14375a264bb3d742d7bc33aa" + integrity sha512-y0CPINnhMvPuwtqXfsGuWE8BB66+B6wTtCofQDRecMQPYX3MYUZXFNKDhdrSe3EVjgOu4V3rxdeqN/Tr91IgbQ== + dependencies: + component-emitter "1.2.1" + component-inherit "0.0.3" + debug "~3.1.0" + engine.io-parser "~2.1.1" + has-cors "1.1.0" + indexof "0.0.1" + parseqs "0.0.5" + parseuri "0.0.5" + ws "~6.1.0" + xmlhttprequest-ssl "~1.5.4" + yeast "0.1.2" + +engine.io-parser@~2.1.0, engine.io-parser@~2.1.1: + version "2.1.3" + resolved "https://registry.toot.party/engine.io-parser/-/engine.io-parser-2.1.3.tgz#757ab970fbf2dfb32c7b74b033216d5739ef79a6" + integrity sha512-6HXPre2O4Houl7c4g7Ic/XzPnHBvaEmN90vtRO9uLmwtRqQmTOw0QMevL1TOfL2Cpu1VzsaTmMotQgMdkzGkVA== + dependencies: + after "0.8.2" + arraybuffer.slice "~0.0.7" + base64-arraybuffer "0.1.5" + blob "0.0.5" + has-binary2 "~1.0.2" + +engine.io@~3.3.1: + version "3.3.2" + resolved "https://registry.toot.party/engine.io/-/engine.io-3.3.2.tgz#18cbc8b6f36e9461c5c0f81df2b830de16058a59" + integrity sha512-AsaA9KG7cWPXWHp5FvHdDWY3AMWeZ8x+2pUVLcn71qE5AtAzgGbxuclOytygskw8XGmiQafTmnI9Bix3uihu2w== + dependencies: + accepts "~1.3.4" + base64id "1.0.0" + cookie "0.3.1" + debug "~3.1.0" + engine.io-parser "~2.1.0" + ws "~6.1.0" + entities@^1.1.1, entities@~1.1.1: version "1.1.2" resolved "https://registry.toot.party/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" @@ -1841,7 +1981,7 @@ escape-html@~1.0.3: resolved "https://registry.toot.party/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= -escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.5, escape-string-regexp@~1.0.5: version "1.0.5" resolved "https://registry.toot.party/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -2007,7 +2147,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@~3.0.2: +extend@~3.0.0, extend@~3.0.2: version "3.0.2" resolved "https://registry.toot.party/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -2120,6 +2260,15 @@ forever-agent@~0.6.1: resolved "https://registry.toot.party/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= +form-data@^3.0.0: + version "3.0.0" + resolved "https://registry.toot.party/form-data/-/form-data-3.0.0.tgz#31b7e39c85f1355b7139ee0c647cf0de7f83c682" + integrity sha512-CKMFDglpbMi6PyN+brwB9Q/GOw0eAnsrEZDgcsH5Krhz5Od/haKHAX0NmQfha2zPPz0JpWzA7GJHGSnvCRLWsg== + 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.toot.party/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" @@ -2283,6 +2432,18 @@ har-validator@~5.1.3: ajv "^6.5.5" har-schema "^2.0.0" +has-binary2@~1.0.2: + version "1.0.3" + resolved "https://registry.toot.party/has-binary2/-/has-binary2-1.0.3.tgz#7776ac627f3ea77250cfc332dab7ddf5e4f5d11d" + integrity sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw== + dependencies: + isarray "2.0.1" + +has-cors@1.1.0: + version "1.1.0" + resolved "https://registry.toot.party/has-cors/-/has-cors-1.1.0.tgz#5e474793f7ea9843d1bb99c23eef49ff126fff39" + integrity sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk= + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.toot.party/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -2422,7 +2583,7 @@ human-signals@^1.1.1: resolved "https://registry.toot.party/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== -iconv-lite@0.4.24, iconv-lite@^0.4.13, iconv-lite@^0.4.4: +iconv-lite@0.4.24, iconv-lite@^0.4.13, iconv-lite@^0.4.4, iconv-lite@~0.4.24: version "0.4.24" resolved "https://registry.toot.party/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -2454,6 +2615,11 @@ imurmurhash@^0.1.4: resolved "https://registry.toot.party/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= +indexof@0.0.1: + version "0.0.1" + resolved "https://registry.toot.party/indexof/-/indexof-0.0.1.tgz#82dc336d232b9062179d05ab3293a66059fd435d" + integrity sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10= + inflight@^1.0.4: version "1.0.6" resolved "https://registry.toot.party/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -2496,6 +2662,11 @@ ipaddr.js@1.9.1: resolved "https://registry.toot.party/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== +ipv6-normalize@1.0.1: + version "1.0.1" + resolved "https://registry.toot.party/ipv6-normalize/-/ipv6-normalize-1.0.1.tgz#1b3258290d365fa83239e89907dde4592e7620a8" + integrity sha1-GzJYKQ02X6gyOeiZB93kWS52IKg= + is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.toot.party/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" @@ -2656,6 +2827,11 @@ is-windows@^1.0.2: resolved "https://registry.toot.party/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.toot.party/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= + is-wsl@^2.1.1: version "2.2.0" resolved "https://registry.toot.party/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" @@ -2668,6 +2844,11 @@ isarray@1.0.0, isarray@~1.0.0: resolved "https://registry.toot.party/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= +isarray@2.0.1: + version "2.0.1" + resolved "https://registry.toot.party/isarray/-/isarray-2.0.1.tgz#a37d94ed9cda2d59865c9f76fe596ee1f338741e" + integrity sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4= + isexe@^2.0.0: version "2.0.0" resolved "https://registry.toot.party/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" @@ -3390,6 +3571,33 @@ lru-cache@^4.1.5: pseudomap "^1.0.2" yallist "^2.1.2" +maildev@^1.1.0: + version "1.1.0" + resolved "https://registry.toot.party/maildev/-/maildev-1.1.0.tgz#8b6977f244373be00112c942ae15dd32f5c225c9" + integrity sha512-D7mrEM/i4c5AX72aRBN9mO5snsGhEs7MvNFWmrSsRL94sIH0/zVQ1GE+ysN9J7lFMLkXNy2xPG3SGP2cjPrCRw== + dependencies: + async "^3.1.0" + commander "^2.20.0" + cors "^2.8.5" + express "^4.17.1" + mailparser-mit "^1.0.0" + opn "^6.0.0" + rimraf "^2.6.3" + smtp-connection "4.0.2" + smtp-server "3.5.0" + socket.io "2.2.0" + wildstring "1.0.9" + +mailparser-mit@^1.0.0: + version "1.0.0" + resolved "https://registry.toot.party/mailparser-mit/-/mailparser-mit-1.0.0.tgz#19df8436c2a02e1d34a03ec518a2eb065e0a94a4" + integrity sha512-sckRITNb3VCT1sQ275g47MAN786pQ5lU20bLY5f794dF/ARGzuVATQ64gO13FOw8jayjFT10e5ttsripKGGXcw== + dependencies: + addressparser "^1.0.1" + iconv-lite "~0.4.24" + mime "^1.6.0" + uue "^3.1.0" + make-dir@^3.0.0: version "3.1.0" resolved "https://registry.toot.party/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -3485,7 +3693,7 @@ mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24: dependencies: mime-db "1.44.0" -mime@1.6.0: +mime@1.6.0, mime@^1.6.0: version "1.6.0" resolved "https://registry.toot.party/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== @@ -3979,6 +4187,11 @@ node-addon-api@^2.0.0: resolved "https://registry.toot.party/node-addon-api/-/node-addon-api-2.0.1.tgz#4fd0931bf6d7e48b219ff3e6abc73cbb0252b7a3" integrity sha512-2WVfwRfIr1AVn3dRq4yRc2Hn35ND+mPJH6inC6bjpYCZVrpXPB4j3T6i//OGVfqVsR1t/X/axRulDsheq4F0LQ== +node-fetch@^2.6.0: + version "2.6.0" + resolved "https://registry.toot.party/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" + integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.toot.party/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -4016,6 +4229,16 @@ node-pre-gyp@^0.14.0: semver "^5.3.0" tar "^4.4.2" +nodemailer@5.0.0: + version "5.0.0" + resolved "https://registry.toot.party/nodemailer/-/nodemailer-5.0.0.tgz#bcb409eca613114e85de42646d0ce7f1fa70b716" + integrity sha512-XI4PI5L7GYcJyHkPcHlvPyRrYohNYBNRNbt1tU8PXNU3E1ADJC84a13V0vbL9AM431OP+ETacaGXAF8fGn1JvA== + +nodemailer@^3.1.1: + version "3.1.8" + resolved "https://registry.toot.party/nodemailer/-/nodemailer-3.1.8.tgz#febfaccb4bd273678473a309c6cb4b4a2f3c48e3" + integrity sha1-/r+sy0vSc2eEc6MJxstLSi88SOM= + nodemailer@^6.4.6: version "6.4.10" resolved "https://registry.toot.party/nodemailer/-/nodemailer-6.4.10.tgz#f4c8dc7991c57f41fd081bef224ef01f7065143d" @@ -4129,11 +4352,16 @@ oauth-sign@~0.9.0: resolved "https://registry.toot.party/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-assign@^4.1.0: +object-assign@^4, object-assign@^4.1.0: version "4.1.1" resolved "https://registry.toot.party/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= +object-component@0.0.3: + version "0.0.3" + resolved "https://registry.toot.party/object-component/-/object-component-0.0.3.tgz#f0c69aa50efc95b866c186f400a33769cb2f1291" + integrity sha1-8MaapQ78lbhmwYb0AKM3acsvEpE= + object-copy@^0.1.0: version "0.1.0" resolved "https://registry.toot.party/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" @@ -4183,6 +4411,13 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" +opn@^6.0.0: + version "6.0.0" + resolved "https://registry.toot.party/opn/-/opn-6.0.0.tgz#3c5b0db676d5f97da1233d1ed42d182bc5a27d2d" + integrity sha512-I9PKfIZC+e4RXZ/qr1RhgyCnGgYX0UEIlXgWnCOVACIvFgaC9rz6Won7xbdhoHrd8IIhV7YEpHjreNUNkqCGkQ== + dependencies: + is-wsl "^1.1.0" + optionator@^0.8.1: version "0.8.3" resolved "https://registry.toot.party/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" @@ -4276,6 +4511,20 @@ parse5@5.1.0: resolved "https://registry.toot.party/parse5/-/parse5-5.1.0.tgz#c59341c9723f414c452975564c7c00a68d58acd2" integrity sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ== +parseqs@0.0.5: + version "0.0.5" + resolved "https://registry.toot.party/parseqs/-/parseqs-0.0.5.tgz#d5208a3738e46766e291ba2ea173684921a8b89d" + integrity sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0= + dependencies: + better-assert "~1.0.0" + +parseuri@0.0.5: + version "0.0.5" + resolved "https://registry.toot.party/parseuri/-/parseuri-0.0.5.tgz#80204a50d4dbb779bfdc6ebe2778d90e4bce320a" + integrity sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo= + dependencies: + better-assert "~1.0.0" + parseurl@~1.3.3: version "1.3.3" resolved "https://registry.toot.party/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -4673,7 +4922,7 @@ ret@~0.1.10: resolved "https://registry.toot.party/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== -rimraf@^2.5.2, rimraf@^2.6.1: +rimraf@^2.5.2, rimraf@^2.6.1, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.toot.party/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -4859,6 +5108,22 @@ slick@^1.12.2: resolved "https://registry.toot.party/slick/-/slick-1.12.2.tgz#bd048ddb74de7d1ca6915faa4a57570b3550c2d7" integrity sha1-vQSN23TefRymkV+qSldXCzVQwtc= +smtp-connection@4.0.2: + version "4.0.2" + resolved "https://registry.toot.party/smtp-connection/-/smtp-connection-4.0.2.tgz#d9dd68d38569f3ad9265473670d09d8f3ea518db" + integrity sha1-2d1o04Vp862SZUc2cNCdjz6lGNs= + dependencies: + nodemailer "^3.1.1" + +smtp-server@3.5.0: + version "3.5.0" + resolved "https://registry.toot.party/smtp-server/-/smtp-server-3.5.0.tgz#eb2e7bd52f26b4136b9dfc2c9fa0ba70e18cdc81" + integrity sha512-7FUg09H1VmqMRlUq/QdkPxn/NK8VCFw7GMU5rdWWDbS00wbLhjRBe3Lme+AamjDSmVoP6e/WqFqsa7jVI+69pg== + dependencies: + base32.js "0.1.0" + ipv6-normalize "1.0.1" + nodemailer "5.0.0" + snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.toot.party/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -4889,6 +5154,52 @@ snapdragon@^0.8.1: source-map-resolve "^0.5.0" use "^3.1.0" +socket.io-adapter@~1.1.0: + version "1.1.2" + resolved "https://registry.toot.party/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz#ab3f0d6f66b8fc7fca3959ab5991f82221789be9" + integrity sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g== + +socket.io-client@2.2.0: + version "2.2.0" + resolved "https://registry.toot.party/socket.io-client/-/socket.io-client-2.2.0.tgz#84e73ee3c43d5020ccc1a258faeeb9aec2723af7" + integrity sha512-56ZrkTDbdTLmBIyfFYesgOxsjcLnwAKoN4CiPyTVkMQj3zTUh0QAx3GbvIvLpFEOvQWu92yyWICxB0u7wkVbYA== + dependencies: + backo2 "1.0.2" + base64-arraybuffer "0.1.5" + component-bind "1.0.0" + component-emitter "1.2.1" + debug "~3.1.0" + engine.io-client "~3.3.1" + has-binary2 "~1.0.2" + has-cors "1.1.0" + indexof "0.0.1" + object-component "0.0.3" + parseqs "0.0.5" + parseuri "0.0.5" + socket.io-parser "~3.3.0" + to-array "0.1.4" + +socket.io-parser@~3.3.0: + version "3.3.0" + resolved "https://registry.toot.party/socket.io-parser/-/socket.io-parser-3.3.0.tgz#2b52a96a509fdf31440ba40fed6094c7d4f1262f" + integrity sha512-hczmV6bDgdaEbVqhAeVMM/jfUfzuEZHsQg6eOmLgJht6G3mPKMxYm75w2+qhAQZ+4X+1+ATZ+QFKeOZD5riHng== + dependencies: + component-emitter "1.2.1" + debug "~3.1.0" + isarray "2.0.1" + +socket.io@2.2.0: + version "2.2.0" + resolved "https://registry.toot.party/socket.io/-/socket.io-2.2.0.tgz#f0f633161ef6712c972b307598ecd08c9b1b4d5b" + integrity sha512-wxXrIuZ8AILcn+f1B4ez4hJTPG24iNgxBBDaJfT6MsyOhVYiTXWexGoPkd87ktJG8kQEcL/NBvRi64+9k4Kc0w== + dependencies: + debug "~4.1.0" + engine.io "~3.3.1" + has-binary2 "~1.0.2" + socket.io-adapter "~1.1.0" + socket.io-client "2.2.0" + socket.io-parser "~3.3.0" + source-map-resolve@^0.5.0: version "0.5.3" resolved "https://registry.toot.party/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" @@ -5186,6 +5497,11 @@ tmpl@1.0.x: resolved "https://registry.toot.party/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1" integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE= +to-array@0.1.4: + version "0.1.4" + resolved "https://registry.toot.party/to-array/-/to-array-0.1.4.tgz#17e6c11f73dd4f3d74cda7a4ff3238e9ad9bf890" + integrity sha1-F+bBH3PdTz10zaek/zI46a2b+JA= + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.toot.party/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -5408,6 +5724,14 @@ utils-merge@1.0.1: resolved "https://registry.toot.party/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= +uue@^3.1.0: + version "3.1.2" + resolved "https://registry.toot.party/uue/-/uue-3.1.2.tgz#e99368414e87200012eb37de4dbaebaa1c742ad2" + integrity sha512-axKLXVqwtdI/czrjG0X8hyV1KLgeWx8F4KvSbvVCnS+RUvsQMGRjx0kfuZDXXqj0LYvVJmx3B9kWlKtEdRrJLg== + dependencies: + escape-string-regexp "~1.0.5" + extend "~3.0.0" + uuid@^3.3.2: version "3.4.0" resolved "https://registry.toot.party/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" @@ -5440,7 +5764,7 @@ validate-npm-package-license@^3.0.1: spdx-correct "^3.0.0" spdx-expression-parse "^3.0.0" -vary@~1.1.2: +vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.toot.party/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= @@ -5551,6 +5875,11 @@ wide-align@^1.1.0: dependencies: string-width "^1.0.2 || 2" +wildstring@1.0.9: + version "1.0.9" + resolved "https://registry.toot.party/wildstring/-/wildstring-1.0.9.tgz#82a696d5653c7d4ec9ba716859b6b53aba2761c5" + integrity sha1-gqaW1WU8fU7JunFoWba1OronYcU= + word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.toot.party/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" @@ -5594,6 +5923,13 @@ ws@^7.0.0, ws@^7.2.3: resolved "https://registry.toot.party/ws/-/ws-7.3.0.tgz#4b2f7f219b3d3737bc1a2fbf145d825b94d38ffd" integrity sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w== +ws@~6.1.0: + version "6.1.4" + resolved "https://registry.toot.party/ws/-/ws-6.1.4.tgz#5b5c8800afab925e94ccb29d153c8d02c1776ef9" + integrity sha512-eqZfL+NE/YQc1/ZynhojeV8q+H050oR8AZ2uIev7RU10svA9ZnJUddHcOUZTJLinZ9yEfdA2kSATS2qZK5fhJA== + dependencies: + async-limiter "~1.0.0" + xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.toot.party/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" @@ -5604,6 +5940,11 @@ xmlchars@^2.1.1: resolved "https://registry.toot.party/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== +xmlhttprequest-ssl@~1.5.4: + version "1.5.5" + resolved "https://registry.toot.party/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.5.5.tgz#c2876b06168aadc40e57d97e81191ac8f4398b3e" + integrity sha1-wodrBhaKrcQOV9l+gRkayPQ5iz4= + xtend@^4.0.2: version "4.0.2" resolved "https://registry.toot.party/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" @@ -5681,6 +6022,11 @@ yauzl@^2.9.2: buffer-crc32 "~0.2.3" fd-slicer "~1.1.0" +yeast@0.1.2: + version "0.1.2" + resolved "https://registry.toot.party/yeast/-/yeast-0.1.2.tgz#008e06d8094320c372dbc2f8ed76a0ca6c8ac419" + integrity sha1-AI4G2AlDIMNy28L47XagymyKxBk= + yn@3.1.1: version "3.1.1" resolved "https://registry.toot.party/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"