Ruby on rails Rails:Action Cable:如何根据角色授权用户连接特定通道?
在我的rails拍卖应用程序中,授权用户可以在产品页面内同时连接到2个频道(一个是产品的all_users频道,另一个是直接消息的用户特定频道) 现在我只想将敏感信息发送给管理员组用户。我想我可以在coffee脚本中定义第三个通道连接请求(admin_channel),但我不知道如何根据角色授权第三个通道的用户连接 另一种选择可能是利用现有的特定于用户的通道,但在这里,我无法理解后端类如何知道管理组中的哪些用户当前处于联机状态(已启动并运行用户通道) 你知道我怎样才能做到吗?任何形式的支持都将不胜感激 在下面,您可以找到我现有的connection.rb文件和coffeescript文件 这是我的connection.rb文件:Ruby on rails Rails:Action Cable:如何根据角色授权用户连接特定通道?,ruby-on-rails,actioncable,Ruby On Rails,Actioncable,在我的rails拍卖应用程序中,授权用户可以在产品页面内同时连接到2个频道(一个是产品的all_users频道,另一个是直接消息的用户特定频道) 现在我只想将敏感信息发送给管理员组用户。我想我可以在coffee脚本中定义第三个通道连接请求(admin_channel),但我不知道如何根据角色授权第三个通道的用户连接 另一种选择可能是利用现有的特定于用户的通道,但在这里,我无法理解后端类如何知道管理组中的哪些用户当前处于联机状态(已启动并运行用户通道) 你知道我怎样才能做到吗?任何形式的支持都将不
module ApplicationCable
class Connection < ActionCable::Connection::Base
identified_by :current_user
def connect
self.current_user = find_verified_user
end
protected
def find_verified_user # this checks whether a user is authenticated with devise
if verified_user = env['warden'].user
verified_user
else
reject_unauthorized_connection
end
end
end
end
私人管理信息频道.rb
class PrivateAdminMessagesChannel < ActionCable::Channel::Base
def subscribed
stream_from :private_admin_messages_channel, coder: ActiveSupport::JSON do |data|
from_user = User.find(data.fetch('from_user_id'))
to_user = User.find(data['to_user_id']) if data['to_user_id']
message = data.fetch('message')
# authorize if "message" is sent to you (a non-admin), and also
# authorize if "message" is sent to you (an admin)
if (to_user && to_user == current_user) || (!to_user && current_user.is_admin?)
# now, finally send the Hash data below and transmit it to the client to be received in the JS-side "received(data)" callback
transmit(
from_user_id: from_user.id,
to_user_id: to_user&.id,
message: message
)
end
end
end
def send_message_to_admins(data)
ActionCable.server.broadcast 'private_admin_messages_channel',
from_user_id: current_user.id,
message: data.fetch('message')
end
def send_message_to_user_and_admins(data)
from_user = current_user
reject unless from_user.is_admin?
ActionCable.server.broadcast 'private_admin_messages_channel',
from_user_id: from_user.id,
to_user_id: data.fetch('to_user_id'),
message: data.fetch('message')
end
end
class privateAdminingMessageSchannel
以上是我能想到的最简单的方法。不是最有效的,因为每个流都有一个额外的授权级别(请参见块中的stream_),不同于我们有不同的广播名称,授权只在“连接”本身上发生一次,而不是在每个“流”。。。这可以通过以下方式实现:
Admin User1打开页面,然后JS订阅UserConnectedChannel
非管理员用户2打开页面,然后JS订阅privateAdminMessagesAnnel
传入数据:user\u id:CURRENT\u user\u id
从2。如上所述,因为User2刚刚订阅;然后在后端,在连接后的def subscribed
内,您ActionCable.server.broadcast:user\u connected,{user\u id:current\u user.id}
订阅了UserConnectedChannel
的Admin User1然后接收带有数据{user\u id:THAT\u USER2\u id}
从上面的第4步开始,在JSreceived(data)
callback中,现在JS订阅privateAdminingMessagesAnnel
传入数据:该用户2\u id`
现在User1和User2都订阅了privateAdminMessagesAnnel user\u id:THAT\u User2\u id
,这意味着他们可以私下交谈(其他管理员也应该已经收到:user\u connected
的JS数据:{user\u id:THAT\u User2\u id}
,因此它们也应该订阅,因为AdminUser1、NonAdminUser2和AdminUser3可以在同一个聊天频道中聊天……这是我根据您的要求得到的)
TODO:从上面的1到6,对“断开连接”过程也执行类似的操作
琐事:
- 可以在频道文件中访问您在
ApplicationTable::Connection
中定义的由标识的。特别是,在这种情况下,可以调用当前用户
- 关于拒绝订阅,请参阅
它们是否连接到同一频道MyauctionChannel
?但它们连接到不同的房间,正如您的id:$(''uuid').attr('data-id')
所标识的,而另一个是id:$('uuid').attr('data-uuid-code')
?@Jay Ar Polidario我试图对这个问题进行更多的澄清。。正如您所指出的,用户连接到基于产品的“广播”频道$('#auctionID').attr('data-uuid-code')以及用户特定频道。我还没有测试过这一点,因此我可能错过了一些东西;让我知道accordingly@Tolga不用担心,祝你好运!:)
$(document).ready ->
App.privateAdminMesssagesChannel = App.cable.subscriptions.create({
channel: 'PrivateAdminMessagesChannel'
},
connected: ->
disconnected: ->
// call this function to send a message from a Non-Admin to All Admins
sendMessageToAdmins: (message) ->
@perform 'send_messsage_to_admins', message: message
// call this function to send a messsage from an Admin to (a Non-admin + all Admins)
sendMessageToUserAndAdmins: (message, toUserId) ->
@perform 'send_messsage_to_user_and_admins', message: message, to_user_id: toUserId
received: (data) ->
console.log(data.from_user_id)
console.log(data.to_user_id)
console.log(data.message)
if data.to_user_id
// this means the message was sent from an Admin to (a Non-admin + all admins)
else
// this means the message was sent from a Non-admin to All Admins
// do some logic here i.e. if current user is an admin, open up one Chatbox
// on the page for each unique `from_user_id`, and put data.message
// in that box accordingly
)
class PrivateAdminMessagesChannel < ActionCable::Channel::Base
def subscribed
stream_from :private_admin_messages_channel, coder: ActiveSupport::JSON do |data|
from_user = User.find(data.fetch('from_user_id'))
to_user = User.find(data['to_user_id']) if data['to_user_id']
message = data.fetch('message')
# authorize if "message" is sent to you (a non-admin), and also
# authorize if "message" is sent to you (an admin)
if (to_user && to_user == current_user) || (!to_user && current_user.is_admin?)
# now, finally send the Hash data below and transmit it to the client to be received in the JS-side "received(data)" callback
transmit(
from_user_id: from_user.id,
to_user_id: to_user&.id,
message: message
)
end
end
end
def send_message_to_admins(data)
ActionCable.server.broadcast 'private_admin_messages_channel',
from_user_id: current_user.id,
message: data.fetch('message')
end
def send_message_to_user_and_admins(data)
from_user = current_user
reject unless from_user.is_admin?
ActionCable.server.broadcast 'private_admin_messages_channel',
from_user_id: from_user.id,
to_user_id: data.fetch('to_user_id'),
message: data.fetch('message')
end
end