Skip to content

Commit

Permalink
POST /:channel/subscribers/:node endpoint created
Browse files Browse the repository at this point in the history
This API endpoint's purpose is to allow affiliation changes to existing
subscriptions to a given node.
  • Loading branch information
guilhermesgb committed Jul 16, 2013
1 parent cd04ead commit 1152658
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
51 changes: 51 additions & 0 deletions src/subscriptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ exports.setup = function(app) {
app.get('/:channel/subscribers/:node',
session.provider,
getNodeSubscriptions);
app.post('/:channel/subscribers/:node',
session.provider,
changeNodeSubscriptions);
};

//// GET /subscribed ///////////////////////////////////////////////////////////
Expand Down Expand Up @@ -171,3 +174,51 @@ function requestNodeAffiliations(req, res, channel, node, callback) {
var iq = pubsub.nodeAffiliationsIq(nodeId);
api.sendQuery(req, res, iq, callback);
}

//// POST /<channel>/subscribers/<node> //////////////////////////////////////////////////////////

function changeNodeSubscriptions(req, res) {
if (!req.user) {
api.sendUnauthorized(res);
return;
}

var channel = req.params.channel;
var node = req.params.node;

var nodeId = pubsub.channelNodeId(channel, node);
var newSubscribedAffiliations = [];

try {

var propertyNames = Object.getOwnPropertyNames(req.body);

This comment has been minimized.

Copy link
@rodrigods

rodrigods Jul 17, 2013

Contributor

you can just do:

for (var key in req.body) {

}

for ( var i=0; i<propertyNames.length; i++ ){

var key = propertyNames[i];

This comment has been minimized.

Copy link
@rodrigods

rodrigods Jul 17, 2013

Contributor

we need to send something like [email protected]/node ? Why don't just the channel jid ([email protected])?

This comment has been minimized.

Copy link
@guilhermesgb

guilhermesgb Jul 17, 2013

Author Member

Oops, you're right. I meant to construct affiliation tags like this one, for example:

 <affiliation jid="[email protected]" affiliation="publisher"/> 
var subscribedChannel = key.split('/', 2)[0];
var subscribedNode = key.split('/', 2)[1];
var affiliation = body[key];

if ( affiliation != "member" && affiliation != "publisher" && affiliation != "moderator" && affiliation != "outcast" ){

This comment has been minimized.

Copy link
@rodrigods

rodrigods Jul 17, 2013

Contributor

just add a method here: isValidAffiliation(affiliation)

continue;
}

//TODO
//Also filter out from newSubscribedAffiliations those channel jids which aren't actually subscribed to this node.
//Probably by performing a getNodeSubscriptions and comparing the results with the new affiliation information given by the user

newSubscribedAffiliations.push({
'jid' : pubsub.channelNodeId(subscribedChannel, subscribedNode),

This comment has been minimized.

Copy link
@rodrigods

rodrigods Jul 17, 2013

Contributor

isn't this "jid" only "subscribedChannel"?

'affiliation' : affiliation
});
}

} catch (e) {
res.send(400);
}

api.sendQuery(req, res, pubsub.changeNodeAffiliationsIq(nodeId, newSubscribedAffiliations), function(){
res.send(200);
});

}
17 changes: 17 additions & 0 deletions src/util/pubsub.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,23 @@ exports.nodeAffiliationsIq = function(nodeId, item) {
root();
};

/**
* Creates a Pub-Sub <affiliations/> IQ with multiple <affiliation> tags,
* each composed by a jid of a subscribing channel and its new type of affiliation.
* The <subscribedJIDAndAffiliation> parameter must be an array of entries in the format:
* {'jid' : 'jid_val', 'affiliation' : 'affiliation_type'}
*/
exports.changeNodeAffiliationsIq = function(nodeId, subscribedJIDAndAffiliation) {
var iqBody = iq({type : 'set'}, exports.ownerNS).
c('affiliations', {node: nodeId});

for ( var i=0; i<subscribedJIDAndAffiliation.length; i++ ){
iqBody.c('affiliation', subscribedJIDAndAffiliation[i]);
}

return iqBody.root();
};

/**
* Creates a Pub-Sub <subscribe/> IQ, which subscribes to a node.
*/
Expand Down

3 comments on commit 1152658

@guilhermesgb
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, someone code-review and validate my work.

I took a guess, based on https://buddycloud.org/wiki/XMPP_XEP#Retrieve_followers, that the Pub-Sub stanza to change affiliation roles of the followers of a node would be something like this:

<iq type="set" from to> 
  <pubsub xmlns="http://jabber.org/protocol/pubsub#owner"> 
    <affiliations node="/user/[email protected]/posts">
      <affiliation jid="[email protected]" affiliation="moderator"/> 
      <affiliation jid="[email protected]" affiliation="moderator"/> 
      <affiliation jid="[email protected]" affiliation="publisher"/> 
      <affiliation jid="[email protected]" affiliation="member"/> 
      <affiliation jid="[email protected]" affiliation="member"/> 
      <affiliation jid="[email protected]" affiliation="outcast"/> 
      <affiliation jid="[email protected]" affiliation="outcast"/> 
      <affiliation jid="[email protected]" affiliation="outcast"/> 
    </affiliations> 
  </pubsub> 
</iq>

@rodrigods
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, there is only small fixes =)

Please, also test it locally.

@lloydwatkin
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will only work if you are the node owner/moderator though, otherwise the nodejs server will fallback to giving you a list of the current user's affiliations (same with subscriptions I believe). The java server does this differently and exposes this data whether you are the owner or not. I raised an issue for this here: buddycloud/deprecated-buddycloud-server#123

Please sign in to comment.