mirror of
https://github.com/stolksdorf/homebrewery.git
synced 2025-12-24 23:01:28 +00:00
'Created
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"host" : "homebrewery.local.naturalcrit.com:8000",
|
"host" : "localhost:8000",
|
||||||
"naturalcrit_url" : "local.naturalcrit.com:8010",
|
"login_path" : "localhost:8000/dev_login",
|
||||||
"secret" : "secret"
|
"secret" : "secretsecret",
|
||||||
|
"admin_key" : "adminadmin"
|
||||||
}
|
}
|
||||||
19
server.js
19
server.js
@@ -1,5 +1,5 @@
|
|||||||
const _ = require('lodash');
|
const _ = require('lodash');
|
||||||
const jwt = require('jwt-simple');
|
|
||||||
const express = require("express");
|
const express = require("express");
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
@@ -22,17 +22,16 @@ require('mongoose')
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
//Account MIddleware
|
//Middleware
|
||||||
app.use((req, res, next) => {
|
const mw = require('./server/middleware.js');
|
||||||
if(req.cookies && req.cookies.nc_session){
|
app.use(mw.account);
|
||||||
try{
|
app.use(mw.admin);
|
||||||
req.account = jwt.decode(req.cookies.nc_session, config.get('secret'));
|
|
||||||
}catch(e){}
|
|
||||||
}
|
|
||||||
return next();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
//Routes
|
||||||
|
|
||||||
|
|
||||||
|
app.use(require('./server/interface.routes.js'));
|
||||||
app.use(require('./server/homebrew.api.js'));
|
app.use(require('./server/homebrew.api.js'));
|
||||||
app.use(require('./server/admin.api.js'));
|
app.use(require('./server/admin.api.js'));
|
||||||
|
|
||||||
|
|||||||
51
server/brew.api.js
Normal file
51
server/brew.api.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
const _ = require('lodash');
|
||||||
|
const router = require('express').Router();
|
||||||
|
|
||||||
|
const BrewData = require('./brew.data.js');
|
||||||
|
const mw = require('./middleware.js');
|
||||||
|
|
||||||
|
//Search
|
||||||
|
router.get('/api/brew', (req, res, next) => {
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
//Get
|
||||||
|
router.get('/api/brew/:shareId', mw.viewBrew, (req, res, next) => {
|
||||||
|
return res.json(req.brew);
|
||||||
|
});
|
||||||
|
|
||||||
|
//Create
|
||||||
|
router.post('/api/brew', (req, res, next)=>{
|
||||||
|
const newBrew = req.body;
|
||||||
|
if(req.account) newBrew.authors = [req.account.username];
|
||||||
|
BrewData.create(newBrew)
|
||||||
|
.then((brew) => {
|
||||||
|
return res.json(brew);
|
||||||
|
})
|
||||||
|
.catch(next)
|
||||||
|
});
|
||||||
|
|
||||||
|
//Update
|
||||||
|
router.put('/api/brew/:editId', mw.loadBrew, mw.Validate, (req, res, next)=>{
|
||||||
|
if(req.account){
|
||||||
|
req.brew.authors = _.uniq(_.concat(req.brew.authors, req.account.username));
|
||||||
|
}
|
||||||
|
BrewData.update(req.brew)
|
||||||
|
.then((brew) => {
|
||||||
|
return res.json(brew);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
//Delete
|
||||||
|
router.delete('/api/brew/:editId', mw.loadBrew, mw.Validate, (req, res, next) => {
|
||||||
|
BrewData.remove(req.brew.editId)
|
||||||
|
.then(()=>{
|
||||||
|
return res.sendStatus(200);
|
||||||
|
})
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
114
server/brew.data.js
Normal file
114
server/brew.data.js
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
const _ = require('lodash');
|
||||||
|
const shortid = require('shortid');
|
||||||
|
const mongoose = require('mongoose');
|
||||||
|
mongoose.Promise = Promise;
|
||||||
|
|
||||||
|
const utils = require('./utils.js');
|
||||||
|
|
||||||
|
const BrewSchema = mongoose.Schema({
|
||||||
|
shareId : {type : String, default: shortid.generate, index: { unique: true }},
|
||||||
|
editId : {type : String, default: shortid.generate, index: { unique: true }},
|
||||||
|
|
||||||
|
text : {type : String, default : ""},
|
||||||
|
|
||||||
|
title : {type : String, default : ""},
|
||||||
|
description : {type : String, default : ""},
|
||||||
|
tags : {type : String, default : ""},
|
||||||
|
systems : [String],
|
||||||
|
authors : [String],
|
||||||
|
published : {type : Boolean, default : false},
|
||||||
|
|
||||||
|
createdAt : { type: Date, default: Date.now },
|
||||||
|
updatedAt : { type: Date, default: Date.now},
|
||||||
|
lastViewed : { type: Date, default: Date.now},
|
||||||
|
views : {type:Number, default:0}
|
||||||
|
}, { versionKey: false });
|
||||||
|
|
||||||
|
/*
|
||||||
|
BrewSchema.methods.sanatize = function(userName, isAdmin, getText = true){
|
||||||
|
const brew = this.toJSON();
|
||||||
|
delete brew._id;
|
||||||
|
delete brew.__v;
|
||||||
|
const isPriviledged = isAdmin || _.contains(this.authors, userName);
|
||||||
|
if(!isPriviledged) delete brew.editId;
|
||||||
|
if(!getText) delete brew.text;
|
||||||
|
return brew;
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
BrewSchema.methods.sanatize = function(req, getText = true){
|
||||||
|
const brew = this.toJSON();
|
||||||
|
delete brew._id;
|
||||||
|
delete brew.__v;
|
||||||
|
const isPriviledged = isAdmin || _.contains(this.authors, userName);
|
||||||
|
if(!isPriviledged) delete brew.editId;
|
||||||
|
if(!getText) delete brew.text;
|
||||||
|
return brew;
|
||||||
|
};
|
||||||
|
|
||||||
|
BrewSchema.methods.increaseView = function(){
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.lastViewed = new Date();
|
||||||
|
this.views = this.views + 1;
|
||||||
|
this.save((err) => {
|
||||||
|
if(err) return reject(err);
|
||||||
|
return resolve(this);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const Brew = mongoose.model('Brew', BrewSchema);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const BrewData = {
|
||||||
|
schema : BrewSchema,
|
||||||
|
model : Brew,
|
||||||
|
|
||||||
|
get : (query) => {
|
||||||
|
//returns a single brew with the given query
|
||||||
|
//Start using egads for errors
|
||||||
|
return Brew.findOne(query).exec();
|
||||||
|
},
|
||||||
|
create : (brew) => {
|
||||||
|
delete brew.shareId;
|
||||||
|
delete brew.editId;
|
||||||
|
|
||||||
|
if(!brew.title) brew.title = utils.getGoodBrewTitle(brew.text);
|
||||||
|
const newBrew = new Brew(brew);
|
||||||
|
|
||||||
|
//TODO: add error decorators to the catches
|
||||||
|
return newBrew.save();
|
||||||
|
},
|
||||||
|
update : (newBrew) => {
|
||||||
|
return Brew.findOneAndUpdate({ editId : newBrew.editId }, {
|
||||||
|
...newBrew,
|
||||||
|
updatedAt : Date.now()
|
||||||
|
}, {new : true, upsert : true}).exec(); //TODO: TEST THIS that this returns a reocrd
|
||||||
|
},
|
||||||
|
remove : (editId) => {
|
||||||
|
return Brew.find({ editId }).remove().exec();
|
||||||
|
},
|
||||||
|
|
||||||
|
//////// Special
|
||||||
|
|
||||||
|
|
||||||
|
getByShare : (shareId) => {
|
||||||
|
//auto sanatize
|
||||||
|
//increase view count
|
||||||
|
},
|
||||||
|
getByEdit : (editId) => {
|
||||||
|
return Brew.get({ editId });
|
||||||
|
},
|
||||||
|
|
||||||
|
search : (query, req={}) => {
|
||||||
|
//defaults with page and count
|
||||||
|
//returns a non-text version of brews
|
||||||
|
//assume sanatized ?
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = BrewData;
|
||||||
54
server/interface.routes.js
Normal file
54
server/interface.routes.js
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
const _ = require('lodash');
|
||||||
|
const utils = require('./utils.js');
|
||||||
|
const BrewData = require('./brew.data.js');
|
||||||
|
const router = require('express').Router();
|
||||||
|
|
||||||
|
|
||||||
|
const vitreumRender = require('vitreum/steps/render');
|
||||||
|
const templateFn = require('./client/template.js');
|
||||||
|
const renderPage = (req, res, next) => {
|
||||||
|
return vitreumRender('homebrew', templateFn, {
|
||||||
|
url : req.originalUrl,
|
||||||
|
version : require('./package.json').version,
|
||||||
|
|
||||||
|
user : req.account && req.account.username,
|
||||||
|
brews : req.brews,
|
||||||
|
brew : req.brew
|
||||||
|
})
|
||||||
|
.then(res.send)
|
||||||
|
.catch(next)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//Share Page
|
||||||
|
router.get('/share/:shareId', mw.viewBrew, renderPage);
|
||||||
|
|
||||||
|
//Edit Page
|
||||||
|
app.get('/edit/:editId', mw.loadBrew, mw.validate, renderPage);
|
||||||
|
|
||||||
|
//Print Page
|
||||||
|
app.get('/print/:shareId', mw.viewBrew, renderPage);
|
||||||
|
|
||||||
|
//Source page
|
||||||
|
router.get('/source/:sharedId', mw.viewBrew, (req, res, next)=>{
|
||||||
|
const text = utils.replaceByMap(req.brew.text, { '<' : '<', '>' : '>' });
|
||||||
|
return res.send(`<code><pre>${text}</pre></code>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//user Page
|
||||||
|
router.get('/user/:username', (req, res, next) => {
|
||||||
|
BrewData.search({ user : req.params.username }, req)
|
||||||
|
.then((brews) => {
|
||||||
|
return render(req, { brews : brews });
|
||||||
|
})
|
||||||
|
.then(res.send)
|
||||||
|
.catch(next);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//Catch all page?
|
||||||
|
router.get('*', renderPage);
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
62
server/middleware.js
Normal file
62
server/middleware.js
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
const _ = require('lodash');
|
||||||
|
const jwt = require('jwt-simple');
|
||||||
|
const config = require('nconf');
|
||||||
|
|
||||||
|
const BrewData = require('./brew.data.js');
|
||||||
|
|
||||||
|
const Middleware = {
|
||||||
|
account : (req, res, next) => {
|
||||||
|
if(req.cookies && req.cookies.nc_session){
|
||||||
|
try{
|
||||||
|
req.account = jwt.decode(req.cookies.nc_session, config.get('secret'));
|
||||||
|
}catch(e){}
|
||||||
|
}
|
||||||
|
return next();
|
||||||
|
},
|
||||||
|
admin : (req, res, next) => {
|
||||||
|
if(req.query.admin_key === config.get('admin_key')){
|
||||||
|
delete req.admin_key;
|
||||||
|
req.isAdmin = true;
|
||||||
|
}
|
||||||
|
return next();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
//Filters
|
||||||
|
devOnly : (req, res, next) => {
|
||||||
|
const env = process.env.NODE_ENV;
|
||||||
|
if(env !== 'staging' && env !== 'production') return next();
|
||||||
|
return res.sendStatus(404);
|
||||||
|
},
|
||||||
|
adminOnly : (req, res, next) => {
|
||||||
|
if(req.isAdmin) return next();
|
||||||
|
return res.sendStatus(401);
|
||||||
|
},
|
||||||
|
validate : (req, res, next) => {
|
||||||
|
//Only allow admin or brew authors pass.
|
||||||
|
|
||||||
|
return next();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
//Loaders
|
||||||
|
loadBrew : (req, res, next) => {
|
||||||
|
//Loads a brew by edit id
|
||||||
|
if(req.params.shareId){
|
||||||
|
BrewData.get({ shareId : req.params.shareId})
|
||||||
|
.then((brew))
|
||||||
|
}else if(req.params.editId){
|
||||||
|
|
||||||
|
|
||||||
|
}else{
|
||||||
|
return next();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
viewBrew : (req, res, next) => {
|
||||||
|
//load by share
|
||||||
|
//increase view count
|
||||||
|
},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Middleware;
|
||||||
23
server/utils.js
Normal file
23
server/utils.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getGoodBrewTitle : (text) => {
|
||||||
|
const titlePos = text.indexOf('# ');
|
||||||
|
if(titlePos !== -1){
|
||||||
|
const ending = text.indexOf('\n', titlePos);
|
||||||
|
return text.substring(titlePos + 2, ending);
|
||||||
|
}else{
|
||||||
|
return _.find(text.split('\n'), (line)=>{
|
||||||
|
return line;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
replaceByMap : (text, mapping) => {
|
||||||
|
return _.reduce(mapping, (r, search, replace) => {
|
||||||
|
return r.split(search).join(replace)
|
||||||
|
}, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user