nweber
nweber

Reputation: 53

AnyCable : Retrieve information gRPC info on ROR App

I work to switch Action Cable to AnyCable.

I don't use cookies to identify users, I use JWT because my app provide only API.

So in case of a chat, we need to retrieve the user who send the message.

In log, I see this message1:

RPC Command: <AnyCable::CommandMessage: command: "subscribe", identifier: "{\"channel\":\"RoomChannel\",\"room_id\":\"566\"}", connection_identifiers: "{\"current_user\":{\"id\":\"XXXXXXXX\",\"login_time\":1589745276,\"okta_id\":\"[email protected]\"

How can I retrieve the value of the object "connection_identifiers"?

Below the current connection Class : `Class : module ApplicationCable class Connection < ActionCable::Connection::Base include Authentication

identified_by :current_user

def connect
  self.current_user = create_user_from_tokens

  reject_unauthorized_connection unless current_user.valid
end

end end`

create_user_from_tokens > Create a user object from JWT token

And the current reception method for a new message : `def receive(content) return false unless receive_params return false unless conversation

message = content['content']

message_params = {conversation_id: @conversation.id,
                  conversation: @conversation,
                  sender_id: @connection.current_user.okta_id,
                  sender_name: @connection.current_user.name,
                  content: message}

ConversationMessageService.post message_params

rescue StandardError Rails.logger.error I18n.t('log.api.websocket.error_receive') render json: {error: :bad_request, error_description: I18n.t('log.api.websocket.error_receive'), error_uri: ''}, status: :bad_request end`

As I undertand it is impossible to retrieve @connection.

Upvotes: 0

Views: 413

Answers (1)

palkan
palkan

Reputation: 191

To access the current user from the channel, you can use #current_user accessor (Rails adds this delegation for you automatically).

So, the code should be:

message_params = {conversation_id: @conversation.id,
                  conversation: @conversation,
                  sender_id: current_user.okta_id,
                  sender_name: current_user.name,
                  content: message}

If I understood you correctly, your current_user object is not an AR record but a plain Ruby class, right?

Then current_user in channels would simply return a JSON-encoded string, not the object.

Currently, AnyCable uses GlobalID to serialize/deserialize connection identifiers. You must add GlobalID functionality to your class to make it work with AnyCable the same way as with Action Cable. For example:

class User
  include GlobalID::Identification

  def self.find_by_gid(gid)
    new(gid.params)
  end

  def to_global_id
    super(to_h.merge!(app: :custom))
  end

  alias to_gid to_global_id
end

# setup GlobalID to correctly resolve your custom class
GlobalID::Locator.use :custom do |gid|
  gid.model_name.constantize.find_by_gid(gid)
end

Upvotes: 0

Related Questions