我按照完整的教程解释了如何处理上下文& @chrismccord的身份验证/授权...我利用他的帖子关于将auth从dockyard blog解耦:slight_smile:auth for phoenix context和Adding CMS functions in phoenix context
根据这一点,在我的情况下( CMS ENR ),所有创建的学生都需要一个注册者,注册者通过自己的会话链接到用户(经过身份验证) :学生 - > belongs_to Enroller,Enroller - > belongs_to用户,用户拥有自己的凭据。
resources "/students", StudentController
受到保护,这很好。
但现在我想揭露一些事实:如果我们想让学生自己注册怎么办?代码看起来如何?
自我注册或自行注册,而不是由管理员的人做...这将是好的。
这是我做的,但我总是重定向到身份验证页面,结果是: “你必须登录” 。
当管理员登录/注册时......他/她可以通过以下方式实现管理任务(创建:学生,登记者,页面等):
scope "/enr", HelloWeb.ENR, as: :enr do
pipe_through [:browser, :authenticate_user]
resources "/admissions", AdmissionController
end
承认任务
CMS
或(ENR
)是管理员部分,我们希望学生通过注册自己公共部分我做了这样的路线: scope "/", InsWeb do
pipe_through :browser # Use the default browser stack
get "/", PageController, :index
resources "/users", UserController
resources "/sessions", SessionController, only: [:new, :create, :delete],
singleton: true
resources "/admissions", AdmissionController, only: [:new, :create, :show]
end
scope "/ENR", InsWeb.ENR, as: :enr do
pipe_through [:browser, :authenticate_user]
resources "/admissions", AdmissionController
end
defp authenticate_user(conn, _) do
case get_session(conn, :user_id) do
nil ->
conn
|> Phoenix.Controller.put_flash(:error, "Login required")
|> Phoenix.Controller.redirect(to: "/")
|> halt()
user_id ->
assign(conn, :current_user, Ins.Accounts.get_user!(user_id))
end
end
一切似乎都很好我通过公共部分到达了录取页面,但是当我提交表格时====没有......我总是得到“需要登录” 所以不允许学生自行注册......
CMS {EN}我的案例中的AdmissionController.ex
范围如下:
defmodule InsWeb.ENR.AdmissionController do
use InsWeb, :controller
plug :require_existing_enroller
plug :authorize_admission when action in [:edit, :update, :delete]
alias Ins.ENR
alias Ins.ENR.Admission
def index(conn, _params) do
admissions = ENR.list_admissions()
render(conn, "index.html", admissions: admissions)
end
def new(conn, _params) do
changeset = ENR.change_admission(%Admission{})
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"admission" => admission_params}) do
case ENR.create_admission(conn.assigns.current_enroller, admission_params) do
{:ok, admission} ->
conn
|> put_flash(:info, "Admission created successfully.")
|> redirect(to: enr_admission_path(conn, :show, admission))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
def show(conn, %{"id" => id}) do
admission =
id
|> ENR.get_admission!()
|> ENR.inc_admission_views()
render(conn, "show.html", admission: admission)
end
def edit(conn, %{"id" => id}) do
admission = ENR.get_admission!(id)
changeset = ENR.change_admission(admission)
render(conn, "edit.html", admission: admission, changeset: changeset)
end
def update(conn, %{"id" => id, "admission" => admission_params}) do
admission = ENR.get_admission!(id)
case ENR.update_admission(conn.assigns.admission, admission_params) do
{:ok, admission} ->
conn
|> put_flash(:info, "Admission updated successfully.")
|> redirect(to: enr_admission_path(conn, :show, admission))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "edit.html", admission: admission, changeset: changeset)
end
end
def delete(conn, %{"id" => id}) do
admission = ENR.get_admission!(id)
{:ok, _admission} = ENR.delete_admission(conn.assigns.admission)
conn
|> put_flash(:info, "Admission deleted successfully.")
|> redirect(to: enr_admission_path(conn, :index))
end
defp require_existing_enroller(conn, _) do
enroller = ENR.ensure_enroller_exists(conn.assigns.current_user)
assign(conn, :current_enroller, enroller)
end
defp authorize_admission(conn, _) do
admission = ENR.get_admission!(conn.params["id"])
if conn.assigns.current_enroller.id == admission.enroller_id do
assign(conn, :admission, admission)
else
conn
|> put_flash(:error, "You can't modify that admission page")
|> redirect(to: enr_admission_path(conn, :index))
|> halt()
end
end
end
另一个来自 CMS
defmodule InsWeb.AdmissionController do
use InsWeb, :controller
alias Ins.ENR
alias Ins.ENR.Admission
def new(conn, _params) do
changeset = ENR.change_admission(%Admission{})
render(conn, "new.html", changeset: changeset)
end
def create(conn, %{"admission" => admission_params}) do
case ENR.create_admission(conn.assigns.current_enroller, admission_params) do
{:ok, admission} ->
conn
|> put_flash(:info, "Admission created successfully.")
|> redirect(to: enr_admission_path(conn, :show, admission))
{:error, %Ecto.Changeset{} = changeset} ->
render(conn, "new.html", changeset: changeset)
end
end
def show(conn, %{"id" => id}) do
admission =
id
|> ENR.get_admission!()
render(conn, "show.html", admission: admission)
end
end
任何帮助将不胜感激!谢谢!
/templates/enr/admission/form.html.eex
<%= form_for @changeset, @action, fn f -> %>
<%= if @changeset.action do %>
<div class="alert alert-danger">
<p>Oops, something went wrong! Please check the errors below.</p>
</div>
<% end %>
<div class="form-group">
<%= label f, :first_name, class: "control-label" %>
<%= text_input f, :first_name, class: "form-control" %>
<%= error_tag f, :first_name %>
</div>
<div class="form-group">
<%= label f, :last_name, class: "control-label" %>
<%= text_input f, :last_name, class: "form-control" %>
<%= error_tag f, :last_name %>
</div>
<div class="form-group">
<%= label f, :views, class: "control-label" %>
<%= number_input f, :views, class: "form-control" %>
<%= error_tag f, :views %>
</div>
<div class="form-group">
<%= submit "Submit", class: "btn btn-primary" %>
</div>
<% end %>
/templates/enr/admission/new.html.eex
<h2>New Admission</h2>
<%= render "form.html", Map.put(assigns, :action, enr_admission_path(@conn, :create)) %>
<span><%= link "Back", to: enr_admission_path(@conn, :index) %></span>
答案 0 :(得分:1)
根据您的定义,您的AdmissionController.create
操作应该有两种方法:
admission_path(conn, :create)
- /admissions
enr_admission_path(conn, :create)
- /ENR/admissions
我可以想象,在你的new.eex模板中,form_for
方法中使用了第二个,因此每个用户都需要登录。
我会改用两个控制器。如果它不适合您,您需要做出决定,应该使用哪条路线。这取决于用户是否已登录。