2017-08-13 31 views
1

我跟着完整的教程解釋瞭如何處理上下文&通過@chrismccord進行身份驗證/授權......並且我利用了他關於從造船廠博客解除身份驗證的文章:slight_smile:auth for phoenix context和從Adding CMS functions in phoenix contextElixir Phoenix上下文授權(帶和不帶)

根據這一點,在我的情況(CMSENR)創建的所有學生需要的註冊程序,將註冊器鏈接到用戶(認證)與自己的會話:學生 - > belongs_to的登記器,註冊人 - > belongs_to用戶,用戶擁有自己的憑證。

resources "/students", StudentController受保護,這很好。

但是現在我想揭示一些事實:如果我們想讓學生註冊自己,那麼怎麼辦?代碼的外觀如何?

用於自我註冊或自行註冊,而不是由管理員的人做...它會很好。

這裏是我做過什麼,但我總是重定向到認證頁面,結果:「你必須先登錄」

  1. 當管理員已登錄/註冊....他/她可以實現管理任務(創建:同學們,Enrollers,網頁等)這是通過允許:

    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 
    

    一切似乎都很好,我達到了通過公開部分入學頁面,但是當我提交表單==== nothing..I總是在CMS了「需要登錄」 所以這是不可能的,讓學生自行註冊...

  • 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 
    

    任何幫助,將不勝感激!謝謝!

    下面是其他內容

    1. /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 %> 
      
    2. /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> 
      

    回答

    1

    隨着你的定義應該有兩種方法您AdmissionController.create行動:

    1. admission_path(conn, :create) - 一個POST路線/admissions
    2. enr_admission_path(conn, :create) - 一個POST路線/ENR/admissions

    我能想象,在你new.eex模板有使用的第二個form_for方法,所以每個用戶都需要登錄。

    我會用兩個控制器來代替。如果它不適合您,您需要做出決定,應該使用哪條路線。這取決於是否有用戶登錄或不登錄。

    +0

    感謝您的回覆@guitarman,我構建了2個控制器,但它是相同的結果。我編輯了我的問題,向你展示'CMS'範圍內的'AdmissionController.ex'。 –

    +0

    我正在使用** Phoenix 1.3 **。 –

    +0

    我在我的Phoenix 1.3應用程序中嘗試了不同的命名。 'resources'/ admissions「,AdmissionController'中使用的控制器對於兩個範圍都是相同的。檢查'混合php.routes'。 請提供new.html.eex的HTML以及是否存在form.html.eex。 – guitarman