Skip to content
This repository has been archived by the owner on Feb 11, 2020. It is now read-only.

Allow published messages on an unauthorised publish topic to be pubacked #638

Merged
merged 5 commits into from
May 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 11 additions & 2 deletions examples/Server_With_All_Interfaces-Settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,20 @@ var authenticate = function (client, username, password, callback) {
}

var authorizePublish = function (client, topic, payload, callback) {
callback(null, true);
var auth = true;
// set auth to :
// true to allow
// false to deny and disconnect
// 'ignore' to puback but not publish msg.
callback(null, auth);
}

var authorizeSubscribe = function (client, topic, callback) {
callback(null, true);
var auth = true;
// set auth to :
// true to allow
// false to deny
callback(null, auth);
}

var server = new mosca.Server(moscaSetting);
Expand Down
15 changes: 13 additions & 2 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,7 @@ Client.prototype.handleSubscribe = function(packet) {
Client.prototype.handleAuthorizePublish = function(err, success, packet) {
var that = this;

// if err is passed, or success is false or undefined, terminate the connection
if (err || !success) {
if (!this._closed && !this._closing) {
that.close(null, (err && err.message) || "publish not authorized");
Expand All @@ -534,13 +535,23 @@ Client.prototype.handleAuthorizePublish = function(err, success, packet) {
packet.payload = success;
}

that.server.publish(packet, that, function() {
var dopuback = function() {
if (packet.qos === 1 && !(that._closed || that._closing)) {
that.connection.puback({
messageId: packet.messageId
});
}
});
};


// if success is passed as 'ignore', ack but don't publish.
if (success !== 'ignore'){
// publish message
that.server.publish(packet, that, dopuback);
} else {
// ignore but acknowledge message
dopuback();
}
};

/**
Expand Down
104 changes: 104 additions & 0 deletions test/abstract_server.js
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,110 @@ module.exports = function(moscaSettings, createConnection) {
});
});


// tests for local authorizePublish, with 'ignore' return
var authorizePublishIgnore = function(client, topic, payload, callback) {
var auth = true;
if (topic === 'authignore'){
auth = 'ignore';
}
if (topic === 'authfalse'){
auth = false;
}

callback(null, auth);
}

it("should not call onPublished on publish to topic where auth='ignore'", function(done) {
var onPublishedCalled = false;
var clientId;
var count = 0;

instance.authorizePublish = authorizePublishIgnore;
instance.published = function(packet, serverClient, callback) {
onPublishedCalled = true;
expect(packet.topic).to.be.equal("hello");
expect(packet.payload.toString().toString()).to.be.equal("some data");
expect(serverClient.id).to.be.equal(clientId);

callback();
};

buildAndConnect(done, function(client) {
clientId = client.opts.clientId;

client.publish({
messageId: 42,
topic: "authignore",
payload: "some data to ignore",
qos: 1
});
client.publish({
messageId: 43,
topic: "hello",
payload: "some data",
qos: 1
});

// auth='ignore' should puback, but not publish
client.on("puback", function() {
count++
// on second call, onPublished should be true
if(count === 2){
expect(onPublishedCalled).to.eql(true);
client.disconnect();
}
});
});
});

it("should disconnect client on publish to topic where auth=false", function(done) {
var onPublishedCalled = false;
var clientId;
var count = 0;
var timer;

instance.authorizePublish = authorizePublishIgnore;
instance.published = function(packet, serverClient, callback) {
onPublishedCalled = true;
expect(packet.topic).to.be.equal("should not have published");
callback();
};

buildAndConnect(done, function(client) {
clientId = client.opts.clientId;

client.publish({
messageId: 42,
topic: "authfalse",
payload: "some data to cause close",
qos: 1
});

// if after 2 seconds, we've not closed
timer = setTimeout(function(){
var test = false;
expect(count).to.eql(0);
expect(test).to.eql(true);
client.disconnect();
}, 2000);

// auth=false should NOT puback
client.on("puback", function() {
expect(onPublishedCalled).to.eql(false);
count++;
expect(count).to.eql(0);
client.disconnect();
});
client.on("close", function() {
expect(onPublishedCalled).to.eql(false);
expect(count).to.eql(0);
client.disconnect();
clearTimeout(timer);
});
});
});

it("should emit an event when a new client is connected", function(done) {
buildClient(done, function(client) {

Expand Down