Webhooks: block multiple subscriptions to the same callback URL

Will allow only one subscription to a given callback URL. If trying to
subscribe again to the same URL, will return success but with a message
saying the callback URL is duplicated, very similar to the response of
create when called multiple times.
This commit is contained in:
Leonardo Crauss Daronco 2014-11-11 16:56:15 -02:00
parent 6fc50f0a7e
commit e070f3c5c5
3 changed files with 29 additions and 12 deletions

View File

@ -47,6 +47,13 @@ config.api.responses.subscribeSuccess = (id) ->
</response>" </response>"
config.api.responses.subscribeFailure = config.api.responses.subscribeFailure =
config.api.responses.failure("subscribeEventError", "An error happened while storing your subscription. Check the logs.") config.api.responses.failure("subscribeEventError", "An error happened while storing your subscription. Check the logs.")
config.api.responses.subscribeDuplicated = (id) ->
"<response> \
<returncode>SUCCESS</returncode> \
<subscriptionID>#{id}</subscriptionID> \
<messageKey>duplicateWarning</messageKey> \
<message>There is already a subscription for this callback URL.</message>
</response>"
config.api.responses.unsubscribeSuccess = config.api.responses.unsubscribeSuccess =
"<response> \ "<response> \

View File

@ -26,11 +26,10 @@ module.exports = class Hook
destroySync: -> destroySync: ->
Hook.destroySync @id Hook.destroySync @id
# TODO: review # mapFromRedis: (redisData) ->
mapFromRedis: (redisData) -> # @callbackURL = redisData?.callbackURL
@callbackURL = redisData?.callbackURL # @externalMeetingID = redisData?.externalMeetingID
@externalMeetingID = redisData?.externalMeetingID # @id = redisData?.subscriptionID
@id = redisData?.subscriptionID
# Puts a new message in the queue. Will also trigger a processing in the queue so this # Puts a new message in the queue. Will also trigger a processing in the queue so this
# message might be processed instantly. # message might be processed instantly.
@ -60,12 +59,16 @@ module.exports = class Hook
@_processQueue() # go to the next message @_processQueue() # go to the next message
@addSubscription = (callbackURL, meetingID=null, callback) -> @addSubscription = (callbackURL, meetingID=null, callback) ->
hook = new Hook() hook = Hook.findByCallbackURLSync(callbackURL)
hook.id = nextId++ if hook?
hook.callbackURL = callbackURL callback?(new Error("There is already a subscription for this callback URL"), hook)
hook.externalMeetingID = meetingID else
hook.saveSync() hook = new Hook()
callback?(null, hook) hook.id = nextId++
hook.callbackURL = callbackURL
hook.externalMeetingID = meetingID
hook.saveSync()
callback?(null, hook)
@removeSubscription = (subscriptionID, callback) -> @removeSubscription = (subscriptionID, callback) ->
hook = Hook.getSync(subscriptionID) hook = Hook.getSync(subscriptionID)
@ -106,3 +109,8 @@ module.exports = class Hook
for id of db for id of db
delete db[id] delete db[id]
db = {} db = {}
@findByCallbackURLSync = (callbackURL) ->
for id of db
if db[id].callbackURL is callbackURL
return db[id]

View File

@ -42,7 +42,9 @@ module.exports = class WebServer
respondWithXML(res, config.api.responses.missingParamCallbackURL) respondWithXML(res, config.api.responses.missingParamCallbackURL)
else else
Hook.addSubscription callbackURL, meetingID, (error, hook) -> Hook.addSubscription callbackURL, meetingID, (error, hook) ->
if hook? if error? # the only error for now is for duplicated callbackURL
msg = config.api.responses.subscribeDuplicated(hook.id)
else if hook?
msg = config.api.responses.subscribeSuccess(hook.id) msg = config.api.responses.subscribeSuccess(hook.id)
else else
msg = config.api.responses.subscribeFailure msg = config.api.responses.subscribeFailure