HELLO. – Thats great, but... Drupal? – Authentication



HELLO. – Thats great, but... Drupal? – Authentication

0 0


drupalcampatx-slides


On Github rh0 / drupalcampatx-slides

HELLO.

theoleschool.comd.o/user/114058twitter.com/rho_github.com/rh0

NODE.JS

  • Server side javascript
  • Single threaded event loop
  • Code must be non blocking
  • Socket.io allows for “real time” messaging.

Thats great, but... Drupal?

I thought we were integrating?

D.O/PROJECT/NODE.JS

“It handles the Plumbing.”

Authentication

Normal Drupal page load. (with auth token)
Normal Drupal page load. (with auth token) Socket.io asks for a connection using the auth token.
Normal Drupal page load. (with auth token) Socket.io asks for a connection using the auth token. Node.js sends the auth token to drupal.
Normal Drupal page load. (with auth token) Socket.io asks for a connection using the auth token. Node.js sends the auth token to drupal. Drupal sends node a list of channels (and some other information) for that user.
Normal Drupal page load. (with auth token) Socket.io asks for a connection using the auth token. Node.js sends the auth token to drupal. Drupal sends node a list of channels for that user. Node.js notifies the client that auth was successful.

Subsequent page loads.

Messages are the name of the game.

nodejs_notify

Send a message to all users.

$subject = "To all users:";
$body = "Hello World!";
nodejs_broadcast_message($subject, $body);

A Closer look.

function nodejs_broadcast_message($subject, $body) {
  $message = (object) array(
    'broadcast' => TRUE,
    'data' => (object) array(
      'subject' => $subject,
      'body' => $body,
    ),
    'channel' => 'nodejs_notify',
  );
  nodejs_enqueue_message($message);
}
nodejs.module

Messages are sent across channels.

d.o/project/messagejs

hook_nodejs_user_channels()

function messagejs_nodejs_user_channels($auth_user) {
  $channels = array();
  if (user_access('receive messagejs notifications', $auth_user)) {
    $channels[] = 'messagejs_general';
  }
  return $channels;
}
messagejs.module

Send a message to channel subscribers.

function messagejs_send_message($body, $subject = '') {
  $notification = new stdClass();
  $notification->channel = 'messagejs_general';
  $notification->data['subject'] = $subject;
  $notification->data['body'] = $body;
  $notification->callback = 'nodejsNotify';

  nodejs_enqueue_message($notification);
}
messagejs.module

But I want to handle messages myself!

http://github.com/rh0/swapit_demo

hook_nodejs_handlers_info()

function swapit_demo_nodejs_handlers_info() {
  return array(
    drupal_get_path('module', 'swapit_demo').'/swapit_demo.client.js',
  );
}
swapit_demo.module

Build and send the message object.

$message = new stdClass();
$message->channel = 'swapit_demo';
$message->data['body'] = $user_msg;
$message->callback = 'swapIt';
nodejs_send_message($message);
swapit_demo.module

Client side callback gets the message

Drupal.Nodejs.callbacks.swapIt = {
  //grab the message and inject into the DOM
  callback: function (message) {
    if(message.channel == 'swapit_demo') {
      $('form #nodejs-selector').html(message.data.body);
    }
  }
};
swapit_demo.client.js
http://demo.theoleschool.com/swap

So where do we stand?

  • The nodejs module establishes a handy node authentication on Drupal rendered pages.
  • “It handles the Plumbing.”
  • Pushes messages to clients via socket.io.
  • Define custom channels to target message delivery using hook_nodejs_user_channels().
  • We can customize client side message handling using hook_nodejs_handlers_info() and writing some client side JS.

I want to have my Drupal and Node it too!

Server Extensions

They let you get your Node on!

nodejs/nodejs.server.extension.js.example

The config object is here to help.

exports.setup = function (config) {
...
}
  • config.publishMessageToClient();
  • config.publishMessageToChannel();
  • config.sendMessageToBackend();

Callbacks

process.on

  • client-connection
  • client-authenticated
  • client-message
  • client-disconnect

A client has connected, do something!

process.on('client-connection', function (sessionId) {
  console.log('... got connection event for session ' + sessionId);
  config.publishMessageToClient(sessionId, {
    data: {
      subject: 'Example extension',
      body: 'Hello, you just connected.'
      }
    }
  );
})

nodejs/nodejs.server.extension.js.example

Is there anybody out there?

Talk back through socket.io

Drupal.Nodejs.socket.emit()

Decide what to say.

var message = {
    type: 'nodeToDrupal',
    messageBody: 'Hello from the client side!'
  };

Then Say it

$("#node-to-drupal-form").submit(function() {
    Drupal.Nodejs.socket.emit('message', message);
    return false;
  });

node_to_drupal.client.js

We've got a callback for that!

exports.setup = function (config) {
process.on('client-message', function (sessionId, message) {
  console.log('Got a message from the client.  Take a look: ');
  console.log(message);
  // Do some stuff ...

and can even respond

  config.publishMessageToClient(sessionId, {
    data: {
      subject: 'Success',
      body: "Huzzah!"
    }
  });
}
};
            

node_to_drupal.server.extension.js

Are you there Drupal? It's me Node.js.

http://github.com/rh0/node_to_drupal

Drupal needs to know what to expect.

hook_nodejs_message_callback()

function node_to_drupal_nodejs_message_callback($type) {
  switch($type) {
    case 'nodeToDrupal':
      return array('node_to_drupal_handler');
  }
  return false;
}
            

which defines a handler

function node_to_drupal_handler($message, &$responce) {
  $message_body = $message['messageBody'];
  watchdog('node_to_drupal', $message_body, array(), WATCHDOG_INFO);
  $responce = 'Message logged to Watchdog!';
}
              

node_to_drupal.module

Yep, it's a callback.

config.sendMessageToBackend()

Specify the message type

message.messageType = 'nodeToDrupal';
            

Send the message to Drupal.

config.sendMessageToBackend(message, function(error, responce, body) {
  if(error) {
    console.log('Error sending message to backend.', error);
    return;
  }
  console.log('Response from drupal: ', body);
});
              

So what does this mean?

  • Server extensions allow us to augment the default node server.
  • There are several useful callbacks at our disposal.
  • The config object is your friend
  • The client can talk to the node server using Drupal.NodeJS.socket.emit()
  • The Node server can talk to Drupal using config.sendMessageToBackend with a message targeted to a custom drupal handler.
https://github.com/rh0/dchess

Content Token Channels

Setup channel in Drupal

nodejs_send_content_channel_token('dchess_game_' . $node->nid);
          

Token channel message from drupal.

nodejs_send_content_channel_message($message);
            

Token channel message from node

function sendMessageToTokenChannel(message, config) {
  if (!message.hasOwnProperty('channel')) {
    console.log('... invalid message object was provided.');
    return;
  }
  if (!config.tokenChannels.hasOwnProperty(message.channel)) {
    console.log('... channel "' + message.channel + '" doesn\'t exist.');
    return;
  }

  for (var socketId in config.tokenChannels[message.channel].sockets) {
    config.publishMessageToClient(socketId, message);
  }
}
            
dchess.server.js
http://chess.theoleschool.com

A few things to note

  • https://github.com/jhlywa/chess.js
  • http://angularjs.org/

Some last thoughts

Works great with pushing messagesto the client.

You can build more complex node applicaitons with this...

but should you?

Thanks

theoleschool.comd.o/user/114058twitter.com/rho_github.com/rh0