Loading opt/comments-server-side/app.js +250 −246 Original line number Diff line number Diff line Loading @@ -19,10 +19,8 @@ * */ config = require('./config'); mongoose = require('mongoose'); var config = require('./config'); require('./database'); require('express-namespace'); var mysql = require('mysql'), client = mysql.createClient({ Loading @@ -32,67 +30,78 @@ var mysql = require('mysql'), database: config.db.dbName }), express = require('express'), connect = require('connect'), MongoStore = require('connect-session-mongo'), MongoStore = require('connect-mongo'), _ = require('underscore'), ForumUser = require('./ForumUser').ForumUser, forumUser = new ForumUser(client), util = require('./util'), crypto = require('crypto'); crypto = require('crypto'), mongoose = require('mongoose'); var app = express(); var app = express.createServer( app.configure(function() { // Headers for Cross Origin Resource Sharing (CORS) function (req, res, next) { app.use(function (req, res, next) { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept'); next(); }, }); express.cookieParser(), app.use(express.cookieParser(config.sessionSecret)); // Hack to set session cookie if session ID is set as a URL param. // This is because not all browsers support sending cookies via CORS function(req, res, next) { if (req.query.sid) { app.use(function(req, res, next) { if (req.query.sid && req.query.sid != 'null') { var sid = req.query.sid.replace(/ /g, '+'); req.cookies = req.cookies || {}; req.cookies['sencha_docs'] = sid; req.sessionID = sid; req.signedCookies = req.signedCookies || {}; req.signedCookies['sencha_docs'] = sid; } next(); }, }); // Use MongoDB for session storage connect.session({ store: new MongoStore, secret: config.sessionSecret, key: 'sencha_docs' }), function(req, res, next) { app.use(express.session({ secret: config.sessionSecret, key: 'sencha_docs', store: new MongoStore({ url: exports.mongoDb + "/sessions" }) })); app.use(function(req, res, next) { // IE doesn't get content-type, so default to form encoded. if (!req.headers['content-type']) { req.headers['content-type'] = 'application/x-www-form-urlencoded'; } next(); }, express.bodyParser(), express.methodOverride() ); }); app.use(express.bodyParser()); app.use(express.methodOverride()); app.enable('jsonp callback'); }); // All URLs start with /auth app.namespace('/auth', function(){ app.configure('development', function(){ app.use(express.logger('dev')); app.use(express.errorHandler()); }); /** * Authentication */ app.get('/session', function(req, res) { app.get('/auth/session', function(req, res) { var result = req.session && req.session.user && forumUser.clientUser(req.session.user); res.json(result || false); }); app.post('/login', function(req, res){ app.post('/auth/login', function(req, res){ forumUser.login(req.body.username, req.body.password, function(err, result) { Loading @@ -114,7 +123,7 @@ app.namespace('/auth', function(){ }); // Remove session app.post('/logout', function(req, res){ app.post('/auth/logout', function(req, res){ req.session.user = null; res.json({ success: true }); }); Loading @@ -122,7 +131,7 @@ app.namespace('/auth', function(){ /** * Handles comment unsubscription requests. */ app.get('/unsubscribe/:subscriptionId', function(req, res) { app.get('/auth/unsubscribe/:subscriptionId', function(req, res) { Subscription.findOne({ _id: req.params.subscriptionId }, function(err, subscription) { if (err) throw(err); Loading @@ -143,18 +152,15 @@ app.namespace('/auth', function(){ }); }); }); /** * Commenting */ app.namespace('/auth/:sdk/:version', function(){ /** * Returns a list of comments for a particular target (eg class, guide, video) */ app.get('/comments', util.getCommentReads, function(req, res) { app.get('/auth/:sdk/:version/comments', util.getCommentReads, function(req, res) { if (!req.query.startkey) { res.json({error: 'Invalid request'}); Loading @@ -179,7 +185,7 @@ app.namespace('/auth/:sdk/:version', function(){ * `offset` and `limit` fields. I'd say it's a hack, but at least * it works for now. */ app.get('/comments_recent', util.getCommentReads, function(req, res) { app.get('/auth/:sdk/:version/comments_recent', util.getCommentReads, function(req, res) { var offset = parseInt(req.query.offset, 10) || 0; var limit = parseInt(req.query.limit, 10) || 100; var filter = { Loading Loading @@ -209,21 +215,21 @@ app.namespace('/auth/:sdk/:version', function(){ * Returns number of comments for each class/member, * and a list of classes/members into which the user has subscribed. */ app.get('/comments_meta', util.getCommentCounts, util.getCommentSubscriptions, function(req, res) { app.get('/auth/:sdk/:version/comments_meta', util.getCommentCounts, util.getCommentSubscriptions, function(req, res) { res.send({ comments: req.commentCounts, subscriptions: req.commentSubscriptions || [] }); }); /** * Returns an individual comment (used when editing a comment) */ app.get('/comments/:commentId', util.findComment, function(req, res) { app.get('/auth/:sdk/:version/comments/:commentId', util.findComment, function(req, res) { res.json({ success: true, content: req.comment.content }); }); /** * Creates a new comment */ app.post('/comments', util.requireLoggedInUser, function(req, res) { app.post('/auth/:sdk/:version/comments', util.requireLoggedInUser, function(req, res) { var target = JSON.parse(req.body.target); Loading Loading @@ -260,7 +266,7 @@ app.namespace('/auth/:sdk/:version', function(){ /** * Updates an existing comment (for voting or updating contents) */ app.post('/comments/:commentId', util.requireLoggedInUser, util.findComment, function(req, res) { app.post('/auth/:sdk/:version/comments/:commentId', util.requireLoggedInUser, util.findComment, function(req, res) { var voteDirection, comment = req.comment; Loading Loading @@ -288,7 +294,7 @@ app.namespace('/auth/:sdk/:version', function(){ /** * Deletes a comment */ app.post('/comments/:commentId/delete', util.requireLoggedInUser, util.findComment, util.requireOwner, function(req, res) { app.post('/auth/:sdk/:version/comments/:commentId/delete', util.requireLoggedInUser, util.findComment, util.requireOwner, function(req, res) { req.comment.deleted = true; req.comment.save(function(err, response) { res.send({ success: true }); Loading @@ -298,7 +304,7 @@ app.namespace('/auth/:sdk/:version', function(){ /** * Restores deleted comment */ app.post('/comments/:commentId/undo_delete', util.requireLoggedInUser, util.findComment, util.requireOwner, util.getCommentReads, function(req, res) { app.post('/auth/:sdk/:version/comments/:commentId/undo_delete', util.requireLoggedInUser, util.findComment, util.requireOwner, util.getCommentReads, function(req, res) { req.comment.deleted = false; req.comment.save(function(err, response) { res.send({ success: true, comment: util.scoreComments([req.comment], req)[0] }); Loading @@ -308,7 +314,7 @@ app.namespace('/auth/:sdk/:version', function(){ /** * Marks a comment 'read' */ app.post('/comments/:commentId/read', util.requireLoggedInUser, util.findCommentMeta, function(req, res) { app.post('/auth/:sdk/:version/comments/:commentId/read', util.requireLoggedInUser, util.findCommentMeta, function(req, res) { req.commentMeta.metaType = 'read'; req.commentMeta.save(function(err, response) { res.send({ success: true }); Loading @@ -318,14 +324,14 @@ app.namespace('/auth/:sdk/:version', function(){ /** * Get email subscriptions */ app.get('/subscriptions', util.getCommentSubscriptions, function(req, res) { app.get('/auth/:sdk/:version/subscriptions', util.getCommentSubscriptions, function(req, res) { res.json({ subscriptions: req.commentMeta.subscriptions }); }); /** * Subscibe / unsubscribe to a comment thread */ app.post('/subscribe', util.requireLoggedInUser, function(req, res) { app.post('/auth/:sdk/:version/subscribe', util.requireLoggedInUser, function(req, res) { var subscriptionBody = { sdk: req.params.sdk, Loading Loading @@ -354,8 +360,6 @@ app.namespace('/auth/:sdk/:version', function(){ }); }); }); var port = 3000; app.listen(port); console.log("Server started at port "+port+"..."); Loading opt/comments-server-side/database.js +8 −1 Original line number Diff line number Diff line /** * Defines comment schema and connects to database */ var mongoose = require('mongoose'), config = require('./config'); Comment = mongoose.model('Comment', new mongoose.Schema({ sdk: String, version: String, Loading Loading @@ -43,4 +48,6 @@ Meta = mongoose.model('Meta', new mongoose.Schema({ metaType: String })); mongoose.connect(config.mongoDb); mongoose.connect(config.mongoDb, function(err, ok) { console.log("Connected to DB") }); opt/comments-server-side/package.json +2 −3 Original line number Diff line number Diff line Loading @@ -4,10 +4,10 @@ "description": "Commenting backend for JSDuck Documentation", "author": "Nick Poudlen <nick@sencha.com>", "dependencies": { "express": "git://github.com/visionmedia/express.git", "express-namespace": "", "connect": "", "connect-mongo": "", "express": "", "express-namespace": "", "marked": "", "mongoose": "", "mysql": "", Loading @@ -17,4 +17,3 @@ "nodemailer": "" } } opt/comments-server-side/util.js +2 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,8 @@ var marked = require('marked'), _ = require('underscore'), sanitizer = require('sanitizer'), nodemailer = require("nodemailer"); nodemailer = require("nodemailer"), mongoose = require('mongoose'); /** * Converts Markdown-formatted comment text into HTML. Loading Loading
opt/comments-server-side/app.js +250 −246 Original line number Diff line number Diff line Loading @@ -19,10 +19,8 @@ * */ config = require('./config'); mongoose = require('mongoose'); var config = require('./config'); require('./database'); require('express-namespace'); var mysql = require('mysql'), client = mysql.createClient({ Loading @@ -32,67 +30,78 @@ var mysql = require('mysql'), database: config.db.dbName }), express = require('express'), connect = require('connect'), MongoStore = require('connect-session-mongo'), MongoStore = require('connect-mongo'), _ = require('underscore'), ForumUser = require('./ForumUser').ForumUser, forumUser = new ForumUser(client), util = require('./util'), crypto = require('crypto'); crypto = require('crypto'), mongoose = require('mongoose'); var app = express(); var app = express.createServer( app.configure(function() { // Headers for Cross Origin Resource Sharing (CORS) function (req, res, next) { app.use(function (req, res, next) { res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'POST, GET, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Accept'); next(); }, }); express.cookieParser(), app.use(express.cookieParser(config.sessionSecret)); // Hack to set session cookie if session ID is set as a URL param. // This is because not all browsers support sending cookies via CORS function(req, res, next) { if (req.query.sid) { app.use(function(req, res, next) { if (req.query.sid && req.query.sid != 'null') { var sid = req.query.sid.replace(/ /g, '+'); req.cookies = req.cookies || {}; req.cookies['sencha_docs'] = sid; req.sessionID = sid; req.signedCookies = req.signedCookies || {}; req.signedCookies['sencha_docs'] = sid; } next(); }, }); // Use MongoDB for session storage connect.session({ store: new MongoStore, secret: config.sessionSecret, key: 'sencha_docs' }), function(req, res, next) { app.use(express.session({ secret: config.sessionSecret, key: 'sencha_docs', store: new MongoStore({ url: exports.mongoDb + "/sessions" }) })); app.use(function(req, res, next) { // IE doesn't get content-type, so default to form encoded. if (!req.headers['content-type']) { req.headers['content-type'] = 'application/x-www-form-urlencoded'; } next(); }, express.bodyParser(), express.methodOverride() ); }); app.use(express.bodyParser()); app.use(express.methodOverride()); app.enable('jsonp callback'); }); // All URLs start with /auth app.namespace('/auth', function(){ app.configure('development', function(){ app.use(express.logger('dev')); app.use(express.errorHandler()); }); /** * Authentication */ app.get('/session', function(req, res) { app.get('/auth/session', function(req, res) { var result = req.session && req.session.user && forumUser.clientUser(req.session.user); res.json(result || false); }); app.post('/login', function(req, res){ app.post('/auth/login', function(req, res){ forumUser.login(req.body.username, req.body.password, function(err, result) { Loading @@ -114,7 +123,7 @@ app.namespace('/auth', function(){ }); // Remove session app.post('/logout', function(req, res){ app.post('/auth/logout', function(req, res){ req.session.user = null; res.json({ success: true }); }); Loading @@ -122,7 +131,7 @@ app.namespace('/auth', function(){ /** * Handles comment unsubscription requests. */ app.get('/unsubscribe/:subscriptionId', function(req, res) { app.get('/auth/unsubscribe/:subscriptionId', function(req, res) { Subscription.findOne({ _id: req.params.subscriptionId }, function(err, subscription) { if (err) throw(err); Loading @@ -143,18 +152,15 @@ app.namespace('/auth', function(){ }); }); }); /** * Commenting */ app.namespace('/auth/:sdk/:version', function(){ /** * Returns a list of comments for a particular target (eg class, guide, video) */ app.get('/comments', util.getCommentReads, function(req, res) { app.get('/auth/:sdk/:version/comments', util.getCommentReads, function(req, res) { if (!req.query.startkey) { res.json({error: 'Invalid request'}); Loading @@ -179,7 +185,7 @@ app.namespace('/auth/:sdk/:version', function(){ * `offset` and `limit` fields. I'd say it's a hack, but at least * it works for now. */ app.get('/comments_recent', util.getCommentReads, function(req, res) { app.get('/auth/:sdk/:version/comments_recent', util.getCommentReads, function(req, res) { var offset = parseInt(req.query.offset, 10) || 0; var limit = parseInt(req.query.limit, 10) || 100; var filter = { Loading Loading @@ -209,21 +215,21 @@ app.namespace('/auth/:sdk/:version', function(){ * Returns number of comments for each class/member, * and a list of classes/members into which the user has subscribed. */ app.get('/comments_meta', util.getCommentCounts, util.getCommentSubscriptions, function(req, res) { app.get('/auth/:sdk/:version/comments_meta', util.getCommentCounts, util.getCommentSubscriptions, function(req, res) { res.send({ comments: req.commentCounts, subscriptions: req.commentSubscriptions || [] }); }); /** * Returns an individual comment (used when editing a comment) */ app.get('/comments/:commentId', util.findComment, function(req, res) { app.get('/auth/:sdk/:version/comments/:commentId', util.findComment, function(req, res) { res.json({ success: true, content: req.comment.content }); }); /** * Creates a new comment */ app.post('/comments', util.requireLoggedInUser, function(req, res) { app.post('/auth/:sdk/:version/comments', util.requireLoggedInUser, function(req, res) { var target = JSON.parse(req.body.target); Loading Loading @@ -260,7 +266,7 @@ app.namespace('/auth/:sdk/:version', function(){ /** * Updates an existing comment (for voting or updating contents) */ app.post('/comments/:commentId', util.requireLoggedInUser, util.findComment, function(req, res) { app.post('/auth/:sdk/:version/comments/:commentId', util.requireLoggedInUser, util.findComment, function(req, res) { var voteDirection, comment = req.comment; Loading Loading @@ -288,7 +294,7 @@ app.namespace('/auth/:sdk/:version', function(){ /** * Deletes a comment */ app.post('/comments/:commentId/delete', util.requireLoggedInUser, util.findComment, util.requireOwner, function(req, res) { app.post('/auth/:sdk/:version/comments/:commentId/delete', util.requireLoggedInUser, util.findComment, util.requireOwner, function(req, res) { req.comment.deleted = true; req.comment.save(function(err, response) { res.send({ success: true }); Loading @@ -298,7 +304,7 @@ app.namespace('/auth/:sdk/:version', function(){ /** * Restores deleted comment */ app.post('/comments/:commentId/undo_delete', util.requireLoggedInUser, util.findComment, util.requireOwner, util.getCommentReads, function(req, res) { app.post('/auth/:sdk/:version/comments/:commentId/undo_delete', util.requireLoggedInUser, util.findComment, util.requireOwner, util.getCommentReads, function(req, res) { req.comment.deleted = false; req.comment.save(function(err, response) { res.send({ success: true, comment: util.scoreComments([req.comment], req)[0] }); Loading @@ -308,7 +314,7 @@ app.namespace('/auth/:sdk/:version', function(){ /** * Marks a comment 'read' */ app.post('/comments/:commentId/read', util.requireLoggedInUser, util.findCommentMeta, function(req, res) { app.post('/auth/:sdk/:version/comments/:commentId/read', util.requireLoggedInUser, util.findCommentMeta, function(req, res) { req.commentMeta.metaType = 'read'; req.commentMeta.save(function(err, response) { res.send({ success: true }); Loading @@ -318,14 +324,14 @@ app.namespace('/auth/:sdk/:version', function(){ /** * Get email subscriptions */ app.get('/subscriptions', util.getCommentSubscriptions, function(req, res) { app.get('/auth/:sdk/:version/subscriptions', util.getCommentSubscriptions, function(req, res) { res.json({ subscriptions: req.commentMeta.subscriptions }); }); /** * Subscibe / unsubscribe to a comment thread */ app.post('/subscribe', util.requireLoggedInUser, function(req, res) { app.post('/auth/:sdk/:version/subscribe', util.requireLoggedInUser, function(req, res) { var subscriptionBody = { sdk: req.params.sdk, Loading Loading @@ -354,8 +360,6 @@ app.namespace('/auth/:sdk/:version', function(){ }); }); }); var port = 3000; app.listen(port); console.log("Server started at port "+port+"..."); Loading
opt/comments-server-side/database.js +8 −1 Original line number Diff line number Diff line /** * Defines comment schema and connects to database */ var mongoose = require('mongoose'), config = require('./config'); Comment = mongoose.model('Comment', new mongoose.Schema({ sdk: String, version: String, Loading Loading @@ -43,4 +48,6 @@ Meta = mongoose.model('Meta', new mongoose.Schema({ metaType: String })); mongoose.connect(config.mongoDb); mongoose.connect(config.mongoDb, function(err, ok) { console.log("Connected to DB") });
opt/comments-server-side/package.json +2 −3 Original line number Diff line number Diff line Loading @@ -4,10 +4,10 @@ "description": "Commenting backend for JSDuck Documentation", "author": "Nick Poudlen <nick@sencha.com>", "dependencies": { "express": "git://github.com/visionmedia/express.git", "express-namespace": "", "connect": "", "connect-mongo": "", "express": "", "express-namespace": "", "marked": "", "mongoose": "", "mysql": "", Loading @@ -17,4 +17,3 @@ "nodemailer": "" } }
opt/comments-server-side/util.js +2 −1 Original line number Diff line number Diff line Loading @@ -2,7 +2,8 @@ var marked = require('marked'), _ = require('underscore'), sanitizer = require('sanitizer'), nodemailer = require("nodemailer"); nodemailer = require("nodemailer"), mongoose = require('mongoose'); /** * Converts Markdown-formatted comment text into HTML. Loading