organized files better
This commit is contained in:
parent
ccdd7ad589
commit
74f3706852
96
package-lock.json
generated
96
package-lock.json
generated
@ -1974,31 +1974,12 @@
|
||||
"dev": true
|
||||
},
|
||||
"bcrypt": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-4.0.1.tgz",
|
||||
"integrity": "sha512-hSIZHkUxIDS5zA2o00Kf2O5RfVbQ888n54xQoF/eIaquU4uaLxK8vhhBdktd0B3n2MjkcAWzv4mnhogykBKOUQ==",
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.0.0.tgz",
|
||||
"integrity": "sha512-jB0yCBl4W/kVHM2whjfyqnxTmOHkCX4kHEa5nYKSoGeYe8YrjTYTc87/6bwt1g8cmV0QrbhKriETg9jWtcREhg==",
|
||||
"requires": {
|
||||
"node-addon-api": "^2.0.0",
|
||||
"node-pre-gyp": "0.14.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"node-pre-gyp": {
|
||||
"version": "0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz",
|
||||
"integrity": "sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA==",
|
||||
"requires": {
|
||||
"detect-libc": "^1.0.2",
|
||||
"mkdirp": "^0.5.1",
|
||||
"needle": "^2.2.1",
|
||||
"nopt": "^4.0.1",
|
||||
"npm-packlist": "^1.1.6",
|
||||
"npmlog": "^4.0.2",
|
||||
"rc": "^1.2.7",
|
||||
"rimraf": "^2.6.1",
|
||||
"semver": "^5.3.0",
|
||||
"tar": "^4.4.2"
|
||||
}
|
||||
}
|
||||
"node-addon-api": "^3.0.0",
|
||||
"node-pre-gyp": "0.15.0"
|
||||
}
|
||||
},
|
||||
"big.js": {
|
||||
@ -4767,9 +4748,9 @@
|
||||
}
|
||||
},
|
||||
"needle": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/needle/-/needle-2.5.0.tgz",
|
||||
"integrity": "sha512-o/qITSDR0JCyCKEQ1/1bnUXMmznxabbwi/Y4WwJElf+evwJNFNwIDMCCt5IigFVxgeGBJESLohGtIS9gEzo1fA==",
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/needle/-/needle-2.5.2.tgz",
|
||||
"integrity": "sha512-LbRIwS9BfkPvNwNHlsA41Q29kL2L/6VaOJ0qisM5lLWsTV3nP15abO5ITL6L81zqFhzjRKDAYjpcBcwM0AVvLQ==",
|
||||
"requires": {
|
||||
"debug": "^3.2.6",
|
||||
"iconv-lite": "^0.4.4",
|
||||
@ -4823,9 +4804,9 @@
|
||||
"integrity": "sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q=="
|
||||
},
|
||||
"node-addon-api": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.1.tgz",
|
||||
"integrity": "sha512-2WVfwRfIr1AVn3dRq4yRc2Hn35ND+mPJH6inC6bjpYCZVrpXPB4j3T6i//OGVfqVsR1t/X/axRulDsheq4F0LQ=="
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.0.0.tgz",
|
||||
"integrity": "sha512-sSHCgWfJ+Lui/u+0msF3oyCgvdkhxDbkCS6Q8uiJquzOimkJBvX6hl5aSSA7DR1XbMpdM8r7phjcF63sF4rkKg=="
|
||||
},
|
||||
"node-libs-browser": {
|
||||
"version": "2.2.1",
|
||||
@ -4866,6 +4847,23 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node-pre-gyp": {
|
||||
"version": "0.15.0",
|
||||
"resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.15.0.tgz",
|
||||
"integrity": "sha512-7QcZa8/fpaU/BKenjcaeFF9hLz2+7S9AqyXFhlH/rilsQ/hPZKK32RtR5EQHJElgu+q5RfbJ34KriI79UWaorA==",
|
||||
"requires": {
|
||||
"detect-libc": "^1.0.2",
|
||||
"mkdirp": "^0.5.3",
|
||||
"needle": "^2.5.0",
|
||||
"nopt": "^4.0.1",
|
||||
"npm-packlist": "^1.1.6",
|
||||
"npmlog": "^4.0.2",
|
||||
"rc": "^1.2.7",
|
||||
"rimraf": "^2.6.1",
|
||||
"semver": "^5.3.0",
|
||||
"tar": "^4.4.2"
|
||||
}
|
||||
},
|
||||
"node-releases": {
|
||||
"version": "1.1.60",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz",
|
||||
@ -5385,6 +5383,11 @@
|
||||
"integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=",
|
||||
"dev": true
|
||||
},
|
||||
"pseudomap": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
|
||||
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
|
||||
},
|
||||
"public-encrypt": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
|
||||
@ -6522,6 +6525,14 @@
|
||||
"setimmediate": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.0.33",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
|
||||
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
|
||||
"requires": {
|
||||
"os-tmpdir": "~1.0.2"
|
||||
}
|
||||
},
|
||||
"to-arraybuffer": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
|
||||
@ -6787,6 +6798,31 @@
|
||||
"integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
|
||||
"dev": true
|
||||
},
|
||||
"useragent": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz",
|
||||
"integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==",
|
||||
"requires": {
|
||||
"lru-cache": "4.1.x",
|
||||
"tmp": "0.0.x"
|
||||
},
|
||||
"dependencies": {
|
||||
"lru-cache": {
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
|
||||
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
|
||||
"requires": {
|
||||
"pseudomap": "^1.0.2",
|
||||
"yallist": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"yallist": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
|
||||
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
|
||||
}
|
||||
}
|
||||
},
|
||||
"util": {
|
||||
"version": "0.11.1",
|
||||
"resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
|
||||
|
@ -12,7 +12,7 @@
|
||||
"test": "run-p --race dev cy:run"
|
||||
},
|
||||
"dependencies": {
|
||||
"bcrypt": "^4.0.1",
|
||||
"bcrypt": "^5.0.0",
|
||||
"body-parser": "^1.19.0",
|
||||
"cl-editor": "^2.1.0",
|
||||
"compression": "^1.7.1",
|
||||
@ -28,7 +28,8 @@
|
||||
"passport": "^0.4.1",
|
||||
"passport-local": "^1.0.0",
|
||||
"rate-limiter-flexible": "^2.1.10",
|
||||
"session-file-store": "^1.4.0"
|
||||
"session-file-store": "^1.4.0",
|
||||
"useragent": "^2.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.11.4",
|
||||
|
93
src/routes/cms/register.js
Normal file
93
src/routes/cms/register.js
Normal file
@ -0,0 +1,93 @@
|
||||
import User from '../../models/user.js';
|
||||
|
||||
export async function post(req, res)
|
||||
{
|
||||
if (req.user) {
|
||||
res.writeHead(401, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `You are already logged in`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
let { username, password, password_confirm, realname } = req.body;
|
||||
if (!username || !password || !password_confirm || !realname) {
|
||||
res.writeHead(422, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `You need to supply a username, real name, password, and password confirmation.`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
if (password.length < 8) {
|
||||
res.writeHead(422, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `The password must be at least 8 characters long.`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
if (password !== password_confirm) {
|
||||
res.writeHead(422, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `The password does not match the confirmation.`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
if (!/^[a-z0-9.]+$/i.test(username)) {
|
||||
res.writeHead(422, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `The username can only contain letters, numbers, and periods.`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
try {
|
||||
await registerRateLimiter.consume();
|
||||
} catch (err) {
|
||||
res.writeHead(429, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `Too Many Requests`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
try {
|
||||
const user = await User.findOne({ username: req.body.username });
|
||||
if (user) {
|
||||
res.writeHead(401, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `This username is taken.`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
// password gets automatically hashed
|
||||
const newUser = await new User({ username, realname, password });
|
||||
await newUser.save();
|
||||
|
||||
req.login(newUser, err => {
|
||||
if (err) throw err;
|
||||
return res.redirect('/cms');
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.writeHead(500, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `Internal server error`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
}
|
26
src/routes/me/avatar.js
Normal file
26
src/routes/me/avatar.js
Normal file
@ -0,0 +1,26 @@
|
||||
import fs from 'fs';
|
||||
import User from '../../models/user.js';
|
||||
|
||||
export async function del(req, res)
|
||||
{
|
||||
if (!req.user) {
|
||||
res.writeHead(401, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `You must be logged in to set an avatar.`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
const user = await User.findById(req.user._id);
|
||||
const filename = 'default.jpg';
|
||||
if (user.avatar !== filename) {
|
||||
fs.unlinkSync(`./static/u/${user.avatar}`);
|
||||
}
|
||||
req.user.avatar = user.avatar = filename;
|
||||
await user.save();
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({ filename }));
|
||||
}
|
16
src/routes/me/index.js
Normal file
16
src/routes/me/index.js
Normal file
@ -0,0 +1,16 @@
|
||||
export function get(req, res, next)
|
||||
{
|
||||
if (req.user) {
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify(req.user));
|
||||
} else {
|
||||
res.writeHead(401, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `You are not logged in`
|
||||
}));
|
||||
}
|
||||
}
|
141
src/server.js
141
src/server.js
@ -12,6 +12,7 @@ import fileUpload from 'express-fileupload';
|
||||
import fs from 'fs';
|
||||
import cors from 'cors';
|
||||
import helmet from 'helmet';
|
||||
import useragent from 'useragent';
|
||||
import crypto from 'crypto';
|
||||
import Article from './models/article.js';
|
||||
import Category from './models/category.js';
|
||||
@ -130,101 +131,6 @@ express()
|
||||
.use(passport.initialize())
|
||||
.use(passport.session())
|
||||
|
||||
.post('/cms/register',
|
||||
function(req, res, next) {
|
||||
if (!req.user) {
|
||||
next();
|
||||
} else {
|
||||
res.writeHead(401, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `You are already logged in`
|
||||
}));
|
||||
}
|
||||
}, async (req, res) => {
|
||||
let { username, password, password_confirm, realname } = req.body;
|
||||
if (!username || !password || !password_confirm || !realname) {
|
||||
res.writeHead(422, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `You need to supply a username, real name, password, and password confirmation.`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
if (password.length < 8) {
|
||||
res.writeHead(422, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `The password must be at least 8 characters long.`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
if (password !== password_confirm) {
|
||||
res.writeHead(422, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `The password does not match the confirmation.`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
if (!/^[a-z0-9.]+$/i.test(username)) {
|
||||
res.writeHead(422, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `The username can only contain letters, numbers, and periods.`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
try {
|
||||
await registerRateLimiter.consume();
|
||||
} catch (err) {
|
||||
res.writeHead(429, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `Too Many Requests`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
try {
|
||||
const user = await User.findOne({ username: req.body.username });
|
||||
if (user) {
|
||||
res.writeHead(401, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `This username is taken.`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
// password gets automatically hashed
|
||||
const newUser = await new User({ username, realname, password });
|
||||
await newUser.save();
|
||||
|
||||
req.login(newUser, err => {
|
||||
if (err) throw err;
|
||||
return res.redirect('/cms');
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
res.writeHead(500, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `Internal server error`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
.post('/cms/login',
|
||||
// rateLimiterMiddleware(loginAttemptRateLimiter),
|
||||
passport.authenticate('local', { failWithError: true }),
|
||||
@ -433,22 +339,6 @@ express()
|
||||
}
|
||||
)
|
||||
|
||||
.get('/me', function(req, res, next) {
|
||||
if (req.user) {
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify(req.user));
|
||||
} else {
|
||||
res.writeHead(401, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `You are not logged in`
|
||||
}));
|
||||
}
|
||||
})
|
||||
|
||||
.post('/me/avatar',
|
||||
async function(req, res, next) {
|
||||
if (!req.user) {
|
||||
@ -511,33 +401,12 @@ express()
|
||||
}
|
||||
)
|
||||
|
||||
.delete('/me/avatar',
|
||||
async function(req, res, next) {
|
||||
if (!req.user) {
|
||||
res.writeHead(401, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({
|
||||
message: `You must be logged in to set an avatar.`
|
||||
}));
|
||||
return false;
|
||||
}
|
||||
const user = await User.findById(req.user._id);
|
||||
const filename = 'default.jpg';
|
||||
if (user.avatar !== filename) {
|
||||
fs.unlinkSync(`./static/u/${user.avatar}`);
|
||||
}
|
||||
req.user.avatar = user.avatar = filename;
|
||||
await user.save();
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'application/json'
|
||||
});
|
||||
res.end(JSON.stringify({ filename }));
|
||||
}
|
||||
)
|
||||
|
||||
.use(compression({ threshold: 0 }))
|
||||
.use(express.static('./static'))
|
||||
.use(async function (req, res, next) {
|
||||
if (req.useragent.browser) {
|
||||
}
|
||||
})
|
||||
.use(sapper.middleware({
|
||||
session: req => ({
|
||||
user: req.session.passport ? req.session.passport.user : null
|
||||
|
Loading…
x
Reference in New Issue
Block a user