Merge branch 'master' of github.com:fraction/oasis into upgrade-koa-router
This commit is contained in:
commit
925e4bc78b
@ -3,9 +3,11 @@
|
||||
"language": "en",
|
||||
"words": [
|
||||
"AGPL",
|
||||
"APPDATA",
|
||||
"Argyris",
|
||||
"CSRF",
|
||||
"EACCESS",
|
||||
"EXIF",
|
||||
"Hintjens",
|
||||
"Kata",
|
||||
"LGPL",
|
||||
@ -39,6 +41,7 @@
|
||||
"patchbay",
|
||||
"patchfoo",
|
||||
"patchfox",
|
||||
"piexifjs",
|
||||
"promisify",
|
||||
"rebecca",
|
||||
"recps",
|
||||
|
@ -5,7 +5,6 @@ standard folder for configuration, depending on your operating system:
|
||||
|
||||
- Linux: `$XDG_CONFIG_HOME/oasis/default.json`.
|
||||
Usually this is `/home/<your username>/.config/oasis/default.json`
|
||||
<!-- cspell:disable-next-line -->
|
||||
- Windows `%APPDATA%\oasis\default.json`.
|
||||
- Mac OS, `/Users/<your username>/Library/Preferences/oasis/default.json`
|
||||
|
||||
|
@ -24,6 +24,9 @@ Please run `npm test` before writing a commit, because if there are errors then
|
||||
maintainers won't be able to merge your patch. Please ask for help if `npm test`
|
||||
is giving you any trouble.
|
||||
|
||||
**Note:** `npm run fix` is run automatically as a pre-commit hook. You always
|
||||
have the option to disable pre-commit hooks with `git commit --no-verify`.
|
||||
|
||||
## Frequently Failed Tests
|
||||
|
||||
### Unknown word
|
||||
|
2357
package-lock.json
generated
2357
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
30
package.json
30
package.json
@ -16,13 +16,12 @@
|
||||
"dev": "nodemon --inspect src/index.js --debug --no-open",
|
||||
"fix": "common-good fix",
|
||||
"start": "node src/index.js",
|
||||
"test": "tap --timeout 240 && common-good check --dependency-check-suffix '-i changelog-version -i mkdirp -i nodemon -i stylelint-config-recommended'",
|
||||
"test": "tap --timeout 240 && common-good check --dependency-check-suffix '-i changelog-version -i mkdirp -i nodemon -i stylelint-config-recommended -i husky'",
|
||||
"preversion": "npm test",
|
||||
"version": "mv docs/CHANGELOG.md ./ && changelog-version && mv CHANGELOG.md docs/ && git add docs/CHANGELOG.md"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fraction/base16-css": "^1.1.0",
|
||||
"@fraction/flotilla": "^5.2.0",
|
||||
"@koa/router": "^10.0.0",
|
||||
"debug": "^4.1.1",
|
||||
"env-paths": "^2.2.0",
|
||||
@ -35,6 +34,7 @@
|
||||
"koa-mount": "^4.0.0",
|
||||
"koa-static": "^5.0.0",
|
||||
"lodash": "^4.17.11",
|
||||
"lodash.shuffle": "^4.2.0",
|
||||
"markdown-it": "^12.0.2",
|
||||
"open": "^7.0.3",
|
||||
"piexifjs": "^1.0.4",
|
||||
@ -44,15 +44,40 @@
|
||||
"pull-sort": "^1.0.2",
|
||||
"pull-stream": "^3.6.12",
|
||||
"require-style": "^1.1.0",
|
||||
"secret-stack": "^6.3.0",
|
||||
"sharp": "^0.26.3",
|
||||
"ssb-about": "^2.0.1",
|
||||
"ssb-backlinks": "^2.1.1",
|
||||
"ssb-blobs": "^1.2.3",
|
||||
"ssb-client": "^4.9.0",
|
||||
"ssb-config": "^3.4.4",
|
||||
"ssb-conn": "^0.19.1",
|
||||
"ssb-db": "^20.3.0",
|
||||
"ssb-ebt": "^5.6.7",
|
||||
"ssb-friends": "^4.3.0",
|
||||
"ssb-invite": "^2.1.6",
|
||||
"ssb-keys": "^8.0.0",
|
||||
"ssb-lan": "^0.2.0",
|
||||
"ssb-logging": "^1.0.0",
|
||||
"ssb-markdown": "^6.0.7",
|
||||
"ssb-master": "^1.0.3",
|
||||
"ssb-meme": "^1.1.0",
|
||||
"ssb-mentions": "^0.5.2",
|
||||
"ssb-msgs": "^5.2.0",
|
||||
"ssb-no-auth": "^1.0.0",
|
||||
"ssb-onion": "^1.0.0",
|
||||
"ssb-ooo": "^1.3.3",
|
||||
"ssb-plugins": "^1.0.2",
|
||||
"ssb-private1": "^1.0.1",
|
||||
"ssb-query": "^2.4.5",
|
||||
"ssb-ref": "^2.13.9",
|
||||
"ssb-replicate": "^1.3.0",
|
||||
"ssb-room": "^1.3.0",
|
||||
"ssb-search": "^1.3.0",
|
||||
"ssb-tangle": "^1.0.1",
|
||||
"ssb-thread-schema": "^1.1.1",
|
||||
"ssb-unix-socket": "^1.0.0",
|
||||
"ssb-ws": "^6.2.3",
|
||||
"yargs": "^16.1.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@ -72,6 +97,7 @@
|
||||
"@types/yargs": "^15.0.4",
|
||||
"changelog-version": "^2.0.0",
|
||||
"common-good": "^2.0.3",
|
||||
"husky": "^4.3.0",
|
||||
"mkdirp": "^1.0.4",
|
||||
"nodemon": "^2.0.3",
|
||||
"stylelint-config-recommended": "^3.0.0",
|
||||
|
@ -144,6 +144,7 @@ section header a {
|
||||
text-decoration: none;
|
||||
margin-right: var(--size--2);
|
||||
margin-left: var(--size--2);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/* For use with elements specific for
|
||||
@ -156,6 +157,7 @@ section header a {
|
||||
section > footer > div > a,
|
||||
section > footer > div > form > button {
|
||||
color: var(--fg-status);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
section > footer > div > form > button {
|
||||
@ -333,6 +335,7 @@ nav {
|
||||
nav > ul > li > a {
|
||||
color: var(--fg);
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.author-action > a {
|
||||
@ -440,7 +443,6 @@ section > .centered-footer {
|
||||
|
||||
section > footer {
|
||||
color: var(--fg-status);
|
||||
margin-top: var(--size-0);
|
||||
}
|
||||
|
||||
section > footer br {
|
||||
|
@ -7,7 +7,6 @@ const path = require("path");
|
||||
const envPaths = require("env-paths");
|
||||
const cli = require("./cli");
|
||||
const fs = require("fs");
|
||||
// cspell:disable-next-line
|
||||
const exif = require("piexifjs");
|
||||
|
||||
const defaultConfig = {};
|
||||
@ -219,7 +218,6 @@ const preparePreview = async function (ctx) {
|
||||
return { authorMeta, text, mentions };
|
||||
};
|
||||
|
||||
// cspell:disable
|
||||
// handleBlobUpload ingests an uploaded form file.
|
||||
// it takes care of maximum blob size (5meg), exif stripping and mime detection.
|
||||
// finally it returns the correct markdown link for the blob depending on the mime-type.
|
||||
@ -284,11 +282,11 @@ const handleBlobUpload = async function (ctx) {
|
||||
name: blobUpload.name,
|
||||
};
|
||||
|
||||
// determain encoding to add the correct markdown link
|
||||
// determine encoding to add the correct markdown link
|
||||
const FileType = require("file-type");
|
||||
try {
|
||||
let ftype = await FileType.fromBuffer(data);
|
||||
blob.mime = ftype.mime;
|
||||
let fileType = await FileType.fromBuffer(data);
|
||||
blob.mime = fileType.mime;
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
blob.mime = "application/octet-stream";
|
||||
@ -305,7 +303,6 @@ const handleBlobUpload = async function (ctx) {
|
||||
return `\n[${blob.name}](${blob.id})`;
|
||||
}
|
||||
};
|
||||
// cspell:enable
|
||||
|
||||
const resolveCommentComponents = async function (ctx) {
|
||||
const { message } = ctx.params;
|
||||
|
@ -427,14 +427,19 @@ module.exports = ({ cooler, isPublic }) => {
|
||||
}),
|
||||
/**
|
||||
* @param feedId {string}
|
||||
* @returns {Promise<{me: boolean, following: boolean, blocking: boolean }>}
|
||||
* @returns {Promise<{me: boolean, following: boolean, blocking: boolean, followsMe: boolean }>}
|
||||
*/
|
||||
getRelationship: async (feedId) => {
|
||||
const ssb = await cooler.open();
|
||||
const { id } = ssb;
|
||||
|
||||
if (feedId === id) {
|
||||
return { me: true, following: false, blocking: false };
|
||||
return {
|
||||
me: true,
|
||||
following: false,
|
||||
blocking: false,
|
||||
followsMe: false,
|
||||
};
|
||||
}
|
||||
|
||||
const isFollowing = await ssb.friends.isFollowing({
|
||||
@ -456,7 +461,6 @@ module.exports = ({ cooler, isPublic }) => {
|
||||
me: false,
|
||||
following: isFollowing,
|
||||
blocking: isBlocking,
|
||||
// @ts-ignore
|
||||
followsMe: followsMe,
|
||||
};
|
||||
},
|
||||
|
56
src/ssb/flotilla.js
Normal file
56
src/ssb/flotilla.js
Normal file
@ -0,0 +1,56 @@
|
||||
const stack = require("secret-stack");
|
||||
const shuffle = require("lodash.shuffle");
|
||||
const debug = require("debug")("oasis");
|
||||
const ssbConfig = require("ssb-config");
|
||||
|
||||
const plugins = [
|
||||
// Authentication often hooked for authentication.
|
||||
require("ssb-master"),
|
||||
// Methods often used during init().
|
||||
require("ssb-db"),
|
||||
// Method `replicate()` often hooked for improvements.
|
||||
require("ssb-replicate"),
|
||||
// Required by ssb-about, ssb-tangle, etc.
|
||||
require("ssb-backlinks"),
|
||||
// Required by ssb-room
|
||||
require("ssb-conn"),
|
||||
shuffle([
|
||||
require("ssb-about"),
|
||||
require("ssb-blobs"),
|
||||
require("ssb-ebt"),
|
||||
require("ssb-friends"),
|
||||
require("ssb-invite"),
|
||||
require("ssb-lan"),
|
||||
require("ssb-logging"),
|
||||
require("ssb-meme"),
|
||||
require("ssb-no-auth"),
|
||||
require("ssb-onion"),
|
||||
require("ssb-ooo"),
|
||||
require("ssb-plugins"),
|
||||
require("ssb-private1"),
|
||||
require("ssb-query"),
|
||||
require("ssb-room/tunnel/client"),
|
||||
require("ssb-search"),
|
||||
require("ssb-tangle"),
|
||||
require("ssb-unix-socket"),
|
||||
require("ssb-ws"),
|
||||
]),
|
||||
];
|
||||
|
||||
module.exports = (config) => {
|
||||
const server = stack();
|
||||
|
||||
// TODO: Move this out of the main function.
|
||||
const walk = (input) => {
|
||||
if (Array.isArray(input)) {
|
||||
input.forEach(walk);
|
||||
} else {
|
||||
debug(input.name || "???");
|
||||
server.use(input);
|
||||
}
|
||||
};
|
||||
|
||||
walk(plugins);
|
||||
|
||||
return server({ ...ssbConfig, ...config });
|
||||
};
|
@ -7,11 +7,22 @@
|
||||
const { promisify } = require("util");
|
||||
const ssbClient = require("ssb-client");
|
||||
const ssbConfig = require("ssb-config");
|
||||
const flotilla = require("@fraction/flotilla");
|
||||
const ssbTangle = require("ssb-tangle");
|
||||
const ssbKeys = require("ssb-keys");
|
||||
const debug = require("debug")("oasis");
|
||||
const path = require("path");
|
||||
const lodash = require("lodash");
|
||||
const fs = require("fs");
|
||||
const os = require("os");
|
||||
|
||||
const flotilla = require("./flotilla");
|
||||
|
||||
// Use temporary path if we're running a test.
|
||||
// TODO: Refactor away 'OASIS_TEST' variable.
|
||||
if (process.env.OASIS_TEST) {
|
||||
ssbConfig.path = fs.mkdtempSync(path.join(os.tmpdir(), "oasis-"));
|
||||
ssbConfig.keys = ssbKeys.generate();
|
||||
}
|
||||
|
||||
const socketPath = path.join(ssbConfig.path, "socket");
|
||||
const publicInteger = ssbConfig.keys.public.replace(".ed25519", "");
|
||||
@ -50,7 +61,9 @@ const connect = (options) =>
|
||||
resolve(api);
|
||||
};
|
||||
|
||||
ssbClient(null, options).then(onSuccess).catch(reject);
|
||||
ssbClient(process.env.OASIS_TEST ? ssbConfig.keys : null, options)
|
||||
.then(onSuccess)
|
||||
.catch(reject);
|
||||
});
|
||||
|
||||
let closing = false;
|
||||
@ -64,7 +77,15 @@ let clientHandle;
|
||||
*/
|
||||
const attemptConnection = () =>
|
||||
new Promise((resolve, reject) => {
|
||||
connect({ remote })
|
||||
const originalConnect = process.env.OASIS_TEST
|
||||
? new Promise((resolve, reject) =>
|
||||
reject({
|
||||
message: "could not connect to sbot",
|
||||
})
|
||||
)
|
||||
: connect({ remote });
|
||||
|
||||
originalConnect
|
||||
.then((ssb) => {
|
||||
debug("Connected to existing Scuttlebutt service over Unix socket");
|
||||
resolve(ssb);
|
@ -70,10 +70,6 @@ const toAttributes = (obj) =>
|
||||
// non-breaking space
|
||||
const nbsp = "\xa0";
|
||||
|
||||
/**
|
||||
// @ts-ignore
|
||||
* @param {{href: string, emoji: string, text: string }} input
|
||||
*/
|
||||
const template = (titlePrefix, ...elements) => {
|
||||
const navLink = ({ href, emoji, text }) =>
|
||||
li(
|
||||
@ -1111,13 +1107,13 @@ exports.settingsView = ({ status, peers, theme, themeNames, version }) => {
|
||||
{ action: "/language", method: "post" },
|
||||
select({ name: "language" }, [
|
||||
// Languages are sorted alphabetically by their 'long name'.
|
||||
/* cspell:disable */
|
||||
/* spell-checker:disable */
|
||||
languageOption("Deutsch", "de"),
|
||||
languageOption("English", "en"),
|
||||
languageOption("Español", "es"),
|
||||
languageOption("Français", "fr"),
|
||||
languageOption("Italiano", "it"),
|
||||
/* cspell:enable */
|
||||
/* spell-checker:enable */
|
||||
]),
|
||||
button({ type: "submit" }, i18n.setLanguage)
|
||||
),
|
||||
|
@ -1,5 +1,6 @@
|
||||
// HACK: Prevent Oasis from opening the web browser.
|
||||
process.argv.push("--no-open", "--offline");
|
||||
process.env.OASIS_TEST = true;
|
||||
|
||||
const app = require("../src");
|
||||
const supertest = require("supertest");
|
||||
@ -30,40 +31,80 @@ const paths = [
|
||||
|
||||
tap.setTimeout(0);
|
||||
|
||||
tap.test("edit profile", (t) => {
|
||||
supertest(app)
|
||||
.post("/profile/edit")
|
||||
.field("name", "allison-wonderland")
|
||||
.field("description", "example description **published**")
|
||||
.attach("image", __filename)
|
||||
.set("Referer", "http://localhost:3000/")
|
||||
.set("Host", "localhost")
|
||||
.expect(302)
|
||||
.end(t.end);
|
||||
});
|
||||
|
||||
tap.test("preview", (t) => {
|
||||
supertest(app)
|
||||
.post("/publish/preview")
|
||||
.field("text", "example message **previewed**")
|
||||
.field("contentWarning", "")
|
||||
.set("Referer", "http://localhost:3000/")
|
||||
.set("Host", "localhost")
|
||||
.expect(200)
|
||||
.expect(({ text }) =>
|
||||
text.includes("example message <strong>previewed</strong>")
|
||||
)
|
||||
.end(t.end);
|
||||
});
|
||||
|
||||
tap.test("publish", (t) => {
|
||||
supertest(app)
|
||||
.post("/publish")
|
||||
.field("text", "example message **published**")
|
||||
.set("Referer", "http://localhost:3000/")
|
||||
.set("Host", "localhost")
|
||||
.expect(302)
|
||||
.end(t.end);
|
||||
});
|
||||
|
||||
tap.test("profile", (t) => {
|
||||
supertest(app)
|
||||
.get("/profile")
|
||||
.set("Host", "localhost")
|
||||
.expect(200)
|
||||
.expect(({ text }) => text.includes("allison-wonderland"))
|
||||
.expect(({ text }) =>
|
||||
text.includes("example description <strong>published</strong>")
|
||||
)
|
||||
.expect(({ text }) =>
|
||||
text.includes("example message <strong>published</strong>")
|
||||
)
|
||||
.end(t.end);
|
||||
});
|
||||
|
||||
tap.test("DNS rebind attack fails", (t) => {
|
||||
t.plan(1);
|
||||
supertest(app)
|
||||
.get("/inbox")
|
||||
.set("Host", "example.com")
|
||||
.expect(400)
|
||||
.end(t.error);
|
||||
.end(t.end);
|
||||
});
|
||||
|
||||
tap.test("CSRF attack should fail with no referer", (t) => {
|
||||
t.plan(1);
|
||||
supertest(app).post("/conn/settings/stop").expect(400).end(t.error);
|
||||
supertest(app).post("/conn/settings/stop").expect(400).end(t.end);
|
||||
});
|
||||
|
||||
tap.test("CSRF attack should fail with wrong referer", (t) => {
|
||||
t.plan(1);
|
||||
supertest(app)
|
||||
.post("/conn/settings/stop")
|
||||
.set("Host", "example.com")
|
||||
.expect(400)
|
||||
.end(t.error);
|
||||
.end(t.end);
|
||||
});
|
||||
|
||||
paths.forEach((path) => {
|
||||
tap.test(path, (t) => {
|
||||
t.plan(1);
|
||||
supertest(app)
|
||||
.get(path)
|
||||
.set("Host", "localhost")
|
||||
.expect(200)
|
||||
.end((err) => {
|
||||
console.log(path);
|
||||
t.error(err);
|
||||
});
|
||||
supertest(app).get(path).set("Host", "localhost").expect(200).end(t.end);
|
||||
});
|
||||
});
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user