diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..af0f0c3 --- /dev/null +++ b/.babelrc @@ -0,0 +1,3 @@ +{ + "presets": ["es2015"] +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 31081e3..e930b7c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ node_modules/ .idea/ *.log.* -uploads/ \ No newline at end of file +uploads/ +package-lock.json \ No newline at end of file diff --git a/assets/css/common.css b/assets/css/common.css deleted file mode 100755 index 9ec4f62..0000000 --- a/assets/css/common.css +++ /dev/null @@ -1,99 +0,0 @@ -html, body { - height: 100%; -} - -body { - margin: 0; -} - -* { - font-family: focalpoint; -} - -@font-face { - font-family: focalpoint; - src: url("/assets/fonts/Proxima-Nova-Semibold.woff2"); -} - -.flex-container { - padding: 0; - margin: 0; - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; - display: flex; - flex-wrap: nowrap; - flex-direction: column !important; - justify-content: flex-start; - align-items: center; -} - -.row { - margin: 0; - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; - display: flex; - flex-direction: row; - align-content: space-around; - justify-content: flex-start; - align-items: center; - width: auto; - padding: 8px; -} - -.row > .row-item { - margin: 5px; -} - -.flex-item { - text-align: center; -} - -.right { - float: right; -} - -.inv { - display: none; -} - -.link { - font-family: focalpoint; - color: black; - cursor: pointer; - cursor: hand; -} - -.link:hover > :first-child { - color: #1799B5 !important; -} - -.dropdown { - position: relative; - display: inline-block; -} - -.dropdown-content { - display: none; - position: absolute; - background-color: #f9f9f9; - min-width: 160px; - box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); - z-index: 2; - margin-top: 10px; -} - -.dropdown-content > * { - padding: 12px 16px; -} - -.dropdown:hover .dropdown-content { - display: block; -} - -.color-red { - color: red; -} diff --git a/assets/img/classroom.jpeg b/assets/img/classroom.jpeg deleted file mode 100755 index 7e47099..0000000 Binary files a/assets/img/classroom.jpeg and /dev/null differ diff --git a/assets/img/classroom.svg b/assets/img/classroom.svg deleted file mode 100755 index 5ed5ed7..0000000 --- a/assets/img/classroom.svg +++ /dev/null @@ -1,1967 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -image/svg+xmlOpenclipart58294main_The.Brain.in.Space-page-47-kids-classroom2010-04-06T07:38:20This is clipart converted and broken apart that has been released into the public domain because the document says so, and its from NASA, a USA government agency. The publication is called "The Brain in Space:" \n \nhttp://www.nasa.gov/audience/foreducators/topnav/materials/listbytype/The.Brain.in.Space.htmlhttp://openclipart.org/detail/38197/-by-rejon-38197rejonastronomybrainclip artclipartconvertedgovernmentnasasciencespaceusa diff --git a/assets/img/howls_moving_castle.png b/assets/img/howls_moving_castle.png deleted file mode 100755 index ba9519a..0000000 Binary files a/assets/img/howls_moving_castle.png and /dev/null differ diff --git a/assets/img/mountains.png b/assets/img/mountains.png deleted file mode 100755 index 7d74724..0000000 Binary files a/assets/img/mountains.png and /dev/null differ diff --git a/assets/img/parrot.png b/assets/img/parrot.png deleted file mode 100755 index ea6eea7..0000000 Binary files a/assets/img/parrot.png and /dev/null differ diff --git a/assets/js/api.js b/assets/js/api.js deleted file mode 100755 index 9f65cb8..0000000 --- a/assets/js/api.js +++ /dev/null @@ -1,54 +0,0 @@ -let _api = { }; - -axios.defaults.withCredentials = true; - -(function () { - const root = 'http://localhost:3000/api/'; - const urls = { - loginUrl: 'signin', - logoutUrl: 'logout', - currentUserUrl: 'current-user', - videosUrl: 'videos' - }; - function url(api) { - return root + urls[api]; - } - - function get(url, params, fn) { - axios.get(url, { - params: params - }) - .then(function (response) { - fn(null, JSON.parse(response.data.split('\n')[1])); - }) - .catch(function (error) { - fn(JSON.parse(error.response.data.split('\n')[1])); - }); - } - - function post(url, params, fn) { - axios.post(url, params) - .then(function (response) { - fn(null, JSON.parse(response.data.split('\n')[1])); - }) - .catch(function (error) { - fn(JSON.parse(error.response.data.split('\n')[1])); - }); - } - - _api.currentUser = function (fn) { - get(url('currentUserUrl'), { }, fn); - }; - - _api.login = function (username, password, fn) { - post(url('loginUrl'), { username: username, password: password }, fn); - }; - - _api.logout = function(fn) { - post(url('logoutUrl'), {}, fn); - }; - - _api.videos = function(topicPath, accessLevel, offset, num, fn) { - get(url('videosUrl'), { subject: topicPath.subject, course: topicPath.course, topic: topicPath.topic, accessLevel: accessLevel, offset: offset, num: num }, fn); - }; -})(); diff --git a/assets/js/constants.js b/assets/js/constants.js deleted file mode 100755 index f62dfcd..0000000 --- a/assets/js/constants.js +++ /dev/null @@ -1,10 +0,0 @@ -const _const = { - headerOne: { - loginButton: 'Login / Create Account', - profileButton: 'Current user', - loginError: 'An error occurred. Please comtact support.' - }, - videos: { - num: 8 - } -}; diff --git a/assets/js/utils.js b/assets/js/utils.js deleted file mode 100755 index 3d26776..0000000 --- a/assets/js/utils.js +++ /dev/null @@ -1,5 +0,0 @@ -const _utils = { - page: { - - } -}; \ No newline at end of file diff --git a/index.html b/index.html index b1fbe4f..378760b 100644 --- a/index.html +++ b/index.html @@ -4,7 +4,7 @@ Image Board - + @@ -13,9 +13,7 @@ - - - + diff --git a/index.js b/index.js index 700060a..f188548 100644 --- a/index.js +++ b/index.js @@ -5,6 +5,7 @@ const express = require('express'), cookieParser = require('cookie-parser'), PropertiesReader = require('properties-reader'), multer = require('multer'), + path = require('path'), passport = require('passport'); const app = express(); @@ -15,7 +16,7 @@ app.use(session({ secret: 'erferfre234324reevvfe', resave: false, saveUninitialized: true, - cookie: { secure: false, maxAge: Number(100000) } + cookie: { secure: false, maxAge: Number(100000000) } })); app.use(passport.initialize()); app.use(passport.session()); @@ -30,15 +31,15 @@ global._isProd = _env === 'production'; console.info = function(message) { console.log('[INFO] ' + message); -} +}; console.debug = function(message) { console.log('[DEBUG] ' + message); -} +}; console.critical = function(message) { console.log('[!!! CRITICAL !!!] ' + message); -} +}; const setUpDatabase = require(_base + 'services/SetupDatabaseService'); const setUpPassport = require(_base + 'services/SetUpPassport'); @@ -49,6 +50,10 @@ setUpPassport(); routescan(app, { ignoreInvalid: true }); +app.use('/dist', express.static('dist')); +app.use('/src/assets', express.static('src/assets')); +app.use('/uploads', express.static('uploads')); +app.use((req, res) => res.sendFile(path.join(_base, '/index.html'))); app.use(function (err, req, res, next) { console.debug('Error encountered: ' + err.message); diff --git a/middleware/ensureAuthenticity.js b/middleware/ensureAuthenticity.js index 8f65f05..4c71dcf 100644 --- a/middleware/ensureAuthenticity.js +++ b/middleware/ensureAuthenticity.js @@ -4,6 +4,6 @@ module.exports = function(req, res, next) { if(req.isAuthenticated()) { next(); } else { - res.redirect("/login"); + next(new Error('Not logged in.')); } -} +}; \ No newline at end of file diff --git a/models/board.js b/models/board.js index bd33475..625bbef 100644 --- a/models/board.js +++ b/models/board.js @@ -2,7 +2,7 @@ let mongoose = require("mongoose"); let boardSchema = new mongoose.Schema({ - categoryName: { type: String, required: true, unique: true }, + categoryName: { type: String, required: true }, name: { type: String, required: true, unique: true }, letter: { type: String, required: true, unique: true }, favIcon: { type: String } diff --git a/models/mod.js b/models/mod.js index 6e979b6..b2cbda7 100644 --- a/models/mod.js +++ b/models/mod.js @@ -1,22 +1,43 @@ let mongoose = require("mongoose"), -// bcrypt = require("bcrypt"), + bcrypt = require("bcrypt-nodejs"), shortid = require("shortid"); +const SALT_FACTOR = 4; + let modSchema = new mongoose.Schema({ _id: { type: String, required: true, default: shortid.generate }, - email: { type: String, required: true }, + username: { type: String, required: true }, password: { type: String, required: true } }, { collection: _db.get("db.collection.mods") }); -// TODO: implement check password method -// modSchema.methods.checkPassword = function(guess, done) { -// bcrypt.compare(guess, this.password, function(err, match) { -// done(err, match); -// }); -// }; -// TODO: remove this test implementation of the checkPassword method +function noop() {}; + +modSchema.pre('save', function (done) { + let user = this; //Reference to user model + + if (!user.isModified("password")) { + return done(); + } + + bcrypt.genSalt(SALT_FACTOR, function (err, salt) { + if (err) { + return done(err); + } + bcrypt.hash(user.password, salt, noop, function (err, hashedPassword) { + if (err) { + return done(err); + } + user.password = hashedPassword; + done(); + }); + }); +}); + modSchema.methods.checkPassword = function(guess, done) { - done(null, true); -} + bcrypt.compare(guess, this.password, function(err, isMatch) { + done(err, isMatch); + }); +}; + let Mod = mongoose.model('Mod', modSchema); module.exports = Mod; diff --git a/models/reply.js b/models/reply.js index f8c8b85..db3cee1 100644 --- a/models/reply.js +++ b/models/reply.js @@ -4,7 +4,11 @@ let shortid = require("shortid"); let replySchema = new mongoose.Schema({ _id: { type: String, required: true, default: shortid.generate }, time: { type: Date, required: true, default: Date.now }, - ip: { type: String, required: true } + ip: { type: String, required: true }, + attachment_path: { type: String, required: false }, + attachment_name: { type: String, required: false }, + threadId: { type: String, required: true }, + content: { type: String, required: false } }); let Reply = mongoose.model("Reply", replySchema); diff --git a/package.json b/package.json index 3d3df71..75acf59 100644 --- a/package.json +++ b/package.json @@ -7,8 +7,8 @@ "test": "echo \"Error: no test specified\" && exit 1", "dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot", "server": "pm2 start index.js --watch --name server --ignore-watch 'uploads'", - "vue": "cross-env NODE_ENV=development pm2 start webpack-dev-server --name vue -- --open --hot --inline --port 3002", - "start": "npm run server | npm run vue", + "vue": "cross-env NODE_ENV=development pm2 start webpack-dev-server --name vue -- --open --hot --inline --port 3002 --host 0.0.0.0", + "start": "npm run server | npm run build", "stop": "pm2 stop all", "log": "pm2 log", "restart": "npm run stop | npm run start | npm run log", @@ -26,14 +26,18 @@ "express-session": "^1.15.6", "express-validator": "^5.0.3", "googleapis": "^27.0.0", + "ipaddr.js": "^1.6.0", "mongoose": "^5.0.9", + "multer": "^1.3.0", "passport": "^0.4.0", "passport-local": "^1.0.0", "properties-reader": "0.0.16", "recaptcha": "^1.2.1", + "request-ip": "^2.0.2", "shortid": "^2.2.8", "string-format": "^0.5.0", "striptags": "^3.1.1", + "transform-runtime": "0.0.0", "validator": "^9.4.1", "vue": "^2.5.11", "vue-router": "^3.0.1" @@ -49,6 +53,7 @@ "vue-loader": "^13.0.5", "vue-template-compiler": "^2.4.4", "webpack": "^3.6.0", + "webpack-cli": "^2.0.14", "webpack-dev-server": "^2.9.1" } } diff --git a/routes/create/ban.js b/routes/create/ban.js index 81c3906..38ed583 100644 --- a/routes/create/ban.js +++ b/routes/create/ban.js @@ -30,4 +30,4 @@ module.exports = { } } -} +}; diff --git a/routes/create/mod.js b/routes/create/mod.js index 3e4d3c7..c4aabc2 100644 --- a/routes/create/mod.js +++ b/routes/create/mod.js @@ -4,9 +4,9 @@ module.exports = { '/create/mod': { methods: ['post'], fn: function(req, res, next) { - let email = req.body.email, - password = req.body.passowrd; - Mod.findOne({ email: email }, function(err, result) { + let username = req.body.username, + password = req.body.password; + Mod.findOne({ username: username }, function(err, result) { if (err) { return next(err); } @@ -14,8 +14,8 @@ module.exports = { return next(new Mod("Mod with that email already exists")); } - let mod = new Mod({ - email: email, + let mod = new Mod({ + username: username, password: password }); @@ -23,7 +23,7 @@ module.exports = { if(err) { return next(err); } - res.json({ result: { email: email } }); + res.json({ result: { username: username } }); }); }); } diff --git a/routes/create/reply.js b/routes/create/reply.js index 2ad2eb2..76a3105 100644 --- a/routes/create/reply.js +++ b/routes/create/reply.js @@ -1,37 +1,54 @@ const Reply = require(_base + 'models/reply'); +const fs = require('fs'); +const path = 'uploads/'; +const multer = require('multer'); +const upload = multer({ dest: './uploads/'}); module.exports = { - '/create/reply': { + '/create/reply' : { methods: ['post'], - fn: function(req, res, next) { - let postId = req.body.id, - content = req.body.content, - attachment = req.body.attachment, - time = req.body.time, - ip = req.body.ip; - - Reply.findOne({ id: postId }, function(err, result) { - if(err) { - return next(err); - } - - if(result) { - return next(new Error("Reply with this id already exists")); - } - - let reply = new Reply({ id: postId, - content: content, - attachment: attachment, - time: time, - ip: ip }); - reply.save(function(err) { - if(err) { - return next(err); - } - res.json({ id: postId, ip: ip}); - }); - }); - + middleware: [upload.single("attachment")], + fn: function (req, res, next) { + console.log(req.file); + let threadId = req.body.threadId, + attachment = req.file, + ip = req.connection.remoteAddress, + content = req.body.content; + + let reply = new Reply({ threadId: threadId, ip: ip, content: content }); + + if (attachment) { + let target_path = path + attachment.filename + "." + attachment.originalname.split('.').pop(); + reply.attachment_path = target_path; + reply.attachment_name = attachment.originalname; + } + + reply.save(function(err) { + console.log(req.files); + if(err) { + return next(err); + } + + if (attachment) { + //Save file to fs + fs.rename(attachment.path, target_path, function(err) { + if(err) { + return next(err); + } + + fs.unlink(attachment.path, function() { + if(err) { + return next(err); + } + + res.json({ result: { threadId: threadId, attachment_path: target_path, attachment_name: attachment.originalname, ip: ip, content: content } }); + }); + }); + } else { + res.json({ result: { threadId: threadId, ip: ip, content: content } }); + } + + }); } } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/routes/create/session.js b/routes/create/session.js index 24ded05..538f1fb 100644 --- a/routes/create/session.js +++ b/routes/create/session.js @@ -3,14 +3,25 @@ const passport = require("passport"); module.exports = { '/create/session': { methods: ['post'], - middleware: [ - passport.authenticate("login", { - successRedirect: "/", - failureRedirect: "/login", - failureFlash: false + middleware: [passport.authenticate("login", { + successRedirect: "session/success", + failureRedirect: "session/fail", + failureFlash: false //Flash not needed })], - fn: function(req, res, next) { - + fn: function (req, res, next) { + + } + }, + '/create/session/success': { + methods: ['get'], + fn: function (req, res, next) { + res.json({ result: 'Success' }); + } + }, + '/create/session/fail': { + methods: ['get'], + fn: function (req, res, next) { + next(new Error('Incorrect credentials.')); } } -} +}; diff --git a/routes/create/thread.js b/routes/create/thread.js index 3c1f41c..a49d578 100644 --- a/routes/create/thread.js +++ b/routes/create/thread.js @@ -1,6 +1,6 @@ const Thread = require(_base + 'models/thread'); const fs = require('fs'); -const path = _base + 'uploads/' +const path = 'uploads/'; const multer = require('multer'); const upload = multer({ dest: './uploads/'}); @@ -27,7 +27,7 @@ module.exports = { return next(new Error('Thread with that name already exists.')); } - let target_path = path + attachment.filename + "." + attachment.originalname.split('.').pop();; + let target_path = path + attachment.filename + "." + attachment.originalname.split('.').pop(); let thread = new Thread({ name: name, boardId: board, attachment_path: target_path, attachment_name: attachment.originalname, pinned: pinned, ip: ip, content: content, title: title }); thread.save(function(err) { console.log(req.files); diff --git a/routes/read/boards.js b/routes/read/boards.js index 9c3b75f..7fea40d 100644 --- a/routes/read/boards.js +++ b/routes/read/boards.js @@ -10,7 +10,7 @@ module.exports = { letter = req.query.letter, favicon = req.query.favicon; - let boards = Boards.find({ letter: letter }, function(err, results) { + Boards.find({}, function(err, results) { if (err) { return next(err); } @@ -19,4 +19,4 @@ module.exports = { }); } } -} +}; diff --git a/routes/read/endSession.js b/routes/read/endSession.js index cd13264..ccf8f03 100644 --- a/routes/read/endSession.js +++ b/routes/read/endSession.js @@ -1,11 +1,15 @@ const passport = require("passport"); module.exports = { - 'read/endSession': { + '/read/endSession': { methods: ['post'], + middleware: [], fn: function(req, res, next) { req.logout(); - res.redirect("/"); + req.session.destroy(function(err) { + if (err) return next(err); + res.json({ result: 'Success' }); + }); } } -} +}; \ No newline at end of file diff --git a/routes/read/replies.js b/routes/read/replies.js index 3b9df6b..430676c 100644 --- a/routes/read/replies.js +++ b/routes/read/replies.js @@ -16,4 +16,4 @@ module.exports = { } } -} +}; diff --git a/routes/read/thread.js b/routes/read/thread.js index 65769e3..bbbb625 100644 --- a/routes/read/thread.js +++ b/routes/read/thread.js @@ -4,17 +4,16 @@ module.exports = { '/read/thread': { methods: ['get'], fn: function(req, res, next) { - let letter = req.query.letter; + let _id = req.query._id; //post id, name, content, pinned, time - Threads.findOne({letter: letter}, function(err, result) { + console.log(_id); + Threads.findById(_id, function(err, result) { if(err) { return next(err); } else { - res.json({ result: { id: result.id, letter: letter, name: result.name, - content: result.content, pinned: result.pinned, - time: result.time } }); + res.json({ result: result }); } }); } } -} +}; \ No newline at end of file diff --git a/routes/read/threads.js b/routes/read/threads.js index 68e1b09..dbc7663 100644 --- a/routes/read/threads.js +++ b/routes/read/threads.js @@ -5,7 +5,7 @@ module.exports = { methods: ['get'], fn: function(req, res, next) { let letter = req.query.letter; - Threads.find({ letter: letter }, function(err, results) { + Threads.find({ boardId: letter }, function(err, results) { if(err) { return next(err); } else { @@ -14,4 +14,4 @@ module.exports = { }); } } -} +}; \ No newline at end of file diff --git a/routes/update/ban.js b/routes/update/ban.js index a73be89..2dba473 100644 --- a/routes/update/ban.js +++ b/routes/update/ban.js @@ -3,7 +3,7 @@ const Ban = require(_base + 'models/ban'); module.exports = { '/update/ban': { methods: ['put'], - middleware: [ensureAuthenticity], + middleware: [], fn: function(req, res, next) { let updateFields = {}; diff --git a/routes/update/board.js b/routes/update/board.js index d79d878..8acb335 100644 --- a/routes/update/board.js +++ b/routes/update/board.js @@ -3,7 +3,7 @@ const Board = require(_base + 'models/board.js'); module.export = { '/update/board': { methods: ['put'], - middleware: [ensureAuthenticity], + middleware: [], fn: function(req, res, next) { let updateFields = {}; diff --git a/routes/update/mod.js b/routes/update/mod.js index 8fa914f..26aae7e 100644 --- a/routes/update/mod.js +++ b/routes/update/mod.js @@ -3,7 +3,7 @@ const Mod = require(_base + 'models/mod.js'); module.export = { '/update/mod': { methods: ['put'], - middleware: [ensureAuthenticity], + middleware: [], fn: function(req, res, next) { let updateFields = {}; @@ -23,7 +23,7 @@ module.export = { } res.json({ result: result }); - } + }); } } diff --git a/services/SetUpPassport.js b/services/SetUpPassport.js index 3213652..ecce8af 100644 --- a/services/SetUpPassport.js +++ b/services/SetUpPassport.js @@ -1,37 +1,39 @@ -let LocalStrategy = require('passport-local').Strategy, - Mod = require(_base + 'models/mod'), - passport = require("passport"); +var passport = require("passport"); -module.exports = function() { - passport.serializeUser(function(mod, done) { - done(null, mod._id); - }); +var LocalStrategy = require("passport-local").Strategy; - passport.deserializeUser(function(_id, done) { - Mod.findById(_id, function(err, mod) { - done(err, mod); - }); - }); -} - -let strategy = new LocalStrategy({ usernameField: 'email' }, function(email, password, done) { - Mod.findOne({ email: email }, function(err, mod) { - if(err) { - return done(err); - } else if(!mod) { - return done(null, false, { message: "No such mod of email " + email }); - } +var User = require(_base + "models/mod"); - mod.checkPassword(password, function(err, matching) { - if(err) { - return done(err); - } else if(match) { - return done(null, mod); - } else { - return done(null, false, { message: "Incorrect password." }) - } +module.exports = function () { + passport.serializeUser(function (user, done) { + done(null, user._id); }); - }); -}); + passport.deserializeUser(function (id, done) { + User.findById(id, function (err, user) { + done(err, user); + }); + }); +}; -passport.use("login", strategy); +passport.use("login", new LocalStrategy(function (username, password, done) { + User.findOne({ username: username }, function (err, user) { + if (err) { + return done(err); + } + if (!user) { + return done(null, false, + { message: "Invalid username or password." }); + } + user.checkPassword(password, function (err, isMatch) { + if (err) { + return done(err); + } + if (isMatch) { + return done(null, user); + } else { + return done(null, false, + { message: "Invalid username or password." }); + } + }); + }); +})); diff --git a/src/App.vue b/src/App.vue index 75f4109..01d88a9 100755 --- a/src/App.vue +++ b/src/App.vue @@ -1,8 +1,5 @@ @@ -15,11 +12,6 @@ export default { diff --git a/src/Router.js b/src/Router.js index c3af0cb..b4ba6e1 100644 --- a/src/Router.js +++ b/src/Router.js @@ -1,33 +1,40 @@ import Vue from 'vue' import Router from 'vue-router' -import Index from './components/Index' -import Catalog from './components/Catalog' -import Thread from './components/Thread' -import About from './components/About' +import Index from './components/Index.vue' +import Catalog from './components/Catalog.vue' +import Thread from './components/Thread.vue' +import About from './components/About.vue' +import Login from './components/Login.vue' -Vue.use(Router) +Vue.use(Router); export default new Router({ - routes: [ - { - path: '/', - name: 'Index', - component: Index - }, - { - path: '/catalog/:board', - name: 'Catalog', - component: Catalog - }, - { - path: '/:board/thread/:thread' - name: 'Thread', - component: Thread - }, - { - path: '/about', - name: 'About', - component: About - } - ] + mode: 'history', + routes: [ + { + path: '/', + name: 'Index', + component: Index + }, + { + path: '/:board/catalog', + name: 'Catalog', + component: Catalog + }, + { + path: '/:board/thread/:thread', + name: 'Thread', + component: Thread + }, + { + path: '/about', + name: 'About', + component: About + }, + { + path: '/login', + name: 'Login', + component: Login + } + ] }) diff --git a/src/assets/css/common.css b/src/assets/css/common.css new file mode 100755 index 0000000..47d5bae --- /dev/null +++ b/src/assets/css/common.css @@ -0,0 +1,3 @@ +body { + background: #eef2ff url(http://s.4cdn.org/image/fade-blue.png) top center repeat-x; +} \ No newline at end of file diff --git a/assets/fonts/Arial.ttf.woff b/src/assets/fonts/Arial.ttf.woff similarity index 100% rename from assets/fonts/Arial.ttf.woff rename to src/assets/fonts/Arial.ttf.woff diff --git a/assets/fonts/Proxima-Nova-Regular.woff2 b/src/assets/fonts/Proxima-Nova-Regular.woff2 similarity index 100% rename from assets/fonts/Proxima-Nova-Regular.woff2 rename to src/assets/fonts/Proxima-Nova-Regular.woff2 diff --git a/assets/fonts/Proxima-Nova-Semibold.woff2 b/src/assets/fonts/Proxima-Nova-Semibold.woff2 similarity index 100% rename from assets/fonts/Proxima-Nova-Semibold.woff2 rename to src/assets/fonts/Proxima-Nova-Semibold.woff2 diff --git a/src/assets/js/api.js b/src/assets/js/api.js new file mode 100755 index 0000000..84eedb8 --- /dev/null +++ b/src/assets/js/api.js @@ -0,0 +1,69 @@ +let _api = { }; + +axios.defaults.withCredentials = true; + +(function () { + const root = 'http://localhost:3001/'; + const urls = { + loginUrl: 'create/session', + logoutUrl: 'read/endSession', + boardsUrl: 'read/boards', + threadsUrl: 'read/threads', + boardUrl: 'read/board', + threadUrl: 'read/thread', + repliesUrl: 'read/replies' + }; + function url(api) { + return root + urls[api]; + } + + function get(url, params, fn) { + axios.get(url, { + params: params + }) + .then(function (response) { + fn(null, response.data); + }) + .catch(function (error) { + fn(error); + }); + } + + function post(url, params, fn) { + axios.post(url, params) + .then(function (response) { + fn(null, response.data); + }) + .catch(function (error) { + fn(error); + }); + } + + _api.boards = function (fn) { + get(url('boardsUrl'), { }, fn); + }; + + _api.threads = function (letter, fn) { + get(url('threadsUrl'), { letter: letter }, fn); + }; + + _api.board = function (letter, fn) { + get(url('boardUrl'), { letter: letter }, fn); + }; + + _api.thread = function(id, fn) { + get(url('threadUrl'), { _id: id }, fn); + }; + + _api.replies = function(threadId, fn) { + get(url('repliesUrl'), { threadId: threadId }, fn); + }; + + _api.login = function (username, password, fn) { + post(url('loginUrl'), { username: username, password: password }, fn); + }; + + _api.logout = function(fn) { + post(url('logoutUrl'), {}, fn); + }; +})(); diff --git a/src/components/Catalog.vue b/src/components/Catalog.vue index e69de29..b950870 100644 --- a/src/components/Catalog.vue +++ b/src/components/Catalog.vue @@ -0,0 +1,200 @@ + + + + + \ No newline at end of file diff --git a/src/components/Index.vue b/src/components/Index.vue index 5af2e4c..4e7d26e 100644 --- a/src/components/Index.vue +++ b/src/components/Index.vue @@ -1,16 +1,150 @@ + + \ No newline at end of file diff --git a/src/components/Login.vue b/src/components/Login.vue new file mode 100644 index 0000000..df03a3e --- /dev/null +++ b/src/components/Login.vue @@ -0,0 +1,110 @@ + + + + + \ No newline at end of file diff --git a/src/components/Thread.vue b/src/components/Thread.vue index e69de29..4684e2e 100644 --- a/src/components/Thread.vue +++ b/src/components/Thread.vue @@ -0,0 +1,288 @@ + + + + + \ No newline at end of file diff --git a/webpack.config.js b/webpack.config.js index fe7ad5d..a546fe2 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -2,78 +2,55 @@ var path = require('path') var webpack = require('webpack') module.exports = { - entry: './src/main.js', - output: { - path: path.resolve(__dirname, './dist'), - publicPath: '/dist/', - filename: 'build.js' - }, - module: { - rules: [ - { - test: /\.css$/, - use: [ - 'vue-style-loader', - 'css-loader' - ], - }, { - test: /\.vue$/, - loader: 'vue-loader', - options: { - loaders: { - } - // other vue-loader options go here - } - }, - { - test: /\.js$/, - loader: 'babel-loader', - exclude: /node_modules/ - }, - { - test: /\.(png|jpg|gif|svg)$/, - loader: 'file-loader', - options: { - name: '[name].[ext]?[hash]' + entry: './src/main.js', + output: { + path: path.resolve(__dirname, './dist'), + publicPath: '/dist/', + filename: 'build.js' + }, + module: { + rules: [ + { + test: /\.vue$/, + use: { + loader: 'vue-loader' + } + }, + { + test: /\.js$/, + exclude: /node_modules/, + use: { + loader: 'babel-loader' + } + } + ] + }, + resolve: { + alias: { + 'vue$': 'vue/dist/vue.esm.js' } - } - ] - }, - resolve: { - alias: { - 'vue$': 'vue/dist/vue.esm.js' }, - extensions: ['*', '.js', '.vue', '.json'] - }, - devServer: { - historyApiFallback: true, - noInfo: true, - overlay: true, - disableHostCheck: true - }, - performance: { - hints: false - }, - devtool: '#eval-source-map' + devServer: { + historyApiFallback: true, + noInfo: true + }, + devtool: '#eval-source-map' } if (process.env.NODE_ENV === 'production') { - module.exports.devtool = '#source-map' - // http://vue-loader.vuejs.org/en/workflow/production.html - module.exports.plugins = (module.exports.plugins || []).concat([ - new webpack.DefinePlugin({ - 'process.env': { - NODE_ENV: '"production"' - } - }), - new webpack.optimize.UglifyJsPlugin({ - sourceMap: true, - compress: { - warnings: false - } - }), - new webpack.LoaderOptionsPlugin({ - minimize: true - }) - ]) -} + module.exports.devtool = '#source-map'; + // http://vue-loader.vuejs.org/en/workflow/production.html + module.exports.plugins = (module.exports.plugins || []).concat([ + new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: '"production"' + } + }), + new webpack.optimize.UglifyJsPlugin({ + compress: { + warnings: false + } + }), + new webpack.optimize.OccurrenceOrderPlugin() + ]) +} \ No newline at end of file