post deletion checkboxes and some form validation (form validation needs refactor)

merge-requests/208/head
fatchan 5 years ago
parent dc804410c7
commit 119cee57e9
  1. 219
      controllers/api.js
  2. 2
      models/boards.js
  3. 15
      models/posts.js
  4. 351
      package-lock.json
  5. 5
      static/css/style.css
  6. 6
      views/includes/postform.pug
  7. 11
      views/mixins/post.pug
  8. 14
      views/pages/board.pug
  9. 14
      views/pages/thread.pug

@ -10,11 +10,43 @@ const express = require('express')
, fileUpload = require(__dirname+'/../helpers/file-upload.js')
, fileThumbnail = require(__dirname+'/../helpers/file-thumbnail.js')
, fileIdentify = require(__dirname+'/../helpers/file-identify.js')
, fileCheckMimeType = require(__dirname+'/../helpers/file-check-mime-types.js')
, fileCheckMimeType = require(__dirname+'/../helpers/file-check-mime-types.js');
/*
(async () => {
await Boards.deleteIncrement('b');
await Boards.deleteAll();
await Boards.insertOne({
_id: 'b',
name: 'random',
description: 'post anything here',
})
await Posts.deleteAll('b');
})();
*/
// make new post
router.post('/board/:board', Boards.exists, async (req, res, next) => {
//needs a refactor into a body validator of some sort
const fileKeys = Object.keys(req.files);
const numFiles = fileKeys.length
if (!req.body.message && numFiles === 0) {
return res.status(400).json({ 'message': 'Must provide a message or file' });
}
if (req.body.message && req.body.message.length > 2000) {
return res.status(400).json({ 'message': 'Message must be 2000 characters or less' });
}
if (req.body.name && req.body.name.length > 50) {
return res.status(400).json({ 'message': 'Name must be 50 characters or less' });
}
if (req.body.subject && req.body.subject.length > 50) {
return res.status(400).json({ 'message': 'Subject must be 50 characters or less' });
}
if (req.body.password && req.body.password.length > 50) {
return res.status(400).json({ 'message': 'Password must be 50 characters or less' });
}
// check if this is responding to an existing thread
if (req.body.thread) {
let thread;
@ -29,65 +61,60 @@ router.post('/board/:board', Boards.exists, async (req, res, next) => {
}
let files = [];
// check for file
if (req.files != null) {
// get names and amounc
const fileKeys = Object.keys(req.files);
const numFiles = fileKeys.length
// if we got a file
if (numFiles > 0) {
// check all mime types befoer we try saving anything
for (let i = 0; i < numFiles; i++) {
if (!fileCheckMimeType(req.files[fileKeys[i]].mimetype)) {
return res.status(400).json({ 'message': 'Invalid file type' });
}
// if we got a file
if (numFiles > 0) {
// check all mime types befoer we try saving anything
for (let i = 0; i < numFiles; i++) {
if (!fileCheckMimeType(req.files[fileKeys[i]].mimetype)) {
return res.status(400).json({ 'message': 'Invalid file type' });
}
// then upload, thumb, get metadata, etc.
for (let i = 0; i < numFiles; i++) {
const file = req.files[fileKeys[i]];
const filename = uuidv4() + path.extname(file.name);
// try to save, thumbnail and get metadata
try {
await fileUpload(req, res, filename);
const fileData = await fileIdentify(filename);
await fileThumbnail(filename);
const processedFile = {
filename: filename,
originalFilename: file.name,
mimetype: file.mimetype,
filesize: file.size, // size in bytes
size: fileData.Filesize, // 123 Ki size formatted string
dimensions: fileData.size, // object with width and height pixels
geometry: fileData.Geometry, // 123 x 123 string
}
//handle gifs with multiple geometry and size
if (Array.isArray(processedFile.size)) {
processedFile.size = processedFile.size[0];
}
if (Array.isArray(processedFile.dimensions)) {
processedFile.geometry = processedFile.dimensions[0];
}
if (Array.isArray(processedFile.geometry)) {
processedFile.geometry = processedFile.geometry[0];
}
files.push(processedFile);
} catch (err) {
console.error(err);
//TODO: DELETE FAILED FILES
return res.status(500).json({ 'message': 'Error uploading file' });
}
// then upload, thumb, get metadata, etc.
for (let i = 0; i < numFiles; i++) {
const file = req.files[fileKeys[i]];
const filename = uuidv4() + path.extname(file.name);
// try to save, thumbnail and get metadata
try {
await fileUpload(req, res, filename);
const fileData = await fileIdentify(filename);
await fileThumbnail(filename);
const processedFile = {
filename: filename,
originalFilename: file.name,
mimetype: file.mimetype,
size: file.size, // size in bytes
geometry: fileData.size, // object with width and height pixels
sizeString: fileData.Filesize, // 123 Ki string
geometryString: fileData.Geometry, // 123 x 123 string
}
//handle gifs with multiple geometry and size
if (Array.isArray(processedFile.geometry)) {
processedFile.geometry = processedFile.geometry[0];
}
if (Array.isArray(processedFile.sizeString)) {
processedFile.sizeString = processedFile.sizeString[0];
}
if (Array.isArray(processedFile.geometryString)) {
processedFile.geometryString = processedFile.geometryString[0];
}
files.push(processedFile);
} catch (err) {
console.error(err);
//TODO: DELETE FAILED FILES
return res.status(500).json({ 'message': 'Error uploading file' });
}
}
}
const data = {
'author': req.body.author || 'Anonymous',
'name': req.body.name || 'Anonymous',
'subject': req.body.subject || '',
'date': new Date(),
'content': req.body.content,
'message': req.body.message || '',
'thread': req.body.thread || null,
'password': req.body.password || '',
'files': files
};
@ -99,8 +126,47 @@ router.post('/board/:board', Boards.exists, async (req, res, next) => {
});
// delete a post
router.delete('/board/:board/post/:id(\\d+)', Boards.exists, async (req, res, next) => {
// delete a post. using POST isntead of DELETE because of html forms supprot
router.post('/board/:board/delete', Boards.exists, async (req, res, next) => {
if (!req.body.password) {
return res.status(400).json({ 'message': 'Must provide a password' })
}
if (req.body.password.length > 50) {
return res.status(400).json({ 'message': 'Password must be 50 characters or less' })
}
if (!req.body.checked || req.body.checked.length === 0 || req.body.checked.length > 10) { //10 for now just for _some_ limit
return res.status(400).json({ 'message': 'Must check 1-10 boxes for posts to delete' })
}
let posts;
try {
posts = await Posts.getPosts(req.params.board, req.body.checked);
} catch (err) {
return res.status(500).json({ 'message': 'Error fetching from DB' });
}
let deleted = 0;
await Promise.all(posts.map(async post =>{
if (post.password != req.body.password) {
return; // res.status(403).json({ 'message': 'Incorrect password' });
}
try {
await Posts.deleteOne(req.params.board, {
'_id': post._id
});
} catch (err) {
return; // res.status(500).json({ 'message': 'Error deleting from DB' });
}
deleted++; //successfully deleted one
}));
return res.json({ 'message': `deleted: ${deleted} posts` })
});
@ -108,6 +174,7 @@ router.delete('/board/:board/post/:id(\\d+)', Boards.exists, async (req, res, ne
router.get('/board/:board/recent/:page(\\d+)?', Boards.exists, async (req, res, next) => {
//get the recently bumped thread & preview po let threads;
let threads;
try {
threads = await Posts.getRecent(req.params.board, req.params.page || 1);
} catch (err) {
@ -118,7 +185,7 @@ router.get('/board/:board/recent/:page(\\d+)?', Boards.exists, async (req, res,
return res.status(404).json({ 'message': 'Not found' });
}
return res.json(threads)
return res.json(threads);
});
@ -176,51 +243,5 @@ router.get('/boards', Boards.exists, async (req, res, next) => {
});
/*
(async () => {
await Boards.deleteIncrement('b');
await Boards.deleteAll();
await Boards.insertOne({
_id: 'b',
name: 'random',
description: 'post anything here',
})
await Posts.deleteAll('b');
})();
*/
/*
(async () => {
await Boards.deleteIncrement('b');
await Boards.deleteAll();
await Boards.insertOne({
_id: 'b',
name: 'random',
description: 'post anything here',
})
await Posts.deleteAll('b');
for (let i = 0; i < 3; i++) {
const thread = await Posts.insertOne('b', {
'author': 'Anonymous',
'subject': 'subject',
'date': new Date(),
'content': Math.random().toString(36).replace(/[^a-z]+/g, ''),
'thread': null
})
for (let j = 0; j < 5; j++) {
await new Promise(resolve => {setTimeout(resolve, 500)})
const post = await Posts.insertOne('b', {
'author': 'Anonymous',
'subject': 'subject',
'date': new Date(),
'content': Math.random().toString(36).replace(/[^a-z]+/g, ''),
'thread': thread.insertedId + ''
})
}
}
})();
*/
module.exports = router;

@ -37,7 +37,7 @@ module.exports = {
if (!board) {
return res.status(404).render('404')
}
res.locals.board = board;
res.locals.board = board; // can acces this in views or next route handlers
next();
},

@ -74,6 +74,17 @@ module.exports = {
},
//takes array "ids" of post ids
getPosts: async(board, ids) => {
return db.collection(board).find({
'_id': {
'$in': ids
}
}).toArray();
},
insertOne: async (board, data) => {
// bump thread if name not sage
@ -89,9 +100,9 @@ module.exports = {
data._id = await Boards.getNextId(board);
//this is an OP, so set the bump date so its pushed to the top
//this is a thread, so set the bump date so its pushed to the top
if (data.thread == null) {
data.bumped = Date.now()
data.bumped = Date.now()
}
return db.collection(board).insertOne(data);

351
package-lock.json generated

@ -6,12 +6,13 @@
"dependencies": {
"@tohru/gm": {
"version": "git+https://github.com/iCrawl/gm.git#70ade5ebee96db0e38d621eb8f9744e5eee159c7",
"from": "git+https://github.com/iCrawl/gm.git",
"requires": {
"array-parallel": "0.1.3",
"array-series": "0.1.5",
"cross-spawn": "4.0.2",
"debug": "3.2.6",
"tmp": "0.0.33"
"array-parallel": "^0.1.3",
"array-series": "^0.1.5",
"cross-spawn": "^4.0.0",
"debug": "^3.1.0",
"tmp": "^0.0.33"
},
"dependencies": {
"debug": {
@ -19,7 +20,7 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
"integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
"requires": {
"ms": "2.1.1"
"ms": "^2.1.1"
}
},
"ms": {
@ -39,7 +40,7 @@
"resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.3.tgz",
"integrity": "sha512-lyJ8sW1PbY3uwuvpOBZ9zMYKshMnQpXmeDHh8dj9j2nJm/xrW0FgB5gLSYOArj5X0IfaXnmhFoJnhS4KbqIMug==",
"requires": {
"@types/babel-types": "7.0.4"
"@types/babel-types": "*"
}
},
"accepts": {
@ -47,7 +48,7 @@
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz",
"integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=",
"requires": {
"mime-types": "2.1.19",
"mime-types": "~2.1.18",
"negotiator": "0.6.1"
}
},
@ -61,7 +62,7 @@
"resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz",
"integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=",
"requires": {
"acorn": "4.0.13"
"acorn": "^4.0.4"
},
"dependencies": {
"acorn": {
@ -76,9 +77,9 @@
"resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
"integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
"requires": {
"kind-of": "3.2.2",
"longest": "1.0.1",
"repeat-string": "1.6.1"
"kind-of": "^3.0.2",
"longest": "^1.0.1",
"repeat-string": "^1.5.2"
}
},
"array-flatten": {
@ -106,8 +107,8 @@
"resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
"integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
"requires": {
"core-js": "2.5.7",
"regenerator-runtime": "0.11.1"
"core-js": "^2.4.0",
"regenerator-runtime": "^0.11.0"
}
},
"babel-types": {
@ -115,10 +116,10 @@
"resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
"integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
"requires": {
"babel-runtime": "6.26.0",
"esutils": "2.0.2",
"lodash": "4.17.11",
"to-fast-properties": "1.0.3"
"babel-runtime": "^6.26.0",
"esutils": "^2.0.2",
"lodash": "^4.17.4",
"to-fast-properties": "^1.0.3"
}
},
"babylon": {
@ -132,15 +133,15 @@
"integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=",
"requires": {
"bytes": "3.0.0",
"content-type": "1.0.4",
"content-type": "~1.0.4",
"debug": "2.6.9",
"depd": "1.1.2",
"http-errors": "1.6.3",
"depd": "~1.1.2",
"http-errors": "~1.6.3",
"iconv-lite": "0.4.23",
"on-finished": "2.3.0",
"on-finished": "~2.3.0",
"qs": "6.5.2",
"raw-body": "2.3.3",
"type-is": "1.6.16"
"type-is": "~1.6.16"
}
},
"bson": {
@ -159,7 +160,7 @@
"integrity": "sha1-bCpiLvz0fFe7vh4qnDetNseSVFM=",
"requires": {
"dicer": "0.2.5",
"readable-stream": "1.1.14"
"readable-stream": "1.1.x"
},
"dependencies": {
"isarray": {
@ -172,10 +173,10 @@
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "0.10.31"
"string_decoder": "~0.10.x"
}
},
"string_decoder": {
@ -205,8 +206,8 @@
"resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
"integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
"requires": {
"align-text": "0.1.4",
"lazy-cache": "1.0.4"
"align-text": "^0.1.3",
"lazy-cache": "^1.0.3"
}
},
"character-parser": {
@ -214,7 +215,7 @@
"resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz",
"integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=",
"requires": {
"is-regex": "1.0.4"
"is-regex": "^1.0.3"
}
},
"clean-css": {
@ -222,7 +223,7 @@
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz",
"integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==",
"requires": {
"source-map": "0.6.1"
"source-map": "~0.6.0"
}
},
"cliui": {
@ -230,8 +231,8 @@
"resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
"integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
"requires": {
"center-align": "0.1.3",
"right-align": "0.1.3",
"center-align": "^0.1.1",
"right-align": "^0.1.1",
"wordwrap": "0.0.2"
}
},
@ -240,7 +241,7 @@
"resolved": "https://registry.npmjs.org/connect-mongo/-/connect-mongo-2.0.3.tgz",
"integrity": "sha512-Vs+QZ/6X6gbCrP1Ls7Oh/wlyY6pgpbPSrUKF5yRT+zd+4GZPNbjNquxquZ+Clv2+03HBXE7T4lVM0PUcaBhihg==",
"requires": {
"mongodb": "2.2.36"
"mongodb": "^2.0.36"
},
"dependencies": {
"mongodb": {
@ -263,13 +264,13 @@
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz",
"integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=",
"requires": {
"buffer-shims": "1.0.0",
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "1.0.0",
"process-nextick-args": "1.0.7",
"string_decoder": "1.0.3",
"util-deprecate": "1.0.2"
"buffer-shims": "~1.0.0",
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "~1.0.0",
"process-nextick-args": "~1.0.6",
"string_decoder": "~1.0.0",
"util-deprecate": "~1.0.1"
}
},
"string_decoder": {
@ -277,7 +278,7 @@
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"requires": {
"safe-buffer": "5.1.2"
"safe-buffer": "~5.1.0"
}
}
}
@ -287,10 +288,10 @@
"resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.2.tgz",
"integrity": "sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw==",
"requires": {
"@types/babel-types": "7.0.4",
"@types/babylon": "6.16.3",
"babel-types": "6.26.0",
"babylon": "6.18.0"
"@types/babel-types": "^7.0.0",
"@types/babylon": "^6.16.2",
"babel-types": "^6.26.0",
"babylon": "^6.18.0"
}
},
"content-disposition": {
@ -347,8 +348,8 @@
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz",
"integrity": "sha1-e5JHYhwjrf3ThWAEqCPL45dCTUE=",
"requires": {
"lru-cache": "4.1.5",
"which": "1.3.1"
"lru-cache": "^4.0.1",
"which": "^1.2.9"
}
},
"csrf": {
@ -368,8 +369,8 @@
"requires": {
"cookie": "0.3.1",
"cookie-signature": "1.0.6",
"csrf": "3.0.6",
"http-errors": "1.5.1"
"csrf": "~3.0.3",
"http-errors": "~1.5.0"
},
"dependencies": {
"http-errors": {
@ -379,7 +380,7 @@
"requires": {
"inherits": "2.0.3",
"setprototypeof": "1.0.2",
"statuses": "1.5.0"
"statuses": ">= 1.3.1 < 2"
}
},
"setprototypeof": {
@ -422,7 +423,7 @@
"resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz",
"integrity": "sha1-WZbAhrszIYyBLAkL3cCc0S+stw8=",
"requires": {
"readable-stream": "1.1.14",
"readable-stream": "1.1.x",
"streamsearch": "0.1.2"
},
"dependencies": {
@ -436,10 +437,10 @@
"resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"requires": {
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "0.10.31"
"string_decoder": "~0.10.x"
}
},
"string_decoder": {
@ -504,36 +505,36 @@
"resolved": "https://registry.npmjs.org/express/-/express-4.16.3.tgz",
"integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=",
"requires": {
"accepts": "1.3.5",
"accepts": "~1.3.5",
"array-flatten": "1.1.1",
"body-parser": "1.18.2",
"content-disposition": "0.5.2",
"content-type": "1.0.4",
"content-type": "~1.0.4",
"cookie": "0.3.1",
"cookie-signature": "1.0.6",
"debug": "2.6.9",
"depd": "1.1.2",
"encodeurl": "1.0.2",
"escape-html": "1.0.3",
"etag": "1.8.1",
"depd": "~1.1.2",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"finalhandler": "1.1.1",
"fresh": "0.5.2",
"merge-descriptors": "1.0.1",
"methods": "1.1.2",
"on-finished": "2.3.0",
"parseurl": "1.3.2",
"methods": "~1.1.2",
"on-finished": "~2.3.0",
"parseurl": "~1.3.2",
"path-to-regexp": "0.1.7",
"proxy-addr": "2.0.4",
"proxy-addr": "~2.0.3",
"qs": "6.5.1",
"range-parser": "1.2.0",
"range-parser": "~1.2.0",
"safe-buffer": "5.1.1",
"send": "0.16.2",
"serve-static": "1.13.2",
"setprototypeof": "1.1.0",
"statuses": "1.4.0",
"type-is": "1.6.16",
"statuses": "~1.4.0",
"type-is": "~1.6.16",
"utils-merge": "1.0.1",
"vary": "1.1.2"
"vary": "~1.1.2"
},
"dependencies": {
"body-parser": {
@ -542,15 +543,15 @@
"integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=",
"requires": {
"bytes": "3.0.0",
"content-type": "1.0.4",
"content-type": "~1.0.4",
"debug": "2.6.9",
"depd": "1.1.2",
"http-errors": "1.6.3",
"depd": "~1.1.1",
"http-errors": "~1.6.2",
"iconv-lite": "0.4.19",
"on-finished": "2.3.0",
"on-finished": "~2.3.0",
"qs": "6.5.1",
"raw-body": "2.3.2",
"type-is": "1.6.16"
"type-is": "~1.6.15"
}
},
"iconv-lite": {
@ -587,7 +588,7 @@
"depd": "1.1.1",
"inherits": "2.0.3",
"setprototypeof": "1.0.3",
"statuses": "1.4.0"
"statuses": ">= 1.3.1 < 2"
}
},
"setprototypeof": {
@ -614,7 +615,7 @@
"resolved": "https://registry.npmjs.org/express-fileupload/-/express-fileupload-1.1.3-alpha.2.tgz",
"integrity": "sha512-askIbniNmGzLBsmzDzfy9aR3vOFCUgNBOKesplC8XAYT85rOOTlgK0gdJMwgDKQ8tw4sdfgYpAnAbuPbYoyQKg==",
"requires": {
"busboy": "0.2.14"
"busboy": "^0.2.14"
}
},
"express-session": {
@ -626,10 +627,10 @@
"cookie-signature": "1.0.6",
"crc": "3.4.4",
"debug": "2.6.9",
"depd": "1.1.2",
"on-headers": "1.0.1",
"parseurl": "1.3.2",
"uid-safe": "2.1.5",
"depd": "~1.1.1",
"on-headers": "~1.0.1",
"parseurl": "~1.3.2",
"uid-safe": "~2.1.5",
"utils-merge": "1.0.1"
},
"dependencies": {
@ -638,7 +639,7 @@
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
"integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==",
"requires": {
"random-bytes": "1.0.0"
"random-bytes": "~1.0.0"
}
}
}
@ -649,12 +650,12 @@
"integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==",
"requires": {
"debug": "2.6.9",
"encodeurl": "1.0.2",
"escape-html": "1.0.3",
"on-finished": "2.3.0",
"parseurl": "1.3.2",
"statuses": "1.4.0",
"unpipe": "1.0.0"
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"on-finished": "~2.3.0",
"parseurl": "~1.3.2",
"statuses": "~1.4.0",
"unpipe": "~1.0.0"
},
"dependencies": {
"statuses": {
@ -694,7 +695,7 @@
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
"requires": {
"function-bind": "1.1.1"
"function-bind": "^1.1.1"
}
},
"helmet": {
@ -753,10 +754,10 @@
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
"integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
"requires": {
"depd": "1.1.2",
"depd": "~1.1.2",
"inherits": "2.0.3",
"setprototypeof": "1.1.0",
"statuses": "1.5.0"
"statuses": ">= 1.4.0 < 2"
}
},
"iconv-lite": {
@ -764,7 +765,7 @@
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz",
"integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==",
"requires": {
"safer-buffer": "2.1.2"
"safer-buffer": ">= 2.1.2 < 3"
}
},
"ienoopen": {
@ -792,8 +793,8 @@
"resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz",
"integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=",
"requires": {
"acorn": "4.0.13",
"object-assign": "4.1.1"
"acorn": "~4.0.2",
"object-assign": "^4.0.1"
},
"dependencies": {
"acorn": {
@ -813,7 +814,7 @@
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
"integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
"requires": {
"has": "1.0.3"
"has": "^1.0.1"
}
},
"isarray": {
@ -836,8 +837,8 @@
"resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz",
"integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=",
"requires": {
"is-promise": "2.1.0",
"promise": "7.3.1"
"is-promise": "^2.0.0",
"promise": "^7.0.1"
}
},
"kind-of": {
@ -845,7 +846,7 @@
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
"requires": {
"is-buffer": "1.1.6"
"is-buffer": "^1.1.5"
}
},
"lazy-cache": {
@ -868,8 +869,8 @@
"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"
"pseudomap": "^1.0.2",
"yallist": "^2.1.2"
}
},
"media-typer": {
@ -908,7 +909,7 @@
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.19.tgz",
"integrity": "sha512-P1tKYHVSZ6uFo26mtnve4HQFE3koh1UWVkp8YUC+ESBHe945xWSoXuHHiGarDqcEZ+whpCDnlNw5LON0kLo+sw==",
"requires": {
"mime-db": "1.35.0"
"mime-db": "~1.35.0"
}
},
"mongodb": {
@ -917,7 +918,7 @@
"integrity": "sha512-xQ6apOOV+w7VFApdaJpWhYhzartpjIDFQjG0AwgJkLh7dBs7PTsq4A3Bia2QWpDohmAzTBIdQVLMqqLy0mwt3Q==",
"requires": {
"mongodb-core": "3.2.2",
"safe-buffer": "5.1.2"
"safe-buffer": "^5.1.2"
},
"dependencies": {
"bson": {
@ -930,10 +931,10 @@
"resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-3.2.2.tgz",
"integrity": "sha512-YRgC39MuzKL0uoGoRdTmV1e9m47NbMnYmuEx4IOkgWAGXPSEzRY7cwb3N0XMmrDMnD9vp7MysNyAriIIeGgIQg==",
"requires": {
"bson": "1.1.1",
"require_optional": "1.0.1",
"safe-buffer": "5.1.2",
"saslprep": "1.0.2"
"bson": "^1.1.1",
"require_optional": "^1.0.1",
"safe-buffer": "^5.1.2",
"saslprep": "^1.0.0"
}
}
}
@ -943,8 +944,8 @@
"resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.20.tgz",
"integrity": "sha512-IN57CX5/Q1bhDq6ShAR6gIv4koFsZP7L8WOK1S0lR0pVDQaScffSMV5jxubLsmZ7J+UdqmykKw4r9hG3XQEGgQ==",
"requires": {
"bson": "1.0.9",
"require_optional": "1.0.1"
"bson": "~1.0.4",
"require_optional": "~1.0.0"
}
},
"ms": {
@ -995,8 +996,8 @@
"resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz",
"integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=",
"requires": {
"process": "0.11.10",
"util": "0.10.4"
"process": "^0.11.1",
"util": "^0.10.3"
}
},
"path-parse": {
@ -1024,7 +1025,7 @@
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
"integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
"requires": {
"asap": "2.0.6"
"asap": "~2.0.3"
}
},
"proxy-addr": {
@ -1032,7 +1033,7 @@
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz",
"integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==",
"requires": {
"forwarded": "0.1.2",
"forwarded": "~0.1.2",
"ipaddr.js": "1.8.0"
}
},
@ -1046,14 +1047,14 @@
"resolved": "https://registry.npmjs.org/pug/-/pug-2.0.3.tgz",
"integrity": "sha1-ccuoJTfJWl6rftBGluQiH1Oqh44=",
"requires": {
"pug-code-gen": "2.0.1",
"pug-filters": "3.1.0",
"pug-lexer": "4.0.0",
"pug-linker": "3.0.5",
"pug-load": "2.0.11",
"pug-parser": "5.0.0",
"pug-runtime": "2.0.4",
"pug-strip-comments": "1.0.3"
"pug-code-gen": "^2.0.1",
"pug-filters": "^3.1.0",
"pug-lexer": "^4.0.0",
"pug-linker": "^3.0.5",
"pug-load": "^2.0.11",
"pug-parser": "^5.0.0",
"pug-runtime": "^2.0.4",
"pug-strip-comments": "^1.0.3"
}
},
"pug-attrs": {
@ -1061,9 +1062,9 @@
"resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.3.tgz",
"integrity": "sha1-owlflw5kFR972tlX7vVftdeQXRU=",
"requires": {
"constantinople": "3.1.2",
"js-stringify": "1.0.2",
"pug-runtime": "2.0.4"
"constantinople": "^3.0.1",
"js-stringify": "^1.0.1",
"pug-runtime": "^2.0.4"
}
},
"pug-code-gen": {
@ -1071,14 +1072,14 @@
"resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.1.tgz",
"integrity": "sha1-CVHsgyJddNjPxHan+Zolm199BQw=",
"requires": {
"constantinople": "3.1.2",
"doctypes": "1.1.0",
"js-stringify": "1.0.2",
"pug-attrs": "2.0.3",
"pug-error": "1.3.2",
"pug-runtime": "2.0.4",
"void-elements": "2.0.1",
"with": "5.1.1"
"constantinople": "^3.0.1",
"doctypes": "^1.1.0",
"js-stringify": "^1.0.1",
"pug-attrs": "^2.0.3",
"pug-error": "^1.3.2",
"pug-runtime": "^2.0.4",
"void-elements": "^2.0.1",
"with": "^5.0.0"
}
},
"pug-error": {
@ -1091,13 +1092,13 @@
"resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-3.1.0.tgz",
"integrity": "sha1-JxZVVbwEwjbkqisDZiRt+gIbYm4=",
"requires": {
"clean-css": "4.2.1",
"constantinople": "3.1.2",
"clean-css": "^4.1.11",
"constantinople": "^3.0.1",
"jstransformer": "1.0.0",
"pug-error": "1.3.2",
"pug-walk": "1.1.7",
"resolve": "1.8.1",
"uglify-js": "2.8.29"
"pug-error": "^1.3.2",
"pug-walk": "^1.1.7",
"resolve": "^1.1.6",
"uglify-js": "^2.6.1"
}
},
"pug-lexer": {
@ -1105,9 +1106,9 @@
"resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-4.0.0.tgz",
"integrity": "sha1-IQwYRX7y4XYCQnQMXmR715TOwng=",
"requires": {
"character-parser": "2.2.0",
"is-expression": "3.0.0",
"pug-error": "1.3.2"
"character-parser": "^2.1.1",
"is-expression": "^3.0.0",
"pug-error": "^1.3.2"
}
},
"pug-linker": {
@ -1115,8 +1116,8 @@
"resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.5.tgz",
"integrity": "sha1-npp65ABWgtAn3uuWsAD4juuDoC8=",
"requires": {
"pug-error": "1.3.2",
"pug-walk": "1.1.7"
"pug-error": "^1.3.2",
"pug-walk": "^1.1.7"
}
},
"pug-load": {
@ -1124,8 +1125,8 @@
"resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.11.tgz",
"integrity": "sha1-5kjlftET/iwfRdV4WOorrWvAFSc=",
"requires": {
"object-assign": "4.1.1",
"pug-walk": "1.1.7"
"object-assign": "^4.1.0",
"pug-walk": "^1.1.7"
}
},
"pug-parser": {
@ -1133,7 +1134,7 @@
"resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-5.0.0.tgz",
"integrity": "sha1-45Stmz/KkxI5QK/4hcBuRKt+aOQ=",
"requires": {
"pug-error": "1.3.2",
"pug-error": "^1.3.2",
"token-stream": "0.0.1"
}
},
@ -1147,7 +1148,7 @@
"resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.3.tgz",
"integrity": "sha1-8VWVkiBu3G+FMQ2s9K+0igJa9Z8=",
"requires": {
"pug-error": "1.3.2"
"pug-error": "^1.3.2"
}
},
"pug-walk": {
@ -1201,8 +1202,8 @@
"resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz",
"integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==",
"requires": {
"resolve-from": "2.0.0",
"semver": "5.5.1"
"resolve-from": "^2.0.0",
"semver": "^5.1.0"
}
},
"resolve": {
@ -1210,7 +1211,7 @@
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",
"integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==",
"requires": {
"path-parse": "1.0.6"
"path-parse": "^1.0.5"
}
},
"resolve-from": {
@ -1223,7 +1224,7 @@
"resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
"integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
"requires": {
"align-text": "0.1.4"
"align-text": "^0.1.1"
}
},
"rndm": {
@ -1247,7 +1248,7 @@
"integrity": "sha512-4cDsYuAjXssUSjxHKRe4DTZC0agDwsCqcMqtJAQPzC74nJ7LfAJflAtC1Zed5hMzEQKj82d3tuzqdGNRsLJ4Gw==",
"optional": true,
"requires": {
"sparse-bitfield": "3.0.3"
"sparse-bitfield": "^3.0.3"
}
},
"semver": {
@ -1261,18 +1262,18 @@
"integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==",
"requires": {
"debug": "2.6.9",
"depd": "1.1.2",
"destroy": "1.0.4",
"encodeurl": "1.0.2",
"escape-html": "1.0.3",
"etag": "1.8.1",
"depd": "~1.1.2",
"destroy": "~1.0.4",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
"fresh": "0.5.2",
"http-errors": "1.6.3",
"http-errors": "~1.6.2",
"mime": "1.4.1",
"ms": "2.0.0",
"on-finished": "2.3.0",
"range-parser": "1.2.0",
"statuses": "1.4.0"
"on-finished": "~2.3.0",
"range-parser": "~1.2.0",
"statuses": "~1.4.0"
},
"dependencies": {
"statuses": {
@ -1287,9 +1288,9 @@
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz",
"integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==",
"requires": {
"encodeurl": "1.0.2",
"escape-html": "1.0.3",
"parseurl": "1.3.2",
"encodeurl": "~1.0.2",
"escape-html": "~1.0.3",
"parseurl": "~1.3.2",
"send": "0.16.2"
}
},
@ -1309,7 +1310,7 @@
"integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=",
"optional": true,
"requires": {
"memory-pager": "1.5.0"
"memory-pager": "^1.0.2"
}
},
"statuses": {
@ -1327,7 +1328,7 @@
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
"requires": {
"os-tmpdir": "1.0.2"
"os-tmpdir": "~1.0.2"
}
},
"to-fast-properties": {
@ -1351,7 +1352,7 @@
"integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==",
"requires": {
"media-typer": "0.3.0",
"mime-types": "2.1.19"
"mime-types": "~2.1.18"
}
},
"uglify-js": {
@ -1359,9 +1360,9 @@
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
"integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
"requires": {
"source-map": "0.5.7",
"uglify-to-browserify": "1.0.2",
"yargs": "3.10.0"
"source-map": "~0.5.1",
"uglify-to-browserify": "~1.0.0",
"yargs": "~3.10.0"
},
"dependencies": {
"source-map": {
@ -1382,7 +1383,7 @@
"resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.4.tgz",
"integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=",
"requires": {
"random-bytes": "1.0.0"
"random-bytes": "~1.0.0"
}
},
"unpipe": {
@ -1428,7 +1429,7 @@
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"requires": {
"isexe": "2.0.0"
"isexe": "^2.0.0"
}
},
"window-size": {
@ -1441,8 +1442,8 @@
"resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz",
"integrity": "sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=",
"requires": {
"acorn": "3.3.0",
"acorn-globals": "3.1.0"
"acorn": "^3.1.0",
"acorn-globals": "^3.0.0"
}
},
"wordwrap": {
@ -1465,9 +1466,9 @@
"resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
"integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
"requires": {
"camelcase": "1.2.1",
"cliui": "2.1.0",
"decamelize": "1.2.0",
"camelcase": "^1.0.2",
"cliui": "^2.1.0",
"decamelize": "^1.0.0",
"window-size": "0.1.0"
}
}

@ -21,6 +21,11 @@ input, textarea {
max-width:100%;
}
.post-check {
vertical-align: sub;
display: inline-block;
}
input textares {
padding: 8px;
}

@ -7,9 +7,11 @@ form.form-post(action='/api/board/'+board._id, enctype='multipart/form-data', me
input#title(type='text', name='subject', placeholder='subject')
input#name(type='text', name='author', placeholder='name')
input#name(type='text', name='name', placeholder='name')
textarea#content(name='content', rows='8', cols='50', placeholder='message')
input#name(type='password', name='password', placeholder='password (for deletion)')
textarea#messagey(name='message', rows='8', cols='50', placeholder='message')
input#file(type='file', name='file')

@ -2,8 +2,9 @@ mixin post(board, post)
.post-wrapper
div(class='post-container '+(post.thread ? '' : 'op'))
.post-info
input.post-check(type='checkbox', name='checked[]' value=post._id)
span.post-subject #{post.subject}
span.post-author #{post.author}
span.post-name #{post.name}
span #{post.date.toLocaleString()}
span No.
if post.thread == null
@ -15,11 +16,11 @@ mixin post(board, post)
each file in post.files
.post-file-info
span: a(href='/img/thumb-'+file.filename download=file.originalFilename) #{file.originalFilename}
span ( Size: #{file.size}
span Dimensions: #{file.geometry} )
span ( Size: #{file.sizeString}
span Dimensions: #{file.geometryString} )
.post-file
a(href='/img/'+file.filename)
object(data='/img/thumb-'+file.filename type=file.mimetype)
.post-content
p(style='white-space: pre-wrap;') #{post.content}
.post-message
p(style='white-space: pre-wrap;') #{post.message}

@ -9,8 +9,12 @@ block content
hr(size=1)
include ../includes/postform.pug
hr(size=1)
for thread in threads
+post(board, thread)
for post in thread.replies
+post(board, post)
hr(size=1)
form(action='/api/board/'+board._id+'/delete' method='POST' enctype='application/x-www-form-urlencoded')
input(type='hidden' name='_csrf' value=csrf)
for thread in threads
+post(board, thread)
for post in thread.replies
+post(board, post)
hr(size=1)
input#password(type='password', name='password', placeholder='password (for deletion)')
input(type='submit', value='delete')

@ -9,6 +9,14 @@ block content
hr(size=1)
include ../includes/postform.pug
hr(size=1)
+post(board, thread)
for post in thread.replies
+post(board, post)
form(action='/api/board/'+board._id+'/delete' method='POST' enctype='application/x-www-form-urlencoded')
input(type='hidden' name='_csrf' value=csrf)
+post(board, thread)
for post in thread.replies
+post(board, post)
input#password(type='password', name='password', placeholder='password (for deletion)')
input(type='submit', value='delete')

Loading…
Cancel
Save