4

I'm authenticating users in ActionCable like this:

module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :current_user

    def connect
      self.current_user = find_verified_user
      logger.add_tags 'ActionCable', current_user.name
    end

    protected
      def find_verified_user
        if verified_user = User.find_by(id: cookies.signed[:user_id])
          verified_user
        else
          reject_unauthorized_connection
        end
      end
  end
end

Is it possible to get connected users list ? I googled but found only this stackoverflow questions: first, second

Community
  • 1
  • 1
user525717
  • 1,612
  • 5
  • 28
  • 40

1 Answers1

9

Ya kinda have to roll your own user-tracking.

The important bits are as follows:

# connection
module ApplicationCable
  class Connection < ActionCable::Connection::Base
    identified_by :uid

    def connect
      self.uid = get_connecting_uid
      logger.add_tags 'ActionCable', uid
    end

    protected

    # the connection URL to this actioncable/channel must be
    # domain.tld?uid=the_uid
    def get_connecting_uid
      # this is just how I get the user id, you can keep using cookies,
      # but because this key gets used for redis, I'd 
      # identify_by the user_id instead of the current_user object
      request.params[:uid]
    end
  end
end


# Your Channel
def subscribed
  stop_all_streams
  stream_from broadcasting_name
  ConnectedList.add(uid)
end

def unsubscribed
  ConnectedList.remove(uid)
end

And then in Models:

class ConnectedList
  REDIS_KEY = 'connected_nodes'

  def self.redis
    @redis ||= ::Redis.new(url: ActionCableConfig[:url])
  end

  # I think this is the method you want.
  def self.all
    redis.smembers(REDIS_KEY)
  end

  def self.clear_all
    redis.del(REDIS_KEY)
  end

  def self.add(uid)
    redis.sadd(REDIS_KEY, uid)
  end

  def self.include?(uid)
    redis.sismember(REDIS_KEY, uid)
  end

  def self.remove(uid)
    redis.srem(REDIS_KEY, uid)
  end
end

from: https://github.com/NullVoxPopuli/mesh-relay/

NullVoxPopuli
  • 61,906
  • 73
  • 206
  • 352
  • It seems that when restarting Action Cable server, connected_nodes won't be reset. Any workaround for this? – cisolarix Sep 14 '16 at 03:45
  • maybe add an initializer that clears the redis cache connected_nodes? – NullVoxPopuli Sep 14 '16 at 11:57
  • 1
    I believe this will also fail when a particular user connects with multiple browser windows. When the user closes one window, they'll be completed removed from the ConnectedList (since the user list is tracked using a set), even though they're still connected from another window. – odonnellt Nov 28 '16 at 08:04
  • 1
    then instead of adding just the uid, you'd probably want to add connected clients or number of connections from that uid in like a hash or something. – NullVoxPopuli Nov 28 '16 at 14:18
  • you can use a hash instead of a set, and use HINCRBY to increment/decrement the number of connections for a specific user. Then you can use HKEYS to get a list of all users – Pere Joan Martorell Feb 11 '20 at 09:33