From 3c166e5bc69668dc7cef3fad8207c32c1a6d2f51 Mon Sep 17 00:00:00 2001 From: Denis Washington Date: Sun, 6 Oct 2013 18:51:35 +0200 Subject: [PATCH 1/4] Add "testing" environment settings to config.js.example If we omit the "testing" configuration, the unit tests won't work, which is extremely confusing. --- config.js.example | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/config.js.example b/config.js.example index 08ecf73..7a36cb3 100644 --- a/config.js.example +++ b/config.js.example @@ -65,3 +65,11 @@ exports.production = { // }*/ //] }; + +// Test suite settings +exports.testing = { + port: 19123, + xmppDomain: 'localhost', + xmppHost: '127.0.0.1', + xmppPort: 15222, +}; From d20d1a443ff4a94c52c5b03bb927e940e7454a17 Mon Sep 17 00:00:00 2001 From: Denis Washington Date: Sun, 6 Oct 2013 19:06:31 +0200 Subject: [PATCH 2/4] Make "npm install" work with Node.js v0.10 --- package.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index b2724f8..8e4018a 100644 --- a/package.json +++ b/package.json @@ -15,11 +15,11 @@ "dependencies": { "connect": "2.4.x", "express": "3.x", - "libxmljs": "0.5.x", - "ltx": "0.2.x", - "node-expat": "1.6.x", - "node-stringprep": "0.1.x", - "node-xmpp": "0.3.2", + "libxmljs": "~0.8.1", + "ltx": "~0.3.0", + "node-expat": "~2.0.0", + "node-stringprep": "~0.1.8", + "node-xmpp": "~0.6.3", "jwt-simple": "0.1.x", "iso8601": "1.1.1", "pubcontrol": "0.3.1", From 89189887b6855ad9a4c777b8ce593c640d4d8974 Mon Sep 17 00:00:00 2001 From: Denis Washington Date: Sun, 6 Oct 2013 19:07:12 +0200 Subject: [PATCH 3/4] Fix test suite --- src/metadata.js | 3 +- src/subscriptions.js | 23 +--- src/util/atom.js | 2 +- src/util/pubsub.js | 11 +- src/util/session.js | 4 +- test/metadata.js | 1 + test/session.js | 213 -------------------------------- test/subscriptions.js | 15 +++ test/support/xmpp_mockserver.js | 4 + 9 files changed, 39 insertions(+), 237 deletions(-) delete mode 100644 test/session.js diff --git a/src/metadata.js b/src/metadata.js index ba55085..0c1453f 100644 --- a/src/metadata.js +++ b/src/metadata.js @@ -41,7 +41,6 @@ exports.setup = function(app) { function getNodeMetadata(req, res) { var channel = req.params.channel; var node = req.params.node; - requestNodeMetadata(req, res, channel, node, function(reply) { var body = replyToJSON(reply); res.contentType('json'); @@ -86,7 +85,7 @@ function getOption(reply, name) { function setNodeMetadata(req, res) { var channel = req.params.channel; var node = req.params.node; - var fields = JSON.parse(req.body); + var fields = JSON.parse(req.body.toString() || '{}'); configureNode(req, res, channel, node, fields, function() { res.send(200); diff --git a/src/subscriptions.js b/src/subscriptions.js index 7d1b94f..28fec64 100644 --- a/src/subscriptions.js +++ b/src/subscriptions.js @@ -158,15 +158,15 @@ function extractSubscriptionCommand(body) { function subscribe(req, res, channel, node, callback) { var nodeId = pubsub.channelNodeId(channel, node); - var bareJid = req.user.split('/', 2)[0]; - var iq = pubsub.subscribeIq(nodeId, bareJid); + var jid = req.user; + var iq = pubsub.subscribeIq(nodeId, jid); api.sendQuery(req, res, iq, callback); } function unsubscribe(req, res, channel, node, callback) { var nodeId = pubsub.channelNodeId(channel, node); - var bareJid = req.user.split('/', 2)[0]; - var iq = pubsub.unsubscribeIq(nodeId, bareJid); + var jid = req.user; + var iq = pubsub.unsubscribeIq(nodeId, jid); api.sendQuery(req, res, iq, callback); } @@ -177,19 +177,8 @@ function getNodeSubscriptions(req, res) { var node = req.params.node; requestNodeAffiliations(req, res, channel, node, function(reply) { var body = replyToJSON(reply, 'node'); - if (!body[req.session.jid]) { - var nodeId = pubsub.channelNodeId(channel, node); - console.log(req.session.jid + " is not subscribed to " + nodeId + ", creating temporary subscription"); - req.session.subscribe(nodeId, function(sub) { - res.contentType('json'); - res.send(body); - }, function(errstr) { - res.send(500); - }); - } else { - res.contentType('json'); - res.send(body); - } + res.contentType('json'); + res.send(body); }); } diff --git a/src/util/atom.js b/src/util/atom.js index b78b3fe..e748cf3 100644 --- a/src/util/atom.js +++ b/src/util/atom.js @@ -174,7 +174,7 @@ exports.fromJSON = function(entry) { var content = ''; if (entry.content) { - content = escapeText(entry.content); + content = entry.content; } entrydoc.root(). node('content', content). diff --git a/src/util/pubsub.js b/src/util/pubsub.js index 2a95b71..5be42b6 100644 --- a/src/util/pubsub.js +++ b/src/util/pubsub.js @@ -186,7 +186,10 @@ exports.userSubscriptionsIq = function() { */ exports.subscribeIq = function(nodeId, jid, isTemp) { var query = iq({type: 'set'}); - query.c('subscribe', {node: nodeId, jid: jid}); + query.c('subscribe', { + node: nodeId, + jid: bareJid(jid) + }); if (isTemp) { var form = query.c('options'). c('x', {xmlns: 'jabber:x:data', type: 'submit'}); @@ -202,10 +205,14 @@ exports.subscribeIq = function(nodeId, jid, isTemp) { */ exports.unsubscribeIq = function(nodeId, jid) { return iq({type: 'set'}). - c('unsubscribe', {node: nodeId, jid: jid}). + c('unsubscribe', {node: nodeId, jid: bareJid(jid)}). root(); }; +function bareJid(jid) { + return (jid.indexOf('/') != -1) ? jid.split('/', 2)[0] : jid; +} + /** * Creates a Pub-Sub IQ which sets a node's configuration. */ diff --git a/src/util/session.js b/src/util/session.js index d176300..ad1a9b3 100644 --- a/src/util/session.js +++ b/src/util/session.js @@ -95,7 +95,7 @@ function createSession(req, res, next) { // FIXME: Checking the error type bassed on the error message // is fragile, but this is the only information that node-xmpp // gives us. - console.log(err); + console.error(err); sessionCache.remove(req.credentials); for (var n = 0; n < session.waitingReqs.length; ++n) { var wr = session.waitingReqs[n]; @@ -126,7 +126,7 @@ function xmppConnectionOptions(req) { jid: '@' + domain, host: host, port: port, - preferredSaslMechanism: 'ANONYMOUS' + //preferredSaslMechanism: 'ANONYMOUS' }; } } diff --git a/test/metadata.js b/test/metadata.js index 02ea520..60c3ee7 100644 --- a/test/metadata.js +++ b/test/metadata.js @@ -213,6 +213,7 @@ describe('Node Metadata', function() { res.statusCode.should.equal(200); delete options.body; + delete options.method; tutil.get(options, function(res, body) { res.statusCode.should.equal(200); var metadata = JSON.parse(body); diff --git a/test/session.js b/test/session.js deleted file mode 100644 index 610f6af..0000000 --- a/test/session.js +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Copyright 2012 Denis Washington - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// test/session.js: -// Tests session management. - -var should = require('should'); -var xml = require('libxmljs'); -var atom = require('../src/util/atom'); -var config = require('../src/util/config'); -var tutil = require('./support/testutil'); - -// See xmpp_mockserver.js -var mockConfig = { - users: { - 'alice': 'alice', - 'bob': 'bob' - }, - stanzas: { - '\ - \ - \ - \ - ': - '\ - \ - \ - \ - \ - foo\ - bar\ - \ - \ - \ - \ - ', - - '\ - \ - \ - \ - ': - '\ - \ - \ - \ - \ - bar\ - baz\ - \ - \ - \ - \ - ' - } -}; - -describe('Session ID', function() { - - before(function(done) { - tutil.startHttpServer(function() { - tutil.mockXmppServer(mockConfig, done); - }); - }); - - it('should be returned on authenicated requests', function(done) { - var options = { - path: '/public@localhost/content/posts', - auth: 'alice@localhost:alice' - }; - tutil.get(options, function(res, body) { - res.statusCode.should.equal(200); - should.exist(res.headers['x-session-id']); - done(); - }).on('error', done); - }); - - it('should also be returned when username is unqualified', function(done) { - var options = { - path: '/public@localhost/content/posts', - auth: 'alice:alice' - }; - tutil.get(options, function(res, body) { - res.statusCode.should.equal(200); - should.exist(res.headers['x-session-id']); - done(); - }).on('error', done); - }); - - it('should not be returned on anonymous requests', function(done) { - var options = { - path: '/public@localhost/content/posts', - }; - tutil.get(options, function(res) { - res.statusCode.should.equal(200); - should.not.exist(res.headers['x-session-id']); - done(); - }).on('error', done); - }); - - it('should allow second request without re-authenication', function(done) { - var options = { - path: '/private@localhost/content/posts', - auth: 'alice@localhost/http:alice' - }; - tutil.get(options, function(res) { - delete options.auth; - options.headers = {'x-session-id': res.headers['x-session-id']}; - tutil.get(options, function(res2) { - res2.statusCode.should.equal(200); - done(); - }).on('error', done); - }).on('error', done); - }); - - it('should remain the same after the first request', function(done) { - var options = { - path: '/private@localhost/content/posts', - auth: 'alice@localhost/http:alice' - }; - tutil.get(options, function(res) { - var sessionId = res.headers['x-session-id']; - options.headers = {'x-session-id': sessionId}; - tutil.get(options, function(res2) { - res2.headers['x-session-id'].should.equal(sessionId); - done(); - }).on('error', done);; - }).on('error', done); - }); - - it('should differ between users', function(done) { - var aliceOptions = { - path: '/public@localhost/content/posts', - auth: 'alice@localhost:alice' - }; - tutil.get(aliceOptions, function(res) { - var bobOptions = { - path: '/public@localhost/content/posts', - auth: 'bob@localhost:bob' - }; - tutil.get(bobOptions, function(res2) { - var aliceSessionId = res.headers['x-session-id'] - var bobSessionId = res2.headers['x-session-id']; - aliceSessionId.should.not.equal(bobSessionId); - done(); - }).on('error', done);; - }).on('error', done); - }); - - it('should expire', function(done) { - this.timeout(0); - var options = { - path: '/private@localhost/content/posts', - auth: 'alice@localhost/http:alice' - }; - tutil.get(options, function(res) { - setTimeout(function() { - delete options.auth; - options.headers = { - 'x-session-id': res.headers['x-session-id'] - }; - tutil.get(options, function(res2) { - res2.statusCode.should.equal(401); - done(); - }).on('error', done); - }, config.sessionExpirationTime * 1000 + 100); - }).on('error', done); - }); - - it('should be renewed on each request', function(done) { - this.timeout(0); - var options = { - path: '/private@localhost/content/posts', - auth: 'alice@localhost/http:alice' - }; - tutil.get(options, function(res) { - var sessionId = res.headers['x-session-id']; - delete options.auth; - options.headers = {'x-session-id': sessionId}; - setTimeout(function() { - tutil.get(options, function(res2) { - res2.statusCode.should.equal(200); - res2.headers['x-session-id'].should.equal(sessionId); - setTimeout(function() { - tutil.get(options, function(res3) { - res3.statusCode.should.equal(200); - res3.headers['x-session-id'].should.equal(sessionId); - done(); - }).on('error', done); - }, config.sessionExpirationTime * 1000 * 0.75); - }).on('error', done); - }, config.sessionExpirationTime * 1000 * 0.75); - }).on('error', done); - }); - - after(function() { - tutil.end(); - }); - -}); diff --git a/test/subscriptions.js b/test/subscriptions.js index f06216a..e5f042a 100644 --- a/test/subscriptions.js +++ b/test/subscriptions.js @@ -29,6 +29,21 @@ var mockConfig = { }, stanzas: { // Get own subscriptions + affiliations + '\ + \ + \ + \ + ': + '\ + \ + \ + \ + \ + \ + \ + ', '\ \ \ diff --git a/test/support/xmpp_mockserver.js b/test/support/xmpp_mockserver.js index 53b223f..f952bc1 100644 --- a/test/support/xmpp_mockserver.js +++ b/test/support/xmpp_mockserver.js @@ -121,6 +121,10 @@ function checkAuth(user, password, callback) { } function handleStanza(client, stanza) { + if (stanza.name == 'presence') { + return; + } + var action = findMatchingRule(stanza); if (!action) { console.error('No rule for handling stanza ' + stanza.toString()); From dba6440ff1506446e641f396af158680789dd533 Mon Sep 17 00:00:00 2001 From: Denis Washington Date: Mon, 7 Oct 2013 07:20:22 +0200 Subject: [PATCH 4/4] Use node-xmpp 0.7.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8e4018a..7fad7ba 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "ltx": "~0.3.0", "node-expat": "~2.0.0", "node-stringprep": "~0.1.8", - "node-xmpp": "~0.6.3", + "node-xmpp": "~0.7.0", "jwt-simple": "0.1.x", "iso8601": "1.1.1", "pubcontrol": "0.3.1",