From e4b5f6158a6855be44ff79dce6bcc45d26419ff6 Mon Sep 17 00:00:00 2001 From: ang-st Date: Mon, 30 Mar 2015 22:04:08 +0100 Subject: [PATCH] basic setup --- .gitignore | 2 + README.md | 4 ++ app.js | 52 ++++++++++++++++++++++- createdb.sh | 7 +++ db.js | 26 ++++++++++++ model.js | 11 +++++ package.json | 7 +++ pages/home.markdown | 7 ++- routes/index.js | 101 +++++++++++++++++++++++++++++++++++++++++++- views/404.jade | 4 ++ views/signin.jade | 13 ++++++ views/signup.jade | 11 +++++ 12 files changed, 238 insertions(+), 7 deletions(-) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 createdb.sh create mode 100644 model.js create mode 100644 views/404.jade create mode 100644 views/signin.jade create mode 100644 views/signup.jade diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a4c2fcb --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +app.db +node_modules diff --git a/README.md b/README.md new file mode 100644 index 0000000..34ff3bc --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +#kitteh wiki +simple wiki for thsf site + + diff --git a/app.js b/app.js index 9373e1c..aca075d 100644 --- a/app.js +++ b/app.js @@ -1,12 +1,51 @@ var Express = require('express'); var Routes = require('./routes'); - +var passport = require('passport'); +var bodyParser = require('body-parser'); +var cookieParser = require('cookie-parser'); +var session = require('express-session'); +var bcrypt = require('bcrypt-nodejs'); +var crypto = require('crypto'); +var sqlite3 = require('sqlite3'); +var Model = require('./model'); +var LocalStrategy = require('passport-local').Strategy; // var TryCatch = require('./trycatch'); var App = Express(); // Configuration + + +passport.use(new LocalStrategy(function(username, password, done) { + new Model.User({username: username}).fetch().then(function(data) { + var user = data; + if(user === null) { + return done(null, false, {message: 'Invalid username or password'}); + } else { + user = data.toJSON(); + if(!bcrypt.compareSync(password, user.password)) { + return done(null, false, {message: 'Invalid username or password'}); + } else { + return done(null, user); + } + } + }); +})); + + + +passport.serializeUser(function(user, done) { + done(null, user.username); +}); + +passport.deserializeUser(function(username, done) { + new Model.User({username: username}).fetch().then(function(user) { + done(null, user); + }); +}); + + App.configure(function(){ App.set('views', __dirname + '/views'); App.set('view engine', 'jade'); @@ -14,6 +53,11 @@ App.configure(function(){ // App.use(function (req, res, next) { // TryCatch(next, next); // }); + App.use(cookieParser()); + App.use(bodyParser()); + App.use(session({ secret: 'whenidrinktoomuchigetdrunk' })); // session secret + App.use(passport.initialize()); + App.use(passport.session()); App.use(Express.bodyParser()); App.use(Express.methodOverride()); App.use(App.router); @@ -30,9 +74,15 @@ App.configure('production', function(){ // Routes App.get('/', Routes.index); +App.get('/signin', Routes.signIn); +App.post('/signin', Routes.signInPost); +App.get('/signup', Routes.signUp); +App.post('/signup', Routes.signUpPost); +App.get('/signout', Routes.signout) App.get('/:name', Routes.view); App.get('/:name/edit', Routes.edit); App.post('/:name', Routes.save); + server = App.listen(process.env.PORT || 3000); console.log("Express server listening on port %d in %s mode", server.address().port, App.settings.env); diff --git a/createdb.sh b/createdb.sh new file mode 100644 index 0000000..4420f90 --- /dev/null +++ b/createdb.sh @@ -0,0 +1,7 @@ +CREATE TABLE "users" ( + "id" INTEGER PRIMARY KEY AUTOINCREMENT, + "username" TEXT, + "password" TEXT, -- sha256 hash of the plain-text password + "salt" TEXT -- salt that is appended to the password before it is hashed +) + diff --git a/db.js b/db.js index e179aa8..e68c2e9 100644 --- a/db.js +++ b/db.js @@ -1,6 +1,9 @@ var FS = require('fs'); var Path = require('path'); var Markdown = require('markdown').markdown; +var knex = require("knex"); + +var Bookshelf = require('bookshelf'); // This function is used to map wiki page names to files // on the real filesystem. @@ -55,3 +58,26 @@ exports.savePage = function (name, value, callback) { var path = pathFromName(name); FS.writeFile(path, value, callback); }; + +var dbFile = Path.join(__dirname, 'app.db'); +var DB = Bookshelf(knex({ + client: 'sqlite3', + connection: { filename: dbFile } +})); + +FS.exists(dbFile, function(exists) { + if (!exists) { + console.log("create a new DB") + DB.knex.schema.createTable('Users', function(table) { + table.increments("id") + table.string('username') + table.string('password') + }).then( function(){ console.log("DB created") }) + } +}) + +exports.DB = DB; + + + + diff --git a/model.js b/model.js new file mode 100644 index 0000000..c061e9a --- /dev/null +++ b/model.js @@ -0,0 +1,11 @@ +var DB = require('./db').DB; +var User = DB.Model.extend({ + tableName: 'Users', + idAttribute: 'userId', +}); + +module.exports = { + User: User +}; + + diff --git a/package.json b/package.json index 2f523e4..db509d9 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,16 @@ "version": "0.0.0", "private": true, "dependencies": { + "bcrypt-nodejs": "0.0.3", + "body-parser": "^1.12.2", + "bookshelf": "^0.7.9", + "cookie-parser": "^1.3.4", "express": "3.0.2", + "express-session": "^1.10.4", "jade": ">= 0.0.1", + "knex": "^0.7.6", "markdown": "~0.3.1", + "passport-local": "^1.0.0", "trycatch": "~0.0.9" } } diff --git a/pages/home.markdown b/pages/home.markdown index c522f2e..1ed6ed2 100644 --- a/pages/home.markdown +++ b/pages/home.markdown @@ -1,5 +1,4 @@ -# Home Page +###Hello THSF +this is a simple wiki :) -This is the homepage of the wiki. - -Cool stuff here. \ No newline at end of file +![](http://stuffpoint.com/lol-cats/image/29077-lol-cats-magical-kitteh.png) \ No newline at end of file diff --git a/routes/index.js b/routes/index.js index 1572f0d..6c540e3 100644 --- a/routes/index.js +++ b/routes/index.js @@ -1,6 +1,8 @@ // Load our model abstraction so we can load and save pages in the wiki. +var passport = require('passport'); var DB = require('../db'); - +var Model = require('../model') +var bcrypt = require('bcrypt-nodejs'); // When the wiki is initially loaded, simply redirect to the `home` page. exports.index = function(req, res) { res.redirect("/home"); @@ -16,16 +18,111 @@ exports.view = function (req, res, next) { // Load a page from the database and render edit form exports.edit = function (req, res, next) { + + if(!req.isAuthenticated()) { + res.redirect('/signin'); + } + else{ DB.loadPage(req.params.name, function (err, page) { if (err) return next(err); res.render('edit', page); }); + } }; // Save changes to a page and redirect to view page exports.save = function (req, res, next) { + if(!req.isAuthenticated()) { + res.redirect('/signin'); + } + else { DB.savePage(req.params.name, req.body.markdown, function (err) { if (err) return next(err) res.redirect("/" + req.params.name); }); -} \ No newline at end of file + } +} + + +var signIn = function(req, res, next) { + if(req.isAuthenticated()) res.redirect('/'); + res.render('signin', {title: 'Sign In'}); +}; + +var signInPost = function(req, res, next) { + passport.authenticate('local', { successRedirect: '/', + failureRedirect: '/signin'}, function(err, user, info) { + if(err) { + return res.render('signin', {title: 'Sign In', errorMessage: err.message}); + } + + if(!user) { + return res.render('signin', {title: 'Sign In', errorMessage: info.message}); + } + return req.logIn(user, function(err) { + if(err) { + return res.render('signin', {title: 'Sign In', errorMessage: err.message}); + } else { + return res.redirect('/'); + } + }); + })(req, res, next); +}; + +var signUp = function(req, res, next) { + if(req.isAuthenticated()) { + res.redirect('/'); + } else { + res.render('signup', {title: 'Sign Up'}); + } +}; + +var signUpPost = function(req, res, next) { + var user = req.body; + var usernamePromise = null; + usernamePromise = new Model.User({username: user.username}).fetch(); + return usernamePromise.then(function(model) { + if(model) { + res.render('signup', {title: 'signup', errorMessage: 'username already exists'}); + } else { + //****************************************************// + // MORE VALIDATION GOES HERE(E.G. PASSWORD VALIDATION) + //****************************************************// + var password = user.password; + var hash = bcrypt.hashSync(password); + + var signUpUser = new Model.User({username: user.username, password: hash}); + + signUpUser.save().then(function(model) { + // sign in the newly registered user + signInPost(req, res, next); + }); + } + }); +}; + + +var signOut = function(req, res, next) { + if(!req.isAuthenticated()) { + notFound404(req, res, next); + } else { + req.logout(); + res.redirect('/signin'); + } +}; + + + +// 404 not found +var notFound404 = function(req, res, next) { + res.status(404); + res.render('404', {title: '404 Not Found'}); +}; + + +exports.signIn=signIn +exports.signInPost=signInPost +exports.signUpPost=signUpPost +exports.signUp = signUp +exports.signOut= signOut +exports.notFound404 = notFound404 diff --git a/views/404.jade b/views/404.jade new file mode 100644 index 0000000..eecf68f --- /dev/null +++ b/views/404.jade @@ -0,0 +1,4 @@ +head + 404 +body + h1 404 diff --git a/views/signin.jade b/views/signin.jade new file mode 100644 index 0000000..dd8ac08 --- /dev/null +++ b/views/signin.jade @@ -0,0 +1,13 @@ +h2 signin +form(method='post', action="/signin") + if errorMessage + span= errorMessage + p + label(for="username") username + input(id="username", type="text",placeholder='username',required="true" ,name ='username') + p + label(for="password") password + input(id="password", type='text', placeholder='password', required="true", name = 'password') + p + input(type='submit',name="signin", id='signin') + a(href="/signup", title="register") signup diff --git a/views/signup.jade b/views/signup.jade new file mode 100644 index 0000000..666bfee --- /dev/null +++ b/views/signup.jade @@ -0,0 +1,11 @@ +h2 signup +form(method='post', action="/signup") + p + label(for="username") username + input(id="username", type="text",placeholder='username',required="true", name="username") + p + label(for="password") password + input(id="password", type='text', placeholder='password', required="true", name="password") + p + input(type='submit',name="signup", id='signup', value='register') + a(href="/signin", title="signin") signin