diff --git a/package-lock.json b/package-lock.json index 9667e1e..27cc621 100644 --- a/package-lock.json +++ b/package-lock.json @@ -330,16 +330,83 @@ "fastq": "^1.6.0" } }, + "@types/accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/node": "*" + } + }, "@types/color-name": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" }, + "@types/connect": { + "version": "3.4.33", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz", + "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "@types/cookies": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.4.tgz", + "integrity": "sha512-oTGtMzZZAVuEjTwCjIh8T8FrC8n/uwy+PG0yTvQcdZ7etoel7C7/3MSd7qrukENTgQtotG7gvBlBojuVs7X5rw==", + "dev": true, + "requires": { + "@types/connect": "*", + "@types/express": "*", + "@types/keygrip": "*", + "@types/node": "*" + } + }, + "@types/debug": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz", + "integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==", + "dev": true + }, "@types/events": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==" }, + "@types/express": { + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.3.tgz", + "integrity": "sha512-I8cGRJj3pyOLs/HndoP+25vOqhqWkAZsWMEmq1qXy/b/M3ppufecUwaK2/TVDVxcV61/iSdhykUjQQ2DLSrTdg==", + "dev": true, + "requires": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "*", + "@types/serve-static": "*" + } + }, + "@types/express-serve-static-core": { + "version": "4.17.3", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.3.tgz", + "integrity": "sha512-sHEsvEzjqN+zLbqP+8OXTipc10yH1QLR+hnr5uw29gi9AhCAAAdri8ClNV7iMdrJrIzXIQtlkPvq8tJGhj3QJQ==", + "dev": true, + "requires": { + "@types/node": "*", + "@types/range-parser": "*" + } + }, "@types/formidable": { "version": "1.0.31", "resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-1.0.31.tgz", @@ -360,6 +427,111 @@ "@types/node": "*" } }, + "@types/highlight.js": { + "version": "9.12.3", + "resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.3.tgz", + "integrity": "sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==", + "dev": true + }, + "@types/http-assert": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz", + "integrity": "sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ==", + "dev": true + }, + "@types/keygrip": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz", + "integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==", + "dev": true + }, + "@types/koa": { + "version": "2.11.2", + "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.11.2.tgz", + "integrity": "sha512-2UPelagNNW6bnc1I5kIzluCaheXRA9S+NyOdXEFFj9Az7jc15ek5V03kb8OTbb3tdZ5i2BIJObe86PhHvpMolg==", + "dev": true, + "requires": { + "@types/accepts": "*", + "@types/cookies": "*", + "@types/http-assert": "*", + "@types/keygrip": "*", + "@types/koa-compose": "*", + "@types/node": "*" + } + }, + "@types/koa-compose": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz", + "integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==", + "dev": true, + "requires": { + "@types/koa": "*" + } + }, + "@types/koa-mount": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/koa-mount/-/koa-mount-4.0.0.tgz", + "integrity": "sha512-56iBULArwY3uKLl28eRFchZ2v0diEoJzJbDaHH/ehgruF/s2/KMHyWsKcIhvDJ3tGdKu9oZNQvxaMg++1IKFdA==", + "dev": true, + "requires": { + "@types/koa": "*" + } + }, + "@types/koa-send": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@types/koa-send/-/koa-send-4.1.2.tgz", + "integrity": "sha512-rfqKIv9bFds39Jxvsp8o3YJLnEQVPVriYA14AuO2OY65IHh/4UX4U/iMs5L0wATpcRmm1bbe0BNk23TRwx3VQQ==", + "dev": true, + "requires": { + "@types/koa": "*" + } + }, + "@types/koa-static": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@types/koa-static/-/koa-static-4.0.1.tgz", + "integrity": "sha512-SSpct5fEcAeRkBHa3RiwCIRfDHcD1cZRhwRF///ZfvRt8KhoqRrhK6wpDlYPk/vWHVFE9hPGqh68bhzsHkir4w==", + "dev": true, + "requires": { + "@types/koa": "*", + "@types/koa-send": "*" + } + }, + "@types/koa__router": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@types/koa__router/-/koa__router-8.0.2.tgz", + "integrity": "sha512-3ZWfVAEcErHrZA31fWUC2YyZyAgoG4eKtQPy2XwBzdSpQealxjL7GcEEtGY925qPPs1wurW59qDl0KuRB39rrw==", + "dev": true, + "requires": { + "@types/koa": "*" + } + }, + "@types/linkify-it": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-2.1.0.tgz", + "integrity": "sha512-Q7DYAOi9O/+cLLhdaSvKdaumWyHbm7HAk/bFwwyTuU0arR5yyCeW5GOoqt4tJTpDRxhpx9Q8kQL6vMpuw9hDSw==", + "dev": true + }, + "@types/lodash": { + "version": "4.14.149", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz", + "integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==", + "dev": true + }, + "@types/markdown-it": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-0.0.9.tgz", + "integrity": "sha512-IFSepyZXbF4dgSvsk8EsgaQ/8Msv1I5eTL0BZ0X3iGO9jw6tCVtPG8HchIPm3wrkmGdqZOD42kE0zplVi1gYDA==", + "dev": true, + "requires": { + "@types/linkify-it": "*" + } + }, + "@types/mime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz", + "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==", + "dev": true + }, "@types/minimatch": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", @@ -372,11 +544,29 @@ "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=", "dev": true }, + "@types/mkdirp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.0.tgz", + "integrity": "sha512-ONFY9//bCEr3DWKON3iDv/Q8LXnhaYYaNDeFSN0AtO5o4sLf9F0pstJKKKjQhXE0kJEeHs8eR6SAsROhhc2Csw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/node": { "version": "13.5.0", "resolved": "https://registry.npmjs.org/@types/node/-/node-13.5.0.tgz", "integrity": "sha512-Onhn+z72D2O2Pb2ql2xukJ55rglumsVo1H6Fmyi8mlU9SvKdBk/pUSUAiBY/d9bAOF7VVWajX3sths/+g6ZiAQ==" }, + "@types/nodemon": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/@types/nodemon/-/nodemon-1.19.0.tgz", + "integrity": "sha512-nf0PKjNv3wo0pyhlPkHjfpU2oUYMdOIsCXceiFG6kvhYxbTwn2ne9mz2iWvJ/4QtCrJUEPJLNXuyGleyTacdaw==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -389,6 +579,37 @@ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", "dev": true }, + "@types/pull-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@types/pull-stream/-/pull-stream-3.6.0.tgz", + "integrity": "sha512-d7cobAytjsYaTluqFTJopLbdZRs1HBkU+N07/zCtsXANZ5s9riDazRkvxkAUfmRzCvXqYAsGgnJHgX2lInIOQg==", + "dev": true + }, + "@types/range-parser": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz", + "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==", + "dev": true + }, + "@types/serve-static": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz", + "integrity": "sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==", + "dev": true, + "requires": { + "@types/express-serve-static-core": "*", + "@types/mime": "*" + } + }, + "@types/sharp": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.23.1.tgz", + "integrity": "sha512-iBRM9RjRF9pkIkukk6imlxfaKMRuiRND8L0yYKl5PJu5uLvxuNzp5f0x8aoTG5VX85M8O//BwbttzFVZL1j/FQ==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/unist": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", @@ -415,6 +636,21 @@ "vfile-message": "*" } }, + "@types/yargs": { + "version": "15.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz", + "integrity": "sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", + "integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", + "dev": true + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", diff --git a/package.json b/package.json index 8c8baec..1131ed6 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,19 @@ "yargs": "^15.3.1" }, "devDependencies": { + "@types/debug": "^4.1.5", + "@types/highlight.js": "^9.12.3", + "@types/koa": "^2.11.2", + "@types/koa-mount": "^4.0.0", + "@types/koa-static": "^4.0.1", + "@types/koa__router": "^8.0.2", + "@types/lodash": "^4.14.149", + "@types/markdown-it": "^0.0.9", + "@types/mkdirp": "^1.0.0", + "@types/nodemon": "^1.19.0", + "@types/pull-stream": "^3.6.0", + "@types/sharp": "^0.23.1", + "@types/yargs": "^15.0.4", "changelog-version": "^1.0.1", "common-good": "^2.0.3", "husky": "^4.0.0", diff --git a/src/http.js b/src/http.js index c085404..7984021 100644 --- a/src/http.js +++ b/src/http.js @@ -4,14 +4,15 @@ const path = require("path"); const mount = require("koa-mount"); /** - * @param {{ host: string, port: number, middleware: [] }} input + * @type function + * @param {{ host: string, port: number, middleware }} input + * @return function */ -module.exports = ({ host, port, middleware }) => { +const http = ({ host, port, middleware }) => { const assets = new Koa(); assets.use(koaStatic(path.join(__dirname, "assets"))); const app = new Koa(); - module.exports = app; app.on("error", (err) => { // Output full error objects @@ -59,16 +60,23 @@ module.exports = ({ host, port, middleware }) => { if (ctx.method !== "GET") { const referer = ctx.request.header.referer; - ctx.assert(referer != null, `HTTP ${ctx.method} must include referer`); + ctx.assert( + referer != null, + 400, + `HTTP ${ctx.method} must include referer` + ); const refererUrl = new URL(referer); const isBlobReferer = refererUrl.pathname.startsWith("/blob/"); ctx.assert( isBlobReferer === false, + 400, `HTTP ${ctx.method} from blob URL not allowed` ); } }); middleware.forEach((m) => app.use(m)); - app.listen({ host, port }); + return app.listen({ host, port }); }; + +module.exports = http; diff --git a/src/index.js b/src/index.js index ddd50a3..2b3bea5 100755 --- a/src/index.js +++ b/src/index.js @@ -38,10 +38,10 @@ if (config.debug) { const nodeHttp = require("http"); const debug = require("debug")("oasis"); -const log = (...args) => { +const log = (formatter, ...args) => { const isDebugEnabled = debug.enabled; debug.enabled = true; - debug(...args); + debug(formatter, ...args); debug.enabled = isDebugEnabled; }; @@ -123,7 +123,7 @@ const { nav, ul, li, a } = require("hyperaxe"); const open = require("open"); const pull = require("pull-stream"); const requireStyle = require("require-style"); -const router = require("@koa/router")(); +const koaRouter = require("@koa/router"); const ssbMentions = require("ssb-mentions"); const ssbRef = require("ssb-ref"); const isSvg = require("is-svg"); @@ -132,6 +132,8 @@ const { isFeed, isMsg, isBlob } = require("ssb-ref"); const ssb = require("./ssb"); +const router = new koaRouter(); + // Create "cooler"-style interface from SSB connection. // This handle is passed to the models for their convenience. const cooler = ssb({ offline: config.offline }); @@ -192,7 +194,11 @@ router const isInteger = size % 1 === 0; const overMinSize = size > 2; const underMaxSize = size <= 256; - ctx.assert(isInteger && overMinSize && underMaxSize, "Invalid image size"); + ctx.assert( + isInteger && overMinSize && underMaxSize, + 400, + "Invalid image size" + ); return next(); }) .param("blobId", (blobId, ctx, next) => { @@ -418,6 +424,11 @@ router } // This prevents an auto-download when visiting the URL. + // + // Using @ts-ignore to circumvent a bug: + // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/43357 + // + // @ts-ignore ctx.attachment(blobId, { type: "inline" }); // If we don't do this explicitly the browser downloads the SVG and thinks @@ -664,13 +675,13 @@ router const { feed } = ctx.params; const referer = new URL(ctx.request.header.referer); ctx.body = await friend.follow(feed); - ctx.redirect(referer); + ctx.redirect(referer.href); }) .post("/unfollow/:feed", koaBody(), async (ctx) => { const { feed } = ctx.params; const referer = new URL(ctx.request.header.referer); ctx.body = await friend.unfollow(feed); - ctx.redirect(referer); + ctx.redirect(referer.href); }) .post("/like/:message", koaBody(), async (ctx) => { const { message } = ctx.params; @@ -710,19 +721,19 @@ router return vote.publish({ messageKey, value, recps: recipients }); }; ctx.body = await like({ messageKey, voteValue }); - ctx.redirect(referer); + ctx.redirect(referer.href); }) .post("/theme.css", koaBody(), async (ctx) => { const theme = String(ctx.request.body.theme); ctx.cookies.set("theme", theme); const referer = new URL(ctx.request.header.referer); - ctx.redirect(referer); + ctx.redirect(referer.href); }) .post("/language", koaBody(), async (ctx) => { const language = String(ctx.request.body.language); ctx.cookies.set("language", language); const referer = new URL(ctx.request.header.referer); - ctx.redirect(referer); + ctx.redirect(referer.href); }) .post("/settings/conn/start", koaBody(), async (ctx) => { await meta.connStart(); diff --git a/src/ssb.js b/src/ssb.js index 5579260..7e292d0 100644 --- a/src/ssb.js +++ b/src/ssb.js @@ -23,10 +23,10 @@ ssbConfig.connections.incoming.unix = [ { scope: "device", transform: "noauth" }, ]; -const log = (...args) => { +const log = (formatter, ...args) => { const isDebugEnabled = debug.enabled; debug.enabled = true; - debug(...args); + debug(formatter, ...args); debug.enabled = isDebugEnabled; }; diff --git a/src/views/i18n.js b/src/views/i18n.js index c91aaeb..d29069e 100644 --- a/src/views/i18n.js +++ b/src/views/i18n.js @@ -1,6 +1,6 @@ const { a, em, strong } = require("hyperaxe"); -module.exports = { +const i18n = { en: { // navbar items extended: "Extended", @@ -510,3 +510,5 @@ module.exports = { "Beiträge von Leuten in deinem Netzwerk die dieses Hashtag referenzieren, sortiert nach Aktualität.", }, }; + +module.exports = i18n; diff --git a/src/views/index.js b/src/views/index.js index 9fbd747..9974f46 100644 --- a/src/views/index.js +++ b/src/views/index.js @@ -47,8 +47,8 @@ const markdown = require("./markdown"); const md = new MarkdownIt(); const i18nBase = require("./i18n"); -let i18n = null; -let selectedLanguage = null; +let selectedLanguage = "en"; +let i18n = i18nBase[selectedLanguage]; exports.setLanguage = (language) => { selectedLanguage = language; diff --git a/src/views/markdown.js b/src/views/markdown.js index 4a60a58..756708c 100644 --- a/src/views/markdown.js +++ b/src/views/markdown.js @@ -53,5 +53,6 @@ const toUrl = (mentions) => { module.exports = (input, mentions = []) => md.block(input, { toUrl: toUrl(mentions), + /** @param character {string} */ emoji: (character) => span({ class: "emoji" }, character).outerHTML, });