From 6eb9af77e60566dfdad2546e5b65e35a714e8bce Mon Sep 17 00:00:00 2001 From: Baris Usakli Date: Wed, 10 Jul 2013 16:22:03 -0400 Subject: [PATCH] first pass at subfolder --- app.js | 18 +- package.json | 1 + public/src/ajaxify.js | 4 +- public/src/app.js | 7 +- public/src/templates.js | 11 +- public/templates/account.tpl | 2 +- public/templates/accountedit.tpl | 2 +- public/templates/category.tpl | 7 +- public/templates/followers.tpl | 2 +- public/templates/following.tpl | 2 +- public/templates/footer.tpl | 1 - public/templates/header.tpl | 28 ++-- public/templates/login.tpl | 2 +- public/templates/recent.tpl | 6 +- public/templates/register.tpl | 2 +- public/templates/reset.tpl | 2 +- public/templates/reset_code.tpl | 2 +- public/templates/topic.tpl | 2 +- public/templates/users.tpl | 2 +- src/categories.js | 2 +- src/user.js | 9 +- src/webserver.js | 277 ++++++++++++++++--------------- 22 files changed, 214 insertions(+), 177 deletions(-) diff --git a/app.js b/app.js index d74b7cf513..96ea6fee76 100644 --- a/app.js +++ b/app.js @@ -2,6 +2,7 @@ var fs = require('fs'), path = require('path'), utils = require('./public/src/utils.js'), + url = require('url'), args = {}; // Runtime environment @@ -21,6 +22,8 @@ fs.readFile(path.join(__dirname, 'config.json'), function(err, data) { global.config = JSON.parse(data); global.config.url = global.config.base_url + (global.config.use_port ? ':' + global.config.port : '') + '/'; global.config.upload_url = global.config.url + 'uploads/'; + + console.log('Info: Base Configuration OK.'); var meta = require('./src/meta.js'); @@ -71,11 +74,13 @@ fs.readFile(path.join(__dirname, 'config.json'), function(err, data) { default_categories = JSON.parse(default_categories); for (var category in default_categories) { + console.log(category); admin.categories.create(default_categories[category]); } }); - // Hardcoding uid 1 as an admin + + console.log('Info: Hardcoding uid 1 as an admin'); var user = require('./src/user.js'); user.makeAdministrator(1); } else { @@ -123,11 +128,17 @@ fs.readFile(path.join(__dirname, 'config.json'), function(err, data) { if (!secret) secret = utils.generateUUID(); if (!bcrypt_rounds) bcrypt_rounds = 10; + var urlObject = url.parse(base_url); + var relative_path = urlObject.pathname; + var host = urlObject.host; + var protocol = urlObject.protocol; + var fs = require('fs'), path = require('path'), config = { secret: secret, base_url: base_url, + relative_path: relative_path, port: port, use_port: use_port, upload_path: '/public/uploads/', @@ -162,10 +173,11 @@ fs.readFile(path.join(__dirname, 'config.json'), function(err, data) { // Client-side config fs.writeFile(path.join(__dirname, 'public', 'config.json'), JSON.stringify({ socket: { - address: base_url, + address: protocol + '//' + host, port: port }, - api_url: base_url + (use_port ? ':' + port : '') + '/api/' + api_url: protocol + '//' + host + (use_port ? ':' + port : '') + relative_path + '/api/', + relative_path: relative_path }, null, 4)); }); }); diff --git a/package.json b/package.json index 6ec3aa08cb..3ea57dc4a3 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "socket.io": "0.9.14", "redis": "0.8.3", "express": "3.2.0", + "express-namespace": "0.1.1", "connect": "2.7.6", "emailjs": "0.3.4", "cookie": "0.0.6", diff --git a/public/src/ajaxify.js b/public/src/ajaxify.js index 060373230f..d86225070e 100644 --- a/public/src/ajaxify.js +++ b/public/src/ajaxify.js @@ -38,12 +38,12 @@ var ajaxify = {}; } else if (templates[url]) { tpl_url = url; } - + if (templates.is_available(tpl_url) && !templates.force_refresh(tpl_url)) { if (quiet !== true) { window.history.pushState({ "url": url - }, url, "/" + url); + }, url, RELATIVE_PATH + '/' + url); } jQuery('#footer, #content').fadeOut(100); diff --git a/public/src/app.js b/public/src/app.js index d032a303b4..7007784a12 100644 --- a/public/src/app.js +++ b/public/src/app.js @@ -1,15 +1,17 @@ var socket, config, app = {}, - API_URL = null; + API_URL = null, + RELATIVE_PATH = null; // todo: cleanup,etc (function() { $.ajax({ - url: '/config.json?v=' + new Date().getTime(), + url: '/forum/config.json?v=' + new Date().getTime(), success: function(data) { API_URL = data.api_url; + RELATIVE_PATH = data.relative_path; config = data; socket = io.connect(config.socket.address + (config.socket.port ? ':' + config.socket.port : '')); @@ -244,6 +246,7 @@ var socket, } }, false); + $.getScript(RELATIVE_PATH + '/src/forum/footer.js'); addTouchEvents(); }); diff --git a/public/src/templates.js b/public/src/templates.js index 871ce28242..07080492a6 100644 --- a/public/src/templates.js +++ b/public/src/templates.js @@ -86,9 +86,12 @@ } function loadClient() { - jQuery.when(jQuery.getJSON('/templates/config.json'), jQuery.getJSON('/api/get_templates_listing')).done(function(config_data, templates_data) { + jQuery.when(jQuery.getJSON(RELATIVE_PATH + '/templates/config.json'), jQuery.getJSON(RELATIVE_PATH + '/api/get_templates_listing')).done(function(config_data, templates_data) { config = config_data[0]; available_templates = templates_data[0]; + + + templates.ready(); }); } @@ -131,7 +134,7 @@ var timestamp = new Date().getTime(); //debug if (!templates[tpl_url]) { - jQuery.get('/templates/' + tpl_url + '.tpl?v=' + timestamp, function(html) { + jQuery.get(RELATIVE_PATH + '/templates/' + tpl_url + '.tpl?v=' + timestamp, function(html) { var template = function() { this.toString = function() { return this.html; @@ -153,7 +156,10 @@ }()); (function() { + console.log(API_URL,api_url); jQuery.get(API_URL + api_url, function(data) { + + if(!data) { ajaxify.go('404'); return; @@ -170,6 +176,7 @@ function parse_template() { if (!templates[tpl_url] || !template_data) return; + template_data['relative_path'] = RELATIVE_PATH || global.config.relative_path; document.getElementById('content').innerHTML = templates[tpl_url].parse(template_data); diff --git a/public/templates/account.tpl b/public/templates/account.tpl index cc4e04a9bc..da49e47d71 100644 --- a/public/templates/account.tpl +++ b/public/templates/account.tpl @@ -101,4 +101,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/templates/accountedit.tpl b/public/templates/accountedit.tpl index e96b9b6d44..b58d0ab5ec 100644 --- a/public/templates/accountedit.tpl +++ b/public/templates/accountedit.tpl @@ -170,4 +170,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/templates/category.tpl b/public/templates/category.tpl index baa73ad197..3b192e00c2 100644 --- a/public/templates/category.tpl +++ b/public/templates/category.tpl @@ -73,7 +73,7 @@
- +
@@ -83,7 +83,7 @@
- +
@@ -94,4 +94,5 @@ - \ No newline at end of file + + \ No newline at end of file diff --git a/public/templates/followers.tpl b/public/templates/followers.tpl index 139a14dd56..45d973e898 100644 --- a/public/templates/followers.tpl +++ b/public/templates/followers.tpl @@ -41,4 +41,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/templates/following.tpl b/public/templates/following.tpl index a167182c8c..38b84c45d4 100644 --- a/public/templates/following.tpl +++ b/public/templates/following.tpl @@ -45,4 +45,4 @@ - + diff --git a/public/templates/footer.tpl b/public/templates/footer.tpl index d9c02f0d34..51d3b71df6 100644 --- a/public/templates/footer.tpl +++ b/public/templates/footer.tpl @@ -45,7 +45,6 @@ - diff --git a/public/templates/header.tpl b/public/templates/header.tpl index 667597b747..6cc5d0a350 100644 --- a/public/templates/header.tpl +++ b/public/templates/header.tpl @@ -9,27 +9,27 @@ - - + + - - - - - - + + + + + + - - - - + + + + - + diff --git a/public/templates/login.tpl b/public/templates/login.tpl index 4cf156f7a6..a3847fbb71 100644 --- a/public/templates/login.tpl +++ b/public/templates/login.tpl @@ -27,4 +27,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/templates/recent.tpl b/public/templates/recent.tpl index 1c8fbf8af9..aa4bb57255 100644 --- a/public/templates/recent.tpl +++ b/public/templates/recent.tpl @@ -26,8 +26,8 @@
-
- +
+

