根据用户角色渲染模板的一部分

时间:2018-05-04 16:02:48

标签: elixir phoenix-framework

我的问题是只显示用户被授权的模板的那些部分。 让我们假设有一个项目只包含用户和用户角色,以及由phx.gen.html生成的模板和控制器。设置路线" / users"我们得到了一个包含所有用户数据和按钮的漂亮表格,用于"显示","编辑"和"删除"。

用户角色可能只是普通用户"和一个" admin"。现在我希望管理员能够删除和编辑所有用户,但"用户"应该只能编辑自己以及我的问题是什么,他应该只看到那些按钮供他参赛。

我已经为相应的操作设置了一些插件,所以正常的"用户"不能编辑,删除甚至显示其他用户,但他甚至不应该知道这样做的选项。所以,我想隐藏那些按钮。以下是我遇到或解决的解决方案,但它们似乎都不适用。

  1. 使用" / admin"路由并限制对它的访问。这似乎是主要使用的方式,但我不想这样做,因为管理员在我的情况下只是一个特权普通用户,并且基本上不需要管理员的完整路由。我必须创建新的控制器,新模板等。
  2. 所以我的下一个想法是:"只需渲染另一个模板并从用户模板中删除这些按钮"。嗯,它有效,但它与1)基本相同。我必须复制所有index.html和其他一些模板的内容。此外,如果我想添加另一个角色,也许是一个"经理"什么的,我必须再次复制它。随着时间的推移,这似乎无法维持。
  3. 向模板本身添加一些逻辑,例如<%= if is_admin?做%> html-things<%end%>。我知道在这一点上它不会受到伤害,因为我用控制器中的插头仔细检查权限但是无论如何......这似乎也很糟糕"因为我不想在模板中使用这个逻辑。
  4. 任何人都有另外一个想法,或者可能是某个讨论此事的人的提法?我只能找到关于1)的文章以及如何实现它。

1 个答案:

答案 0 :(得分:1)

我喜欢将权限逻辑保存在一个位置,并在控制器和模板中使用它。灵感来自Ruby on Rails'旧的cancan gem,我定义了一个函数:

defmodule MyApp.Can do
  def can?(_user, :create, Post), do: true
  def can?(user, :delete, %Post{} = post), do: user.is_admin || post.user_id == user.id
  ...
end

现在在控制器中,使用此功能进行授权:

def delete(...) do
  ...
  if MyApp.Can.can?(current_user, :delete, post) do
    ...
  else
    ...
  end
end

在模板中:

<%= MyApp.Can.can?(@current_user, :delete, @post) %> <Delete Button> <% end %>