gpt4 book ai didi

elixir - 你能在 Elixir 中创建条件插件吗?

转载 作者:行者123 更新时间:2023-12-03 08:54:43 26 4
gpt4 key购买 nike

我想从 if-else 语句的 else 部分调用插件。

我尝试调用plug SpiderWeb.AdminAuth,但收到ArgumentError:无法在函数/宏内设置属性@plugs。

我也尝试过 SpiderWeb.AdminAuth.call(conn) 但在 GET/user/1 处收到错误 UndefinedFunctionError: function SpiderWeb.AdminAuth.call/1 is undefined or private .

我也可以在其他部分重写整个插件,但这违背了 DRY 原则。

这是用户 Controller 文件:

defmodule SpiderWeb.UserController do
use SpiderWeb, :controller

alias Spider.Accounts
plug :user_authenticate when action in [:index, :show]
plug SpiderWeb.AdminAuth when action in [:index]

## Action parameters changed to ensure only current user has access or admin ##
def action(conn, _) do
args = [conn, conn.params, conn.assigns.current_user]
apply(__MODULE__, action_name(conn), args)
end

def index(conn, _params) do
users = Accounts.list_users
render(conn, "index.html", users: users)
end

def show(conn, %{"id" => id}, current_user) do
if current_user.id == String.to_integer(id) do
user = Accounts.get_user!(id)
render(conn, "show.html", user: user)
else
SpiderWeb.AdminAuth.call(conn)
end
end
end

这是管理员身份验证插件:

defmodule SpiderWeb.AdminAuth do
import Plug.Conn
import Phoenix.Controller

alias Spider.Accounts
alias SpiderWeb.Router.Helpers, as: Routes

def init(opts), do: opts

def call(conn, _opts) do
case Accounts.check_admin(conn.assigns.current_user) do
{:ok, _} -> conn
{:error, _} -> conn
|> put_flash(:error, "You don't have access to that page")
|> redirect(to: Routes.page_path(conn, :index))
|> halt()
end
end
end

我的目标是确保只有当前经过身份验证的用户才能访问展示页面(使用自己的 ID)或管理员。

编辑:其他尝试我还尝试制作一个单独的虚拟函数并尝试将插头插入其中:

...
plug SpiderWeb.AdminAuth when action in [:index, :do_nothing]
...
def show(conn, %{"id" => id}, current_user) do
...
else
do_nothing(conn)
end
end

defp do_nothing(conn) do
end
end

但相反,我在 GET/user/1 处收到 RuntimeError :预期操作/2 返回 Plug.Conn,所有插头必须接收连接 (conn) 并返回连接,得到:nil

最佳答案

你几乎是对的,你只是忘了将第二个参数传递给call!

模块插件是具有两个功能的模块:init/1call/2。为了动态调用任何模块插件,您需要使用默认选项调用 init/1 并传递 call/2 ,其中连接作为第一个参数以及调用的结果init/1 作为第二个。这是整个插头规范。 :)

换句话说,你可以这样做:

def show(conn, %{"id" => id}, current_user) do
if ... do
...
else
SpiderWeb.AdminAuth.call(conn, SpiderWeb.AdminAuth.init([]))
end
end

但也许,最好的选择是创建一个新的插件,“确保只有当前经过身份验证的用户才能访问显示页面(使用他们自己的 ID)或管理员”。这样您就可以重用它并将授权逻辑保留在操作之外。

关于elixir - 你能在 Elixir 中创建条件插件吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56333125/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com