{topics.teaser_username}: {topics.teaser_text}

posted {topics.teaser_timestamp} ago
@@ -49,4 +49,4 @@
- \ No newline at end of file + \ No newline at end of file diff --git a/public/templates/register.tpl b/public/templates/register.tpl index 5a2cea9fc5..7b149091ef 100644 --- a/public/templates/register.tpl +++ b/public/templates/register.tpl @@ -20,4 +20,4 @@
- \ No newline at end of file + \ No newline at end of file diff --git a/public/templates/reset.tpl b/public/templates/reset.tpl index 3a1857a4f4..42d3d12f08 100644 --- a/public/templates/reset.tpl +++ b/public/templates/reset.tpl @@ -14,4 +14,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/templates/reset_code.tpl b/public/templates/reset_code.tpl index a37d4534df..700005b3f7 100644 --- a/public/templates/reset_code.tpl +++ b/public/templates/reset_code.tpl @@ -22,4 +22,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/templates/topic.tpl b/public/templates/topic.tpl index 9d716a1e3d..576afb828f 100644 --- a/public/templates/topic.tpl +++ b/public/templates/topic.tpl @@ -140,4 +140,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/templates/users.tpl b/public/templates/users.tpl index 8f6da1c8b2..3904e6db06 100644 --- a/public/templates/users.tpl +++ b/public/templates/users.tpl @@ -36,4 +36,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/src/categories.js b/src/categories.js index df390e4055..1d2575bfe1 100644 --- a/src/categories.js +++ b/src/categories.js @@ -309,7 +309,7 @@ var RDB = require('./redis.js'), } Categories.getCategories = function(cids, callback, current_user) { - if (cids.length === 0) { + if (!cids || cids.length === 0) { callback({'categories' : []}); return; } diff --git a/src/user.js b/src/user.js index 0c2ab2f73c..a80a10c873 100644 --- a/src/user.js +++ b/src/user.js @@ -14,10 +14,9 @@ var utils = require('./../public/src/utils.js'), User.create = function(username, password, email, callback) { username = username.trim(), email = email.trim(); - // @todo return a proper error? use node-validator? + // @todo use node-validator? if(!utils.isEmailValid(email) || !utils.isUserNameValid(username) || !utils.isPasswordValid(password)) { - console.log('Invalid email/username/password!'); - callback(null, 0); + callback('Invalid email/username/password!', 0); return; } @@ -25,13 +24,13 @@ var utils = require('./../public/src/utils.js'), User.exists(userslug, function(exists) { if(exists) { - callback(null, 0); + callback('Username taken!', 0); return; } User.isEmailAvailable(email, function(available) { if(!available) { - callback(null, 0); + callback('Email taken!', 0); return; } diff --git a/src/webserver.js b/src/webserver.js index 4c5d7ee007..d3a8b79224 100644 --- a/src/webserver.js +++ b/src/webserver.js @@ -1,4 +1,5 @@ var express = require('express'), + express_namespace = require('express-namespace'), WebServer = express(), server = require('http').createServer(WebServer), RedisStore = require('connect-redis')(express), @@ -26,16 +27,18 @@ var express = require('express'), app.build_header = function(res) { return templates['header'].parse({ - cssSrc: global.config['theme:src'] || '/vendor/bootstrap/css/bootstrap.min.css', + cssSrc: global.config['theme:src'] || global.config.relative_path + '/vendor/bootstrap/css/bootstrap.min.css', title: global.config['title'] || 'NodeBB', - csrf:res.locals.csrf_token + csrf:res.locals.csrf_token, + relative_path: global.config.relative_path }); }; // Middlewares app.use(express.favicon(path.join(__dirname, '../', 'public', 'favicon.ico'))); app.use(require('less-middleware')({ src: path.join(__dirname, '../', 'public') })); - app.use(express.static(path.join(__dirname, '../', 'public'))); + //app.use(express.static(path.join(__dirname, '../', 'public'))); + app.use(global.config.relative_path, express.static(path.join(__dirname, '../', 'public'))); app.use(express.bodyParser()); // Puts POST vars in request.body app.use(express.cookieParser()); // If you want to parse cookies (res.cookies) app.use(express.compress()); @@ -108,11 +111,7 @@ var express = require('express'), res.json('500', { error: err.message }); }); - auth.create_routes(app); - admin.create_routes(app); - userRoute.create_routes(app); - installRoute.create_routes(app); - testBed.create_routes(app); + app.create_route = function(url, tpl) { // to remove return ''; @@ -141,77 +140,156 @@ var express = require('express'), }()); // Complex Routes - app.get('/', function(req, res) { - categories.getAllCategories(function(returnData) { - res.send( - app.build_header(res) + - '\n\t' + - app.create_route('') + - templates['footer'] - ); - }, 0); - }); + app.namespace(global.config.relative_path, function() { - app.get('/topic/:topic_id/:slug?', function(req, res) { - var tid = req.params.topic_id; - if (tid.match('.rss')) { - fs.readFile('feeds/topics/' + tid, function (err, data) { - if (err) { - res.type('text').send(404, "Unable to locate an rss feed at this location."); + auth.create_routes(app); + admin.create_routes(app); + userRoute.create_routes(app); + installRoute.create_routes(app); + testBed.create_routes(app); + + app.get('/', function(req, res) { + console.log('going in home'); + categories.getAllCategories(function(returnData) { + res.send( + app.build_header(res) + + '\n\t' + + app.create_route('') + + templates['footer'] + ); + }, 0); + }); + + + app.get('/topic/:topic_id/:slug?', function(req, res) { + var tid = req.params.topic_id; + if (tid.match('.rss')) { + fs.readFile('feeds/topics/' + tid, function (err, data) { + if (err) { + res.type('text').send(404, "Unable to locate an rss feed at this location."); + return; + } + + res.type('xml').set('Content-Length', data.length).send(data); + }); + return; + } + + + var topic_url = tid + (req.params.slug ? '/' + req.params.slug : ''); + topics.getTopicWithPosts(tid, ((req.user) ? req.user.uid : 0), function(err, topic) { + if (err) return res.redirect('404'); + + res.send( + app.build_header(res) + + '\n\t' + + '\n\t' + + templates['footer'] + ); + }); + }); + + app.get('/category/:category_id/:slug?', function(req, res) { + var cid = req.params.category_id; + if (cid.match('.rss')) { + fs.readFile('feeds/categories/' + cid, function (err, data) { + if (err) { + res.type('text').send(404, "Unable to locate an rss feed at this location."); + return; + } + + res.type('xml').set('Content-Length', data.length).send(data); + }); + return; + } + + var category_url = cid + (req.params.slug ? '/' + req.params.slug : ''); + categories.getCategoryById(cid, 0, function(returnData) { + if(!returnData) { + res.redirect('404'); return; } - res.type('xml').set('Content-Length', data.length).send(data); + res.send( + app.build_header(res) + + '\n\t' + + '\n\t' + + templates['footer'] + ); }); - return; - } - - - var topic_url = tid + (req.params.slug ? '/' + req.params.slug : ''); - topics.getTopicWithPosts(tid, ((req.user) ? req.user.uid : 0), function(err, topic) { - if (err) return res.redirect('404'); - - res.send( - app.build_header(res) + - '\n\t' + - '\n\t' + - templates['footer'] - ); }); - }); - app.get('/category/:category_id/:slug?', function(req, res) { - var cid = req.params.category_id; - if (cid.match('.rss')) { - fs.readFile('feeds/categories/' + cid, function (err, data) { - if (err) { - res.type('text').send(404, "Unable to locate an rss feed at this location."); + app.get('/confirm/:code', function(req, res) { + res.send(app.build_header(res) + '' + templates['footer']); + }); + + app.get('/api/:method', api_method); + app.get('/api/:method/:id', api_method); + // ok fine MUST ADD RECURSION style. I'll look for a better fix in future but unblocking baris for this: + app.get('/api/:method/:id/:section?', api_method); + app.get('/api/:method/:id*', api_method); + + app.get('/cid/:cid', function(req, res) { + categories.getCategoryData(req.params.cid, function(data){ + if(data) + res.send(data); + else + res.send(404, "Category doesn't exist!"); + }); + }); + + app.get('/tid/:tid', function(req, res) { + topics.getTopicData(req.params.tid, function(data){ + if(data) + res.send(data); + else + res.send(404, "Topic doesn't exist!"); + }); + }); + + app.get('/pid/:pid', function(req, res) { + posts.getPostData(req.params.pid, function(data){ + if(data) + res.send(data); + else + res.send(404, "Post doesn't exist!"); + }); + }); + + + //START TODO: MOVE TO GRAPH.JS + + app.get('/graph/users/:username/picture', function(req, res) { + user.get_uid_by_username(req.params.username, function(uid) { + if (uid == null) { + res.json({ + status: 0 + }); return; } - - res.type('xml').set('Content-Length', data.length).send(data); + user.getUserField(uid, 'picture', function(picture) { + if (picture == null) res.redirect('http://www.gravatar.com/avatar/a938b82215dfc96c4cabeb6906e5f953&default=identicon'); + res.redirect(picture); + }); }); - return; - } - - var category_url = cid + (req.params.slug ? '/' + req.params.slug : ''); - categories.getCategoryById(cid, 0, function(returnData) { - if(!returnData) { - res.redirect('404'); - return; - } - res.send( - app.build_header(res) + - '\n\t' + - '\n\t' + - templates['footer'] - ); }); - }); - app.get('/confirm/:code', function(req, res) { - res.send(app.build_header(res) + '' + templates['footer']); + //END TODO: MOVE TO GRAPH.JS + + app.get('/test', function(req, res) { + + console.log('derp'); + user.get_userslugs_by_uids([1,2], function(data) { + res.send(data); + }); + + /* categories.getCategoryById(1,1, function(data) { + res.send(data); + },1);*/ + + }); + }); // These functions are called via ajax once the initial page is loaded to populate templates with data @@ -342,73 +420,10 @@ var express = require('express'), } } - app.get('/api/:method', api_method); - app.get('/api/:method/:id', api_method); - // ok fine MUST ADD RECURSION style. I'll look for a better fix in future but unblocking baris for this: - app.get('/api/:method/:id/:section?', api_method); - app.get('/api/:method/:id*', api_method); - - app.get('/cid/:cid', function(req, res) { - categories.getCategoryData(req.params.cid, function(data){ - if(data) - res.send(data); - else - res.send(404, "Category doesn't exist!"); - }); - }); - - app.get('/tid/:tid', function(req, res) { - topics.getTopicData(req.params.tid, function(data){ - if(data) - res.send(data); - else - res.send(404, "Topic doesn't exist!"); - }); - }); - - app.get('/pid/:pid', function(req, res) { - posts.getPostData(req.params.pid, function(data){ - if(data) - res.send(data); - else - res.send(404, "Post doesn't exist!"); - }); - }); + - app.get('/test', function(req, res) { - - console.log('derp'); - user.get_userslugs_by_uids([1,2], function(data) { - res.send(data); - }); - -/* categories.getCategoryById(1,1, function(data) { - res.send(data); - },1);*/ - - }); - - - //START TODO: MOVE TO GRAPH.JS - - app.get('/graph/users/:username/picture', function(req, res) { - user.get_uid_by_username(req.params.username, function(uid) { - if (uid == null) { - res.json({ - status: 0 - }); - return; - } - user.getUserField(uid, 'picture', function(picture) { - if (picture == null) res.redirect('http://www.gravatar.com/avatar/a938b82215dfc96c4cabeb6906e5f953&default=identicon'); - res.redirect(picture); - }); - }); - - }); - - //END TODO: MOVE TO GRAPH.JS + }(WebServer)); server.listen(config.port);