refactor: Properly unescape tags, update deps, simplify code with lodash, use Remy's eslint rules (Closes #1375)

Signed-off-by: Richie Bendall <richiebendall@gmail.com>
This commit is contained in:
Richie Bendall 2019-11-06 20:08:34 +13:00
parent 2cd12f2695
commit 054b6b76c7
No known key found for this signature in database
GPG key ID: 1C6A99DFA9D306FC
8 changed files with 35 additions and 52 deletions

1
.eslintrc.js Normal file
View file

@ -0,0 +1 @@
module.exports = require('@remy/eslint')('node');

View file

@ -1,25 +0,0 @@
{
"env": {
"browser": true,
"es6": true,
"node": true
},
"plugins": [
"node"
],
"extends": [
"plugin:prettier/recommended",
"eslint:recommended",
"plugin:node/recommended"
],
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module",
"warnOnUnsupportedTypeScriptVersion": false
},
"rules": {
"prettier/prettier": "error",
"node/no-deprecated-api": 0,
"no-console": 0
}
}

View file

@ -1,3 +0,0 @@
# use the prettier defaults except for:
trailingComma: "es5"
singleQuote: true

View file

@ -30,33 +30,34 @@
}, },
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@octokit/rest": "^16.33.1", "@octokit/rest": "^16.34.1",
"btoa": "^1.2.1", "btoa": "^1.2.1",
"ejs": "^2.7.1", "ejs": "^2.7.1",
"express": "^4.17.1", "express": "^4.17.1",
"express-minify": "^1.0.0", "express-minify": "^1.0.0",
"lodash": "^4.17.15",
"md5": "^2.2.1", "md5": "^2.2.1",
"postcss-middleware": "^1.1.4", "postcss-middleware": "^1.1.4",
"postcss-preset-env": "^6.7.0", "postcss-preset-env": "^6.7.0",
"serve-favicon": "^2.5.0" "serve-favicon": "^2.5.0"
}, },
"devDependencies": { "devDependencies": {
"@remy/eslint": "^3.2.2",
"@types/btoa": "^1.2.3", "@types/btoa": "^1.2.3",
"@types/css": "^0.0.31", "@types/css": "^0.0.31",
"@types/ejs": "^2.6.3", "@types/ejs": "^2.6.3",
"@types/express": "^4.17.1", "@types/express": "^4.17.2",
"@types/express-minify": "^0.1.34", "@types/express-minify": "^0.1.34",
"@types/lodash": "^4.14.144",
"@types/md5": "^2.1.33", "@types/md5": "^2.1.33",
"@types/node": "^12.11.1", "@types/node": "^12.12.6",
"babel-eslint": "^10.0.3",
"css": "^2.2.4", "css": "^2.2.4",
"eslint": "^6.5.1", "eslint": "^6.6.0",
"eslint-config-prettier": "^6.4.0",
"eslint-plugin-node": "^10.0.0", "eslint-plugin-node": "^10.0.0",
"eslint-plugin-prettier": "^3.1.1",
"has-flag": "^4.0.0", "has-flag": "^4.0.0",
"husky": "^3.0.9", "husky": "^3.0.9",
"nodemon": "^1.19.4", "nodemon": "^1.19.4"
"prettier": "^1.18.2"
}, },
"resolutions": { "resolutions": {
"postcss-middleware/vinyl-fs/glob-stream/micromatch/braces": "^3.0.2" "postcss-middleware/vinyl-fs/glob-stream/micromatch/braces": "^3.0.2"

View file

@ -1,14 +1,14 @@
const md5 = require('md5'); const md5 = require('md5');
const path = require('path'); const path = require('path');
const { stripTags, escapeTags } = require('./utils'); const { stripTags, escapeTags, unescapeTags } = require('./utils');
const _ = require('lodash');
function getCopyrightHTML(user, plain) { function getCopyrightHTML(user, plain) {
let html = ''; let html = '';
const name = const name = _.isString(user)
typeof user === 'string' ? user
? user : plain
: plain
? user.name || user.copyright ? user.name || user.copyright
: escapeTags(user.name || user.copyright); : escapeTags(user.name || user.copyright);
@ -34,9 +34,9 @@ module.exports = (req, res) => {
// No error and valid // No error and valid
if (user.copyright) { if (user.copyright) {
if (typeof user.copyright === 'string') { if (_.isString(user.copyright)) {
name = getCopyrightHTML(user, options.format !== 'html'); name = getCopyrightHTML(user, options.format !== 'html');
} else if (user.copyright.every(val => typeof val === 'string')) { } else if (user.copyright.every(val => _.isString(val))) {
// Supports: ['Remy Sharp', 'Richie Bendall'] // Supports: ['Remy Sharp', 'Richie Bendall']
name = user name = user
.map(_ => (options.format !== 'html' ? _ : escapeTags(_))) .map(_ => (options.format !== 'html' ? _ : escapeTags(_)))
@ -51,7 +51,7 @@ module.exports = (req, res) => {
gravatar = `<img id="gravatar" alt="Profile image" src="https://www.gravatar.com/avatar/${md5( gravatar = `<img id="gravatar" alt="Profile image" src="https://www.gravatar.com/avatar/${md5(
user.email.trim().toLowerCase() user.email.trim().toLowerCase()
)}" />`; )}" />`;
} else if (typeof user.copyright[0] === 'object' && user.gravatar) { } else if (_.isObject(user.copyright[0]) && user.gravatar) {
// Supports multi-user format // Supports multi-user format
gravatar = `<img id="gravatar" alt="Profile image" src="https://www.gravatar.com/avatar/${md5( gravatar = `<img id="gravatar" alt="Profile image" src="https://www.gravatar.com/avatar/${md5(
user.copyright[0].email.trim().toLowerCase() user.copyright[0].email.trim().toLowerCase()
@ -82,7 +82,7 @@ module.exports = (req, res) => {
res res
.set('Content-Type', 'text/plain; charset=UTF-8') .set('Content-Type', 'text/plain; charset=UTF-8')
.send(stripTags(plain).trim()); .send(unescapeTags(stripTags(plain)).trim());
return; return;
} }

View file

@ -5,6 +5,7 @@ const access = promisify(fs.access);
const writeFile = promisify(fs.writeFile); const writeFile = promisify(fs.writeFile);
const btoa = require('btoa'); const btoa = require('btoa');
const { version } = require(path.join(__dirname, '..', 'package.json')); const { version } = require(path.join(__dirname, '..', 'package.json'));
const _ = require('lodash');
const github = require('@octokit/rest')({ const github = require('@octokit/rest')({
// GitHub personal access token // GitHub personal access token
auth: process.env.github_token, auth: process.env.github_token,
@ -15,10 +16,10 @@ const { validDomainId } = require('./utils');
function getUserData({ query, body }) { function getUserData({ query, body }) {
// If query parameters provided // If query parameters provided
if (Object.keys(query).length > 0) return query; if (_.size(query) > 0) return query;
// If the data parsed as {'{data: "value"}': ''} // If the data parsed as {'{data: "value"}': ''}
const keys = Object.keys(body); if (_.size(body) === 1 && !_.first(_.values(body)))
if (keys.length === 1 && !Object.values(body)[0]) return JSON.parse(keys[0]); return JSON.parse(_.first(_.keys(body)));
// Fallback // Fallback
return body; return body;
} }
@ -39,7 +40,7 @@ module.exports = async (req, res) => {
} }
// Extract the name from the URL // Extract the name from the URL
const id = params[0]; const id = _.first(params);
if (!validDomainId(id)) { if (!validDomainId(id)) {
// Return a vague error intentionally // Return a vague error intentionally

View file

@ -1,8 +1,16 @@
const _ = require('lodash');
const tags = { const tags = {
'<': '&lt;', '<': '&lt;',
'>': '&gt;', '>': '&gt;',
'&': '&amp;', '&': '&amp;',
}; };
exports.escapeTags = str => (str || '').replace(/[<>&]/g, m => tags[m]); const untags = _.invert(tags);
exports.stripTags = str => (str || '').replace(/<(?:.|\n)*?>/gm, '');
exports.validDomainId = str => /^[\w-_]+$/.test(str); module.exports = {
escapeTags: str => (str || '').replace(/[<>&]/g, m => tags[m]),
unescapeTags: str =>
(str || '').replace(/(&lt;|&gt;|&amp;)/g, m => untags[m]),
stripTags: str => (str || '').replace(/<(?:.|\n)*?>/gm, ''),
validDomainId: str => /^[\w-_]+$/.test(str),
};

BIN
yarn.lock

Binary file not shown.