Skip to content

Commit

Permalink
Merge pull request #2 from ATMartin/tiny-auth
Browse files Browse the repository at this point in the history
Add simple auth
  • Loading branch information
mason-stewart committed Feb 5, 2015
2 parents 7fd641b + 5cfae04 commit a198c4b
Show file tree
Hide file tree
Showing 11 changed files with 308 additions and 97 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
node_modules
.DS_Store
.DS_Store
npm-debug.log
*.swp
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ Run `npm install` and `bower update` to get your dependencies ready. `./node_mod
#### Usage
Run `grunt` to fire it up, and make sure you have Mongo installed (`brew install mongo`) and that you've started the Mongo dæmon with `mongod`. Enjoy!

#### "Secure" Access

#####:bangbang: This is JUST FOR FUN & LEARNING. This is NOT FOR PRODUCTION USE. This is NOT SECURE. :bangbang:

Identical resources are available at `/collections` AND `/secure/collections`. POST/PUT/DELETE actions for `/secure` resources require an api key, which can be retrieved with a post call to `/secure/collections/users`. The post body should contain a JSON object with "username" and "email" values and will return a JSON object with an "apiKey" value. This can be passed as query string "api_key" for access to restricted `/secure` resources.

#### Deploy
To deploy to Heroku, use the button below. You will need to have a credit card on your account in order to set up MongoLab, but it is free and will not be charged.

Expand Down
126 changes: 32 additions & 94 deletions app.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
// require necessary modules
var express = require('express')
, mongoskin = require('mongoskin')
, routes = require('./routes')
, http = require('http')
, path = require('path')
, db = mongoskin.db((process.env.MONGOLAB_URI || 'localhost:27017/test'), {safe:true});
, routeIndex = require('./routes')
, routePublic = require('./routes/public')
, routeSecure = require('./routes/secure')
, morgan = require('morgan')
, favicon = require('serve-favicon')
, methodOverride = require('method-override')
, errorhandler = require('errorhandler')
, http = require('http')
, path = require('path')
, bodyParser = require('body-parser')

// get an instance of express
var app = express();
Expand All @@ -13,103 +17,37 @@ var allowCrossDomain = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');

// intercept OPTIONS method
if ('OPTIONS' == req.method) {
res.send(200);
}
else {
next();
}
('OPTIONS' == req.method) ? res.send(200) : next();
};

// configure it
app.configure(function(){
// Configuration
app.use(allowCrossDomain);
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(app.router);
app.use(favicon(__dirname + '/public/favicon.ico'));
app.use(morgan('dev'));
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());
app.use(methodOverride());
app.use(express.static(path.join(__dirname, 'public')));
});

// dev config
app.configure('development', function(){
app.use(express.errorHandler());
});

// PLEASE NOTE this turns on CORS for everything, everywhere!
// Almost certainly not what you want to do in production.
// app.all('/*', function(req, res, next) {
// res.header("Access-Control-Allow-Origin", "*");
// res.header("Access-Control-Allow-Headers", "X-Requested-With");
// next();
// });

// index route
app.get('/', routes.index);

// Setup the collectionName param for requests
app.param('collectionName', function(req, res, next, collectionName){
req.collection = db.collection(collectionName)
return next()
})

// API endpoints
// Thanks to http://webapplog.com/tutorial-node-js-and-mongodb-json-rest-api-server-with-mongoskin-and-express-js/
// for the cool help

// GET /collections/:collectionName
app.get('/collections/:collectionName', function(req, res) {
req.collection.find({},{limit:10, sort: [['_id',-1]]}).toArray(function(e, results){
if (e) return next(e)
res.send(results)
})
})

// POST /collections/:collectionName
app.post('/collections/:collectionName', function(req, res) {
req.collection.insert(req.body, {}, function(e, results){
if (e) return next(e)
res.send(results[0])
})
})


// GET /collections/:collectionName/:id
app.get('/collections/:collectionName/:id', function(req, res) {
req.collection.findOne({_id: req.collection.id(req.params.id)}, function(e, result){
if (e) return next(e)
res.send(result)
})
})

// PUT /collections/:collectionName/:id
app.put('/collections/:collectionName/:id', function(req, res) {

// backbone sends the _id in the payload, but mongo doesn't wan it in the $set
delete req.body._id

req.collection.update({_id: req.collection.id(req.params.id)}, {$set:req.body}, {safe:true, multi:false}, function(e, result){
res.send((result===1)? 200 : 404 )
})
})

// DELETE /collections/:collectionName
app.del('/collections/:collectionName/:id', function(req, res) {
req.collection.remove({_id: req.collection.id(req.params.id)}, function(e, result){
if (e) return next(e)
res.send((result===1)?{msg:'success'}:{msg:'error'})
})
})

// end API endpoints

// run the server
// Dev-Specific Configuration
var env = process.env.NODE_ENV || 'development';
if ('development' == env) {
app.use(errorhandler());
}

// Routes
// |-- Index
app.get('/', routeIndex.index);
// |-- Insecure API
app.use('/collections', routePublic);
// |-- "Secured" API
app.use('/secure/collections', routeSecure);

// Light It Up!
http.createServer(app).listen(app.get('port'), function(){
console.log("Express server listening on port " + app.get('port'));
});
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@
"postinstall": "./node_modules/.bin/bower install"
},
"dependencies": {
"express": "~4.0.0",
"bower": "^1.3.12",
"express": "~3.3.4",
"jade": "~0.34.0",
"mongoskin": "~0.6.0"
"mongoskin": "~0.6.0",
"body-parser": "~1.10.2",
"morgan": "~1.5.1",
"serve-favicon": "~2.2.0",
"method-override": "~2.3.1",
"errorhandler": "~1.3.2"
},
"devDependencies": {
"grunt": "~0.4.1",
Expand Down
Binary file added public/favicon.ico
Binary file not shown.
58 changes: 58 additions & 0 deletions routes/public.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
var express = require('express'),
mongoskin = require('mongoskin'),
router = express.Router(),
db = mongoskin.db((process.env.MONGOLAB_URI || 'localhost:27017/test'), {safe: true});

// Thanks to http://webapplog.com/tutorial-node-js-and-mongodb-json-rest-api-server-with-mongoskin-and-express-js/
// for the cool help

router.param('collectionName', function(req, res, next, collectionName) {
req.collection = db.collection(collectionName);
next();
});

router.route('/:collectionName')

// GET /collections/:collectionName
.get(function(req, res, next) {
req.collection.find({},{limit:10, sort: [['_id',-1]]}).toArray(function(e, results){
if (e) { return next(e); }
res.send(results);
});
})

// POST /collections/:collectionName
.post(function(req, res, next) {
req.collection.insert(req.body, {}, function(e, results, next){
if (e) { return next(e); }
res.send(results[0]);
});
});

router.route('/:collectionName/:id')

// GET /collections/:collectionName/:id
.get(function(req, res, next) {
req.collection.findOne({_id: req.collection.id(req.params.id)}, function(e, result){
if (e) { return next(e); }
res.send(result)
})
})

// PUT /collections/:collectionName/:id
.put(function(req, res) {
delete req.body._id; //<-- backbone sends the _id in the payload, but mongo doesn't wan it in the $set (--@masondesu)
req.collection.update({_id: req.collection.id(req.params.id)}, {$set:req.body}, {safe:true, multi:false}, function(e, result){
res.send((result===1)? 200 : 404 )
})
})

// DELETE /collections/:collectionName
.delete(function(req, res, next) {
req.collection.remove({_id: req.collection.id(req.params.id)}, function(e, result){
if (e) { return next(e); }
res.send((result===1)?{msg:'success'}:{msg:'error'});
});
});

module.exports = router;
Loading

0 comments on commit a198c4b

Please sign in to comment.