Rares R
Rares R

Reputation: 229

Rails 5 ActionCable setup and workflow

I am new to ActionCable and sockets and trying to implement some real time features.

I successfully implemented real time notifications functionality (basic one) into my app, however there are a couple of things on which i spent some time to understand.

My Real time notifications code:

The authentification process:

# Connection.rb (using Devise)
module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = env['warden'].user
      reject_unauthorized_connection unless self.current_user

      logger.add_tags 'ActionCable', current_user.email
    end

  end
end

Notification Channel:

class NotificationsChannel < ApplicationCable::Channel
  def subscribed
    stream_from "notification_channel_#{current_user.id}"
  end

  def unsubscribed
  end
end

Notifications.coffee

App.notifications = App.cable.subscriptions.create "NotificationsChannel",
  connected: ->

  disconnected: ->

  received: (data) ->
    this.update_counter(data.counter)

    # if use_sound is "true" play a mp3 sound
    # use_sound is sent ("true" or "false") because when a notification is destroyed we don't want to use sound only update counter  

    if data.use_sound == "true"
      $("#sound-play").get(0).play()

  # Update Notifications Counter and change color

  update_counter: (counter) ->
    $("#notifications-counter").html("#{counter}")

    if counter > 0
      $("#notifications-counter").css('color','#FFA5A5')
    else
      $("#notifications-counter").css('color','white')

And there is the Job file where we broadcast to the channel with Notifications Counter

Note: I only send notifications count because in the nav-bar when the user clicks the (ex. 2 Notifications) - button, a dropdown is toggled and populated via AJax call.

My questions are:

  1. Is it normal to have all the time 'GET /cable' requests with the response 'An unauthorized connection attempt was rejected' when a user is not logged in ( I understand that the current_user in the Connect.rb file is set from the cookie, but when a user is on ex Home page, Logg-in page, etc.. basically not authenticated.

    In the server logs I can see every 1,2 seconds the GET /cable enter image description here

    Is this normal? I'm thinking that somehow I have to stop this if the user logs out or something.

  2. When I start the server I get the following error for like 10 seconds till the server starts in the browsers console. Since the notifications work, I don't know if this is a problem of not, but an error it is.

    WebSocket connection to 'ws://localhost:3000/cable' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED

    I even tried setting config.action_cable.mount_path = "/cable" or "ws://localhost:3000/cable" and did not fix it.

  3. Next I want to implement a chat, where 2 users can have a private conversation, is the "current_user" defined in the Connection.rb 'secure', how can I add authorization to ActionCable or something like. In the rest of my app I'm using CanCan Gem and works perfectly.

Thank you very much for the time invested in reading the question. If you have answers for my questions I will really appreciate them. And if you have some directions to give or tips for building a complex and secure chat with ActionCable I would love to hear them. Thank you!

Upvotes: 0

Views: 1131

Answers (1)

fbelanger
fbelanger

Reputation: 3568

I think what you want to be looking at is the cable.js file where the createConsumer function is called.

Creating a consumer is what subscribers a user to the channel. I think you need to focus on when this code gets called.

You are using user authentication's presence to reject unauthorised use.

This is very good, however not so great when the JS consumer is created for any visitor (i.e. cable.js is loaded into application.js for all pages).

What you can do is use content_for into a seperate layout for authenticated users that calls the cable.js to create a consumer and ensure that cable.js does not get included into unauthorised pages.

Upvotes: 1

Related Questions