Commit 1a2bfabb authored by Rene Saarsoo's avatar Rene Saarsoo
Browse files

Move comments server code to another repository.

The comments server is now available at:

    https://github.com/senchalabs/jsduck-comments

The comments server is quite a separate app so it's better maintained
as a completely separate project.
parent de8d1285
Loading
Loading
Loading
Loading
+0 −9
Original line number Diff line number Diff line
@@ -14,15 +14,6 @@ RSpec::Core::RakeTask.new(:spec) do |spec|
  spec.pattern = "spec/**/*_spec.rb"
end

desc "Run Jasmine specs for comments backend"
task :jasmine do
  # Initialize database with test data
  system("cd comments/; node load_test_db.js")

  # run jasmine tests against that database
  system("node comments/node_modules/jasmine-node/lib/jasmine-node/cli.js comments/spec/")
end

def load_sdk_vars
  if File.exists?("sdk-vars.rb")
    require "./sdk-vars.rb"

comments/.gitignore

deleted100644 → 0
+0 −2
Original line number Diff line number Diff line
config.js
node_modules

comments/app.js

deleted100644 → 0
+0 −253
Original line number Diff line number Diff line
var express = require('express');
var MySQLStore = require('connect-mysql-session')(express);
var config = require('./config');
var Request = require('./lib/request');
var Auth = require('./lib/auth');
var ApiAdapter = require('./lib/api_adapter');

var app = express();

app.configure(function() {
    // Headers for Cross Origin Resource Sharing (CORS)
    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();
    });

    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
    app.use(function(req, res, next) {
        if (req.query.sid && req.query.sid != 'null') {
            var sid = req.query.sid.replace(/ /g, '+');
            req.sessionID = sid;
            req.signedCookies = req.signedCookies || {};
            req.signedCookies['sencha_docs'] = sid;
        }
        next();
    });

    // Use MongoDB for session storage
    app.use(express.session({
        secret: config.sessionSecret,
        key: 'sencha_docs',
        store: new MySQLStore(
            config.mysql.database,
            config.mysql.user,
            config.mysql.password,
            {logging: false}
        )
    }));

    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();
    });

    app.use(express.bodyParser());
    app.use(express.methodOverride());

    app.enable('jsonp callback');

    app.use(express.logger('dev'));
});

// Authentication

// Old version for backwards compat.
app.get('/auth/session', function(req, res) {
    new Request(req).getUser(function(user) {
        if (user) {
            res.json({
                userName: user.username,
                mod: user.moderator
            });
        }
        else {
            res.json(false);
        }
    });
});

// New version.
app.get('/auth/session_new', function(req, res) {
    new Request(req).getUser(function(user) {
        if (user) {
            var json = ApiAdapter.userToJson(user);
            json.sessionID = req.sessionID;
            res.json(json);
        }
        else {
            res.json({sessionID: req.sessionID});
        }
    });
});

app.post('/auth/login', Auth.attemptLogin, function(req, res) {
    new Request(req).getUser(function(user) {
        var json = ApiAdapter.userToJson(user);
        json.sessionID = req.sessionID;
        json.success = true;
        res.json(json);
    });
});

app.post('/auth/logout', Auth.doLogout, function(req, res) {
    res.json({ success: true });
});


// Requests for Comments

// Returns n most recent comments.
app.get('/auth/:sdk/:version/comments_recent', function(req, res) {
    var query = {
        offset: parseInt(req.query.offset, 10),
        limit: parseInt(req.query.limit, 10),
        orderBy: req.query.sortByScore ? "vote" : "created_at",
        hideCurrentUser: req.query.hideCurrentUser,
        hideRead: req.query.hideRead,
        username: req.query.username,
        targetId: req.query.targetId,
        tagname: req.query.tagname
    };
    new Request(req).getRecentComments(query, function(comments) {
        res.json(comments);
    });
});

// Returns top users (with most upvotes or with most comments).
app.get('/auth/:sdk/:version/users', function(req, res) {
    new Request(req).getTopUsers(req.query.sortBy, function(users) {
        res.json({ success: true, data: users });
    });
});

// Returns the most commented targets.
app.get('/auth/:sdk/:version/targets', function(req, res) {
    new Request(req).getTopTargets(function(targets) {
        res.json({ success: true, data: targets });
    });
});

// Returns the most used tags.
app.get('/auth/:sdk/:version/tags', function(req, res) {
    new Request(req).getTopTags(function(tags) {
        res.send({ success: true, data: tags });
    });
});

// Returns number of comments for each class/member,
// and when user is logged in, all his subscriptions.
app.get('/auth/:sdk/:version/comments_meta', function(req, res) {
    var r = new Request(req);
    r.getCommentCountsPerTarget(function(counts) {
        r.getSubscriptions(function(subs) {
            res.json({ comments: counts, subscriptions: subs });
        });
    });
});

// Returns a list of comments for a particular target (eg class, guide, video)
app.get('/auth/:sdk/:version/comments', Auth.hasStartKey, function(req, res) {
    new Request(req).getComments(req.query.startkey, function(comments) {
        res.json(comments);
    });
});

// Adds new comment
app.post('/auth/:sdk/:version/comments', Auth.isLoggedIn, function(req, res) {
    new Request(req).addComment(req.body.target, req.body.comment, req.body.url, function(comment) {
        res.json({ id: comment._id, comment: comment, success: true });
    });
});

// Returns plain markdown content of individual comment (used when editing a comment)
app.get('/auth/:sdk/:version/comments/:commentId', function(req, res) {
    new Request(req).getComment(req.params.commentId, function(comment) {
        res.json({ success: true, content: comment.content });
    });
});

// Updates an existing comment (for voting or updating contents)
app.post('/auth/:sdk/:version/comments/:commentId', Auth.isLoggedIn, function(req, res) {
    if (req.body.vote) {
        Auth.canVote(req, res, function() {
            new Request(req).vote(req.params.commentId, req.body.vote, function(direction, total) {
                res.json({
                    success: true,
                    direction: direction,
                    total: total
                });
            });
        });
    }
    else {
        Auth.canModify(req, res, function() {
            new Request(req).updateComment(req.params.commentId, req.body.content, function(comment) {
                res.json({ success: true, content: comment.contentHtml });
            });
        });
    }
});

// Deletes a comment
app.post('/auth/:sdk/:version/comments/:commentId/delete', Auth.isLoggedIn, Auth.canModify, function(req, res) {
    new Request(req).setDeleted(req.params.commentId, true, function() {
        res.send({ success: true });
    });
});

// Restores a deleted comment
app.post('/auth/:sdk/:version/comments/:commentId/undo_delete', Auth.isLoggedIn, Auth.canModify, function(req, res) {
    var r = new Request(req);
    r.setDeleted(req.params.commentId, false, function() {
        r.getComment(req.params.commentId, function(comment) {
            res.send({ success: true, comment: comment });
        });
    });
});

// Tags a comment
app.post('/auth/:sdk/:version/comments/:commentId/add_tag', Auth.isLoggedIn, Auth.isModerator, function(req, res) {
    new Request(req).addTag(req.params.commentId, req.body.tagname, function() {
        res.send({ success: true });
    });
});

// Removes tag from a comment
app.post('/auth/:sdk/:version/comments/:commentId/remove_tag', Auth.isLoggedIn, Auth.isModerator, function(req, res) {
    new Request(req).removeTag(req.params.commentId, req.body.tagname, function() {
        res.send({ success: true });
    });
});

// Marks a comment 'read'
app.post('/auth/:sdk/:version/comments/:commentId/read', Auth.isLoggedIn, function(req, res) {
    new Request(req).markRead(req.params.commentId, function() {
        res.send({ success: true });
    });
});

// Returns all subscriptions for logged in user
app.get('/auth/:sdk/:version/subscriptions', function(req, res) {
    new Request(req).getSubscriptions(function(subs) {
        res.json({ subscriptions: subs });
    });
});

// Subscibe / unsubscribe to a comment thread
app.post('/auth/:sdk/:version/subscribe', Auth.isLoggedIn, function(req, res) {
    new Request(req).changeSubscription(req.body.target, req.body.subscribed === 'true', function() {
        res.send({ success: true });
    });
});

app.listen(config.port);
console.log("Server started at port "+config.port+"...");

comments/config.example.js

deleted100644 → 0
+0 −41
Original line number Diff line number Diff line

module.exports = {
    sessionSecret: 'blahblahblah',
    port: 3000,

    // local comments database
    mysql: {
        user: "",
        password: "",
        database: "comments",
        host: "localhost"
    },

    // Sencha Forum database
    forumDb: {
        user: '',
        password: '',
        host: '',
        database: ''
    },

    // The database to run jasmine unit tests in
    testDb: {
        user: "",
        password: "",
        database: "comments_test",
        host: "localhost"
    },

    // Config for nodemailer
    email: {
        from: "Sencha Documentation <no-reply@sencha.com>",
        config: {
            host: 'localhost',
            port: 25
        }
    },

    // old MongoDB database
    mongoDb: 'mongodb://localhost:27017/comments'
};

comments/generate_tags.js

deleted100644 → 0
+0 −47
Original line number Diff line number Diff line
// Generates tags "Fixed internally" and "Fixed in 4.1"
// based on the contents of comments.

var mysql = require("mysql");
var DbFacade = require('./lib/db_facade');
var Comments = require('./lib/comments');
var config = require('./config.js');

var db = new DbFacade(mysql.createConnection(config.mysql));

function loopInSequence(arr, callback, eventually) {
    var i = -1;
    function next() {
        i++;
        if (i < arr.length) {
            callback(arr[i], next);
        }
        else {
            eventually();
        }
    }
    next();
}

function addTags(domain, tagname, callback) {
    console.log("Adding '"+tagname+"' tags for "+domain);
    var comments = new Comments(db, domain);
    db.query("SELECT id FROM full_comments WHERE content LIKE '%"+tagname+"%' AND domain = ?", [domain], function(err, rows) {
        if (err) {
            throw err;
        }

        var i = 0;
        loopInSequence(rows, function(row, next) {
            console.log(++i);
            comments.addTag({
                user_id: 3,
                comment_id: row.id,
                tagname: tagname
            }, next);
        }, callback);
    });
}

loopInSequence(["Fixed internally", "Fixed in 4.1"], function(tagname, next) {
    addTags("ext-js-4", tagname, next);
}, process.exit.bind(process));
 No newline at end of file
Loading