Rails / Devise - 每个房间的单独身份验证

问题描述 投票:0回答:1

我正在编写一个包含多个“房间”供用户加入的应用程序。每个房间的用户会话应该相互独立。

例如,用户应该能够访问

/room/1
并以
user1
登录,访问
/room/2
并以
user2
登录,而无需在
user1
中从
/room/1
注销。签入/注销一个房间不应影响其他房间的会话。

这可以在 Devise 中完成吗?如果不是,实现此行为的可能选项是什么?

我读过有关 Devise 范围的信息,但似乎 Devise 的范围需要预定义并分成不同的模型,这在这种情况下是不可能的(房间可以在运行时创建)。

编辑:

为了解决问题,我不需要跟踪用户的在线或离线状态——传统的基于 cookie 的会话就足够了,它只需要在每个房间范围内。

我可以想象如果我需要从头开始实现这个,我会将每个房间的会话 cookie 存储在不同的 cookie 中。我只是问是否有现有的宝石能够实现这一目标。

ruby-on-rails authentication devise
1个回答
2
投票

我认为您应该为这个功能想象一个单独的系统,它与 Devise 或您选择使用的任何身份验证系统共存。并非所有内容都应塞入您的身份验证系统。

身份验证系统将负责用户登录应用程序并跟踪凭据,而用户表和聊天室之间的简单连接表会跟踪在(或曾经在)房间中的用户。

# This is the actual user that signs into your application
class User < ApplicationRecord
  # ...
  has_many :room_users
  has_many :rooms, through: :room_users
end

# this is just a member of a chat room
# rails g model room_user nickname:string user:belongs_to room:belongs_to left_at:date_time 
class RoomUser < ApplicationRecord
  belongs_to :room
  belongs_to :user

  def soft_delete
    update_attribute(:left_at, Time.current)
  end
end

class Room < ApplicationRecord
  has_many :room_users
end
class RoomUsersController
  before_action :authenticate_user!
  before_action :set_room!

  # Joining a room
  # POST /rooms/1/room_users
  def create
    @room_user = @room.room_users.new(room_user_params) do |ru|
      ru.user = current_user
    end
    if @room_user.save
      render json: @room_user,
             status: :created
    else 
      render json: { errors: @room_user.errors.full_messages },
             status: :unprocessable_entity
    end
  end

  # Leaving a room
  # DELETE /room_users/1
  def destroy
    @room_user = @room.room_users.find_by!(user_id: current_user.id)
    @room_user.soft_delete
    head :no_content
  end

  private

  def set_room
    @room = Room.find(params[:room_id])
  end

  def room_user_params
     params.require(:room_user)
           .permit(:nickname)
  end
end

这可以在 Devise 中完成吗?

是和不是。 Rails(以及扩展的 Devise)默认使用基于 cookie 的会话存储。这意味着无法跟踪用户在任何给定时间签署的内容,因为该信息由客户持有。

如果你想实现它,你需要将会话存储切换到数据库存储或类似 memcached/redis 的东西。

更好的问题是:这应该在 Devise 中完成吗?我认为答案是否定的,因为它已经做了很多疯狂的事情而且非常复杂。

© www.soinside.com 2019 - 2024. All rights reserved.