3

I am working on a mobile application using Firebase. In the mobile app, I need to register a user based on his/her mobile number similar to Whatsapp. I intend to use Nexmo to verify user's mobile number. There are two steps involved in verifying the number.

  1. Send the the user mobile number to the Nexmo API and it returns back with a request_id on success and it also sends a code to user's mobile via SMS
  2. Send the code and the request_id to the Nexmo to verify the number

I want to use firebase-queue to execute these tasks. I want to ask if there is a way to return results for a task back to the client. I didn't see any such example on the firebase-queue documentation. Basically, I want to add a task to send the mobile number to the Nexmo API and want to get the request_id in response so that I can add another task to verify the code entered by the user.

Varun Gupta
  • 2,870
  • 6
  • 33
  • 73

2 Answers2

7

There definitely is a way to get responses back to the client. We have a good example of that in the Flashlight search integration:

  function doSearch(index, type, query) {
      var ref = new Firebase(URL+'/search');
      var key = ref.child('request').push({ index: index, type: type, query: query }).key();
      console.log('search', key, { index: index, type: type, query: query });
      ref.child('response/'+key).on('value', showResults);
    }

This code runs in the client-side JavaScript application and sends a search term to the server in the line that calls push(). It then "waits" for a response to come back on the last line of the function. The key here is that it listens for a response with the sam push id/key that it used to send the request. That way the request and response match up.

While Firebase Queue doesn't have built-in support for such a "handshake", you can easily build it yourself into the client and server code of your app. When you add a task, you add a request id (adapter from the firebase-queue sample):

var request_id = ref.push().key();
ref.child('queue/tasks').push({ requestId: request_id, foo: 'bar' });

In your task worker, you perform your usual processing and then write the response back into the database with the same request id (adapter from the firebase-queue sample):

var ref = new Firebase('https://<your-firebase>.firebaseio.com/queue');
var responses = new Firebase('https://<your-firebase>.firebaseio.com/responses');
var queue = new Queue(ref, function(data, progress, resolve, reject) {
  // Read and process task data
  console.log(data);

  // Do some work
  progress(50);

  // Finish the task asynchronously
  setTimeout(function() {
    // write the response to the client
    responses.child(data.requestId).set({ allDone: true });
    // tell firebase-queue that we're done
    resolve();
  }, 1000);
});
Alexander Mills
  • 90,741
  • 139
  • 482
  • 817
Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • Thanks for the response. I kind of figured that I would have to write my own logic to pass the results back but your tip to publish the result at /responses/ is neat. – Varun Gupta Apr 05 '16 at 14:57
  • Just a small note that (I believe) the "ref.child('response/'+key).on('value', showResults);" should be "ref.child('responses/'+key).on('value', showResults);" to be consistent with the rest of the code. Notice "responses" instead of "response". This is mostly for future readers in case they are trying to get this to work. – Ralph Yozzo May 30 '16 at 00:33
  • I just implemented this solution but it makes me wonder: What happens to all the responses nodes. Who remove them ? Do we have to let the client remove them ? If I give clients read/write access to the responses node, can he(evil) somehow listen to inserts and remove them before they can be listen by clients ? – Tom Nov 12 '16 at 13:49
  • 1
    Clients should only have read permission to `/responses/$id` and not to all `/responses`. Clean-up strategy would typically indeed be upon the client, with a server-side script that cleans up older, orphaned responses. – Frank van Puffelen Nov 12 '16 at 16:38
  • Ok I get it thanks. It also answer my question [there](https://stackoverflow.com/questions/40608672/how-to-safely-allow-user-to-delete-responses-from-firebase-queue). If you want, you can answer and I'll promote it. – Tom Nov 20 '16 at 13:23
2

You do not need to write the requestId in the object. Instead, you can use the following code to return a response. I think it is a bit cleaner.

On the client side: ref.child('queue/tasks').push({foo:'bar'});

The trick is to not sanitize the input. On the server side:

var options = {sanitize:false};

queue = new Queue(firebaseQueueRef, options , function(request, progress, resolve, reject){
   //do some work
   setTimeout(function(){
     resposeRef.child(request._id).set(myResponse);
     resolve();
   }
});
kvs
  • 121
  • 4