diff options
Diffstat (limited to 'app/server')
| -rw-r--r-- | app/server/db/model.js | 55 | ||||
| -rw-r--r-- | app/server/db/models.js | 4 | ||||
| -rw-r--r-- | app/server/site.js | 34 | ||||
| -rw-r--r-- | app/server/util/auth.js | 168 |
4 files changed, 231 insertions, 30 deletions
diff --git a/app/server/db/model.js b/app/server/db/model.js index dd851bf..c829c85 100644 --- a/app/server/db/model.js +++ b/app/server/db/model.js @@ -17,9 +17,8 @@ module.exports = function modelScope(type, db_model, _props) { crud: crud, index: (query) => { - - return new Promise( (resolve, reject) => { - crud.index(query).then( (data) => { + return new Promise((resolve, reject) => { + crud.index(query).then(data => { if (! props.hasOne) { resolve(data ? data.toJSON() : []) @@ -27,13 +26,13 @@ module.exports = function modelScope(type, db_model, _props) { else { let recs = data.toJSON() const loader = new Loader () - loader.onReady( () => { + loader.onReady(() => { // console.log(type, 'ready') resolve(recs) }) // console.log('hasOne') loader.register('hasOne') - Object.keys(props.hasOne).forEach( (key,i) => { + Object.keys(props.hasOne).forEach((key, i) => { loader.register(key) // console.log('register', key) const type = props.hasOne[key] @@ -45,7 +44,7 @@ module.exports = function modelScope(type, db_model, _props) { }) // console.log('\n\n%%%%%%%%%%%%%%%%%%%%%%%% index > hasOne ' + key + '\n\n\n') // console.log(recs.length, Object.keys(id_lookup).length) - db_crud(type).show_ids(Object.keys(id_lookup)).then( (sub_recs) => { + db_crud(type).show_ids(Object.keys(id_lookup)).then(sub_recs => { // console.log(key, 'sub_recs', sub_recs) const short_key = key.replace('_id','') sub_recs.toJSON().forEach(rec => { @@ -57,49 +56,51 @@ module.exports = function modelScope(type, db_model, _props) { }) loader.ready('hasOne') } - }) // }).catch( () => res.sendStatus(500) ) + }) }) }, - show: (id) => { - return new Promise( (resolve, reject) => { - crud.show(id).then( (data) => { - if (! props.hasOne) { + show: (id, field = 'id') => { + return new Promise((resolve, reject) => { + crud.show(id, field).then(data => { + if (!data) { + resolve() + } else if (! props.hasOne) { resolve(data.toJSON()) } else { let rec = data.toJSON() const loader = new Loader () - loader.onReady( () => { + loader.onReady(() => { resolve(rec) }) loader.register('hasOne') - Object.keys(props.hasOne).forEach( (key,i) => { + Object.keys(props.hasOne).forEach((key, i) => { loader.register(key) const type = props.hasOne[key] - db_crud(type).show(rec[key + '_id']).then( (sub_rec) => { + db_crud(type).show(rec[key + '_id']).then((sub_rec) => { rec[key] = sub_rec loader.ready(key) }) }) loader.ready('hasOne') } - }) // .catch( (err) => res.sendStatus(500) ) + }) }) }, findOrCreate: (data) => { - return new Promise( (resolve, reject) => { + return new Promise((resolve, reject) => { let query = Object.assign({}, data) query.limit = 1 - crud.index(query).then( (recs) => { + crud.index(query).then((recs) => { if (recs && recs.length) { const rec = recs.at(0) // console.log('found rec', data.name) return resolve(rec) } // console.log('creating rec', data.name) - model.create(data).then( (rec) => { + model.create(data).then((rec) => { resolve(rec) }) }) @@ -107,12 +108,12 @@ module.exports = function modelScope(type, db_model, _props) { }, create: (data) => { - return new Promise( (resolve, reject) => { + return new Promise((resolve, reject) => { const should_relay = data.should_relay === 'true' - crud.create( model.sanitize(data) ).then( (rec) => { + crud.create( model.sanitize(data) ).then((rec) => { resolve(rec.toJSON()) props.afterCreate && props.afterCreate(rec, should_relay) - }).catch( (e) => { + }).catch(e => { console.error('error creating', e) reject() }) @@ -121,10 +122,10 @@ module.exports = function modelScope(type, db_model, _props) { update: (id, data) => { // console.log('update', id) - return new Promise( (resolve, reject) => { - crud.update(id, model.sanitize(data)).then( (data) => { + return new Promise((resolve, reject) => { + crud.update(id, model.sanitize(data)).then(data => { resolve(data.toJSON()) - }).catch( (e) => { + }).catch(e => { console.error('error updating', e) reject() }) @@ -132,7 +133,7 @@ module.exports = function modelScope(type, db_model, _props) { }, destroy: (id) => { - return new Promise( (resolve, reject) => { + return new Promise((resolve, reject) => { crud.show(id).then( data => { if (! data) { console.error('no record found', id) @@ -141,9 +142,9 @@ module.exports = function modelScope(type, db_model, _props) { if (type === 'file') { upload.destroyFile(data) } - crud.destroy(id).then( (destroyData) => { + crud.destroy(id).then((destroyData) => { resolve(data.toJSON()) - })// .catch( () => res.sendStatus(500) ) + }) }) }) }, diff --git a/app/server/db/models.js b/app/server/db/models.js index 24be774..8bf6d9a 100644 --- a/app/server/db/models.js +++ b/app/server/db/models.js @@ -21,7 +21,7 @@ let Task = bookshelf.Model.extend({ jsonColumns: ['opt'], }) let User = bookshelf.Model.extend({ - tableName: 'user', + tableName: 'users', hasTimestamps: true, }, { jsonColumns: ['profile'], @@ -61,7 +61,7 @@ module.exports = { // bridge.processTasks() } }), - user: model('user', Task, { + user: model('user', User, { fields: "username password realname level avatar lastseen profile created_at updated_at".split(" "), afterCreate: (user) => { console.log('created user') diff --git a/app/server/site.js b/app/server/site.js index 85c932f..717e42b 100644 --- a/app/server/site.js +++ b/app/server/site.js @@ -2,12 +2,18 @@ const express = require('express') const http = require('http') const path = require('path') const multer = require('multer')() -const upload = require('./util/upload') +const sessionstore = require('sessionstore') +const session = require('express-session') const bodyParser = require('body-parser') +const cookieParser = require('cookie-parser') +const MongoStore = require('connect-mongo')(session); const compression = require('compression') // const multer = require('multer') // const upload = multer({ dest: 'uploads/' }) +const upload = require('./util/upload') +const auth = require('./util/auth') + export const app = new express() export const server = http.createServer(app) @@ -17,6 +23,32 @@ app.use(bodyParser.urlencoded({ extended: false, limit: '100mb', })) app.use(express.query()) app.use(express.static(path.join(__dirname, '../../public'))) app.use(compression()) +app.use(cookieParser()) +var sessionSettings = { + secret: 'argonauts', + proxy: true, + key: 'cortex.sid', + cookie: { + secure: process.env.NODE_ENV === 'production', + domain: '.' + process.env.HOST_NAME, + maxAge: 43200000000, + }, + resave: true, + saveUninitialized: false, +} +if (!process.env.SESSIONS_IN_MEMORY) { + sessionSettings.store = new MongoStore({ + url: 'mongodb://127.0.0.1:28108/cortexSessionDb' + // type: 'mongodb', + // host: 'localhost', + // port: 27017, + // dbName: 'buckySessionDb', + // collectionName: 'sessions', + // timeout: 10000, + }) +} +app.use(session(sessionSettings)) +auth.route(app, serve_index) export const io = require('socket.io').listen(server) diff --git a/app/server/util/auth.js b/app/server/util/auth.js new file mode 100644 index 0000000..1515bb4 --- /dev/null +++ b/app/server/util/auth.js @@ -0,0 +1,168 @@ +import passport from 'passport' +import { Strategy as LocalStrategy } from 'passport-local' +import crypto from 'crypto' +import db from '../db' + +const { user: userModel } = db.models + +export function route(app, serve_index){ + app.use(passport.initialize()) + app.use(passport.session()) + passport.serializeUser(serializeUser) + passport.deserializeUser(deserializeUser) + passport.use(new LocalStrategy(verifyLocalUser)) + + app.get("/login", serve_index) + app.get("/signup", serve_index) + app.get("/logout", logout) + + app.put("/api/signup", + checkIfUserExists, + createUser, + login) + app.put("/api/login", + passport.authenticate("local"), + login) + app.put("/api/checkin", + ensureAuthenticated, + checkin) +} + +export function ensureAuthenticated(req, res, next) { + if (!req.isAuthenticated()) { + if (req.session) req.session.returnTo = req.path + return res.redirect('/login') + } + next() +} + +export function getUserByUsername(username) { + return userModel.show(sanitizeName(username), 'username') +} + +export function checkIfUserExists(req, res, next) { + getUserByUsername(req.body.username) + .then((user) => { + console.log('gotta user?', !!user); + user ? res.json({ error: "user exists" }) : next() + }).catch(err => { + console.error('error', err) + }) +} + +export function sanitizeName(s) { return (s || "").replace(new RegExp('[^-_a-zA-Z0-9]', 'g'), "") } +export function sanitizeUser(req_user) { + // sanitize user object + let user = JSON.parse(JSON.stringify(req_user)) + try { + user.profile = JSON.parse(user.profile) + } catch (e) { + console.error('error decoding profile') + user.profile = {} + } + delete user.password + return user +} + +export function createUser(req, res, next) { + const { username, password, password2 } = req.body + if (password !== password2) { + return res.json({ error: "passwords don't match" }) + } + let data = { + username: sanitizeName(username), + realname: sanitizeName(username), + password: makePassword(password), + lastseen: new Date(), + level: 0, + profile: {}, + } + userModel.create(data) + .then(user => { + console.log('created userrrrr', user) + req.login(user, err => { + console.log(err) + err ? next(err) : next() + }) + }) + .catch(err => { + res.json({ error }) + }) +} + +export function login(req, res) { + console.log(req.user) + if (req.isAuthenticated()) { + let returnTo = req.session.returnTo + delete req.session.returnTo + console.log(">> logged in", req.user.username) + return res.json({ + status: "OK", + user: sanitizeUser(req.user), + returnTo: returnTo || "/", + }) + } + res.json({ + error: 'bad credentials', + }) +} + +export function serializeUser(user, done) { + done(null, user.id) +} + +export function deserializeUser(id, done) { + userModel.show(id).then(user => { + done(!user, user) + }).catch(done) +} + +export function makePassword(password) { + let shasum = crypto.createHash('sha1') + shasum.update(password) + return shasum.digest('hex') +} + +export function validPassword(user, password) { + return user.password === makePassword(password) +} + +export function changePassword(req, res, next) { + if (!req.body.oldpassword && !req.body.newpassword) return next() + if (req.body.newpassword !== req.body.newpassword2) { + return res.send({ error: 'Passwords don\'t match.' }) + } + if (!validPassword(res.user, req.body.oldpassword)) { + return res.send({ error: 'Password is incorrect.' }) + } + let username = req.user.username + let newPassword = makePassword(req.body.newpassword) + res.user.password = newPassword + res.user.save() + .then(next) + .catch(err => res.send({ error: err })) +} + +export function verifyLocalUser(username, password, done) { + // handle passwords!! + getUserByUsername(username) + .then(user => { + console.log(user) + // if (err) { return done(err) } + if (! user) { return done("no user") } + if (! user || !validPassword(user, password)) { + return done(null, false, { error: { message: 'Bad username/password.' } }) + } + return done(null, user) + }) +} + +export function checkin(req, res) { + console.log(req.user) + res.json({ user: sanitizeUser(req.user) }) +} + +export const logout = (req, res) => { + req.logout() + res.redirect('/') +}
\ No newline at end of file |
