问题
I am currently implementing a chat between 2 of my Devise models. Client
and Professionnel
. It is working just fine at the moment but I have only one channel: every Client or Professionnel receive all messages from all clients and all professionals. The displaying is fine but someone who watches their AJAX flow can see every private message that is not meant for them..
As per this thread http://www.thegreatcodeadventure.com/rails-5-action-cable-with-multiple-chatroom-subscriptions/ this is called single responsibility principle
So I am trying to create "sub streams" in order to broadcast to the right users.
My first step is authing with Devise. I am using the classic :
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.email
end
protected
def find_verified_user
if verified_user = env['warden'].user
verified_user
else
reject_unauthorized_connection
end
end
end
end
And this is where the problem arises: when a Client is logged in, Actioncable is not creating a connection:
Started GET "/cable" for 127.0.0.1 at 2018-04-16 22:30:28 +0200
Started GET "/cable/" [WebSocket] for 127.0.0.1 at 2018-04-16 22:30:28 +0200
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: keep-alive, Upgrade, HTTP_UPGRADE: websocket)
An unauthorized connection attempt was rejected
But when a Professionel logs in everything is ok :
Successfully upgraded to WebSocket (REQUEST_METHOD: GET, HTTP_CONNECTION: keep-alive, Upgrade, HTTP_UPGRADE: websocket)
Professionnel Load (0.4ms) SELECT "professionnels".* FROM "professionnels" WHERE "professionnels"."id" = $1 ORDER BY "professionnels"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
[ActionCable] [dummy@gmail.com] Registered connection (Z2lkOi8vcm9vZnNlZWRzL1Byb2Zlc3Npb25uZWwvMQ)
This is very strange as in both case the session cookie shows a warden related id, either when Client or Professionel is logged :
["session_id", "0c3649a0e924de3fbf14dbb1cf2ce058"] ["flash", {"discard"=>[], "flashes"=>{"notice"=>"Connecté."}}] ["professionnel_return_to", "/"] ["warden.user.client.key", [[1], "$2a$12$auNvgciv6qPDf7n5a93vXu"]]
["session_id", "43a9b6db09311473419d7f22f2ce6419"] ["flash", {"discard"=>[], "flashes"=>{"notice"=>"Connecté."}}] ["warden.user.professionnel.key", [[1], "$2a$12$qZ4whbN3e2w7fn8NJWa/B."]] ["professionnel_return_to", "/"] ["_csrf_token", "sZA8gze5lxU6R71XUci0uQDXVk+d75VslI90ImcjwhA="]
I dont get where the error comes from ..
EDIT EDIT EDIT
Just found this piece of code in Devise initializer :
# Configure the default scope given to Warden. By default it's the first
# devise role declared in your routes (usually :user).
# config.default_scope = :user
Professionnel is indeed my first Devise role declared in my routes. Does it has anything to do with my problem ? And How can I solve this ?
devise_for :professionnels, controllers: {registrations: "professionnels/registrations", passwords: "professionnels/passwords", confirmations: "professionnels/confirmations"}
devise_for :clients, controllers: {registrations: "clients/registrations", passwords: "clients/passwords", confirmations: "clients/confirmations"}
devise_for :admins, controllers: {registrations: "admins/registrations", sessions: "admins/sessions"}
回答1:
Ok the answer is simple: if you have multiple Devise accounts to auth into Actioncable, you have to scope warden for each of them, in my case connection.rb looks like :
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.email
end
protected
def find_verified_user
if verified_user = env["warden"].user(:professionnel)
verified_user
elsif verified_user = env["warden"].user(:client)
verified_user
else
reject_unauthorized_connection
end
end
end
end
In this case I give them the same identifier as the chatroom is a child of both of them so I ( guess I) can treat them the same. I think it is possible to give them different identifiers if needed.
来源:https://stackoverflow.com/questions/49866041/actioncable-authentication-with-multiple-devise-models