我过去曾使用声明性授权 gem,如 cancan
和 cancancan
来控制对数据的访问。但是,在这个新应用程序中,我试图控制对实际功能的访问。
这是典型的 SaaS 模型,其中根据用户订阅的级别逐渐提供更多功能。
大多数功能都可以通过单击整个应用程序中的不同图标或菜单项来使用。
我写信是想询问在我自己动手之前是否有一个我不知道的众所周知的实现模式。
以下是根据订阅级别限制的不同类型的内容:
- 可通过图标访问的功能
- 可通过菜单项访问的功能
- 某些报告(每个报告都有定义它的 ReportDefinition。)
- 某些上传(每个上传都有一个文件类型定义。)
- 某些 BackgroundProcesses(每个都有一个定义它的 ProcessType。)
每个订阅都有一个计划。将该计划与上面的第 3、4 和 5 项联系起来并使用 cancancan
以供 current_user
访问非常简单。但是,功能 1 和 2 是另一回事。我可以看到将它们的可访问性包装在检查功能/计划列表的 View 助手中。但这只处理 View 。如果用户知道 URL,他们仍然可以通过直接输入 URL 来访问该功能。在这种情况下,我是否需要在 Controller 操作级别再次处理授权,或者我是否可以放入某种中间件来限制对这些功能的访问?
非常感谢。
最佳答案
如果它是一个简单的应用程序,我只需在 User
上添加一个 admin
列。如果有超过 2 种用户类型(admin/non-admin/author/editor/etc),那么我会将其设为 Enum
字段而不是 bool 值。
然后,在 user.rb
中我添加了几个方法...
def is_admin?
admin?
end
def is_author?
!admin?
end
从那里,我还在 application_controller.rb
中添加了一些引发异常的代码:
def unauthorized
head(:unauthorized)
end
def unprocessable
head(:unprocessable_entity)
end
我还在application_controller.rb
中添加了一个current_user
方法:
helper_method :current_user
def current_user
@user ||= User.find(session[:user_id])
end
然后在我看来,这就是我处理“隐藏”事物或禁用按钮的地方。
<%= if current_user.is_admin? %>
<button>Admin button</button>
<% else %>
<button>Author button</button>
<% end %>
这当然不是安全性(仅 View 层更改),这就是为什么我也使用我之前布置的方法提前从 Controller 返回:
def destroy
return unauthorized unless current_user.is_admin?
# ... delete code here
end
对于上面的例子不要忘记使用return否则代码会一直执行。
对于比较简单的事情,我使用 Pundit .
关于ruby-on-rails - 如何限制对 UI 功能的访问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48310464/