我过去曾使用cancan
和cancancan
之类的声明式授权来控制对数据的访问。但是,在这个新的应用程序中,我试图控制对实际功能的访问。
这是您典型的SaaS模式,根据用户订阅的级别,可以逐步提供更多功能。
通过单击整个应用程序中的不同图标或菜单项,可以使用大多数功能。
我正在写信询问是否有一个众所周知的实现模式,在我推出自己的实现模式之前我还没有意识到。
以下是基于订阅级别限制的不同类型的事物:
每个订阅都有一个计划。将该计划与上面的第3,4和5项联系起来很简单,并cancancan
使用current_user
来获取可访问性。但是,功能1和2是不同的故事。我可以看到在查看功能/计划列表的视图助手中包装其可访问性。但那只能处理视图。如果用户知道该URL,他们仍然可以通过直接键入URL来访问该功能。在这种情况下,我是否需要在控制器操作级别再次处理授权,或者是否可以使用某种中间件来限制功能的可访问性?
非常感谢。
答案 0 :(得分:2)
如果它是一个简单的应用,我只需在admin
上添加User
列。如果有超过2种用户类型(admin / non-admin / author / editor / etc),那么我会将其设为Enum
字段而不是布尔值。
然后,在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
我还在current_user
中添加了application_controller.rb
方法:
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 %>
这当然不是安全性(仅限视图层更改),这就是为什么我也使用我之前提出的方法从控制器返回的原因:
def destroy
return unauthorized unless current_user.is_admin?
# ... delete code here
end
对于上面的例子,不要忘记使用return ,否则代码将继续执行。
对于非常简单的事情,我使用Pundit。
答案 1 :(得分:1)
我会简单地使用枚举来设置不同的访问或订阅级别。然后只需编写一个名为before_action
的{{1}}来阻止整个操作。然后我会在视图中设置一些条件或view_helpers来阻止对某些UI元素的访问。
答案 2 :(得分:0)
https://github.com/jnunemaker/flipper是一个很好的解决方案,可以完全满足您的需求。
否则,就像你说的那样,cancancan
对于天真的解决方案是有益的。