Rails、Devise、Pundit - 授权从 Devise 注册控制器创建的配置文件
Rails, Devise, Pundit - authorise Profile created from Devise registration controller
如果您认为有什么不对的地方,请随时说出来。
我扩展了 Devise Registration 控制器来为每个新用户创建一个 Profile 对象:
class Users::RegistrationsController < Devise::RegistrationsController
def new
resource = build_resource({})
resource.profile = Profile.new
resource.profile.user_id = @user.id
respond_with resource
end
它们都是 has_one
- has_one
相关并且在数据库中:
create_table :profiles do |t|
t.belongs_to :user, index: { unique: true }, foreign_key: true
end
所以要获得当前用户的正确配置文件,我必须:
private
def set_profile
@profile = Profile.where(user_id: current_user.id).first
end
这有点解决问题 - 似乎其他用户无法绕过此查询并访问其他配置文件(或者他们可以吗?),但对于其他资源我使用 Pundit 来控制授权,所以现在感觉有点乱。
所以这是一个问题。其他 - 我仍然不知道在没有用户登录时如何操作,因为如果访问任何受限资源,这:
private
def set_some_resource
end
end
抛出 - “nil:NilClass) 的未定义方法 `id' - 如何最好地避免这种情况?
感谢您的任何建议。
您可能想先阅读 Rails guides on assocations。
要创建一对一关联,您在外键列的一侧使用 belongs_to
,在另一侧使用 has_one。
class User
has_one :profile
end
class Profile
belongs_to :user
end
ActiveRecord 然后自动将记录链接在一起。通常,您应该避免显式设置 ID(或通过 ID 获取关联记录),而是使用关联:
class Users::RegistrationsController < Devise::RegistrationsController
# ...
def new
# calls Devise::RegistrationsController#new
super do |user|
user.profile.new
end
end
end
Devise 非常漂亮,让您可以通过一个块来进入流程,而不是复制粘贴整个操作。
同样地,您将获取当前用户的个人资料:
private
def set_profile
@profile = current_user.profile
end
您可以设置是否应使用 if:
选项调用回调。
before_action :set_profile, if: :user_signed_in?
但是如果操作需要身份验证,您应该确保它在 :authenticate_user!
之后,无论如何这将停止过滤器链。
And this kinda solves the problem - seems other users cant go around
this query and access other profiles (or CAN THEY?), but for other
resources I use Pundit to control authorisation, so now it feels a bit
messy.
您不需要使用 Pundit 来授权创建个人资料或获取当前用户个人资料。由于配置文件是通过用户获取的,因此其他用户无法访问它(没有黑客攻击)。
如果您创建 ProfilesController
,您可能想要授权的是显示、索引、编辑等操作。
如果您认为有什么不对的地方,请随时说出来。 我扩展了 Devise Registration 控制器来为每个新用户创建一个 Profile 对象:
class Users::RegistrationsController < Devise::RegistrationsController
def new
resource = build_resource({})
resource.profile = Profile.new
resource.profile.user_id = @user.id
respond_with resource
end
它们都是 has_one
- has_one
相关并且在数据库中:
create_table :profiles do |t|
t.belongs_to :user, index: { unique: true }, foreign_key: true
end
所以要获得当前用户的正确配置文件,我必须:
private
def set_profile
@profile = Profile.where(user_id: current_user.id).first
end
这有点解决问题 - 似乎其他用户无法绕过此查询并访问其他配置文件(或者他们可以吗?),但对于其他资源我使用 Pundit 来控制授权,所以现在感觉有点乱。
所以这是一个问题。其他 - 我仍然不知道在没有用户登录时如何操作,因为如果访问任何受限资源,这:
private
def set_some_resource
end
end
抛出 - “nil:NilClass) 的未定义方法 `id' - 如何最好地避免这种情况?
感谢您的任何建议。
您可能想先阅读 Rails guides on assocations。
要创建一对一关联,您在外键列的一侧使用 belongs_to
,在另一侧使用 has_one。
class User
has_one :profile
end
class Profile
belongs_to :user
end
ActiveRecord 然后自动将记录链接在一起。通常,您应该避免显式设置 ID(或通过 ID 获取关联记录),而是使用关联:
class Users::RegistrationsController < Devise::RegistrationsController
# ...
def new
# calls Devise::RegistrationsController#new
super do |user|
user.profile.new
end
end
end
Devise 非常漂亮,让您可以通过一个块来进入流程,而不是复制粘贴整个操作。
同样地,您将获取当前用户的个人资料:
private
def set_profile
@profile = current_user.profile
end
您可以设置是否应使用 if:
选项调用回调。
before_action :set_profile, if: :user_signed_in?
但是如果操作需要身份验证,您应该确保它在 :authenticate_user!
之后,无论如何这将停止过滤器链。
And this kinda solves the problem - seems other users cant go around this query and access other profiles (or CAN THEY?), but for other resources I use Pundit to control authorisation, so now it feels a bit messy.
您不需要使用 Pundit 来授权创建个人资料或获取当前用户个人资料。由于配置文件是通过用户获取的,因此其他用户无法访问它(没有黑客攻击)。
如果您创建 ProfilesController
,您可能想要授权的是显示、索引、编辑等操作。