diff --git a/lib/wiki/accounts/user.ex b/lib/wiki/accounts/user.ex index d422eca..98dded9 100644 --- a/lib/wiki/accounts/user.ex +++ b/lib/wiki/accounts/user.ex @@ -7,7 +7,8 @@ defmodule Wiki.Accounts.User do password: String.t() | nil, hashed_password: String.t(), confirmed_at: NaiveDateTime.t(), - content_encryption_key_salt: String.t() + content_encryption_key_salt: String.t(), + is_admin: boolean() } @derive {Inspect, except: [:password]} @@ -17,6 +18,7 @@ defmodule Wiki.Accounts.User do field :hashed_password, :string field :confirmed_at, :naive_datetime field :content_encryption_key_salt, :binary + field :is_admin, :boolean, default: false timestamps() end diff --git a/lib/wiki_web/controllers/user_auth.ex b/lib/wiki_web/controllers/user_auth.ex index 9b3abc8..84ba612 100644 --- a/lib/wiki_web/controllers/user_auth.ex +++ b/lib/wiki_web/controllers/user_auth.ex @@ -143,6 +143,19 @@ defmodule WikiWeb.UserAuth do end end + def require_admin_user(conn, _opts) do + case conn.assigns[:current_user] do + %Accounts.User{is_admin: true} -> + conn + + _ -> + conn + |> put_flash(:error, "You must be logged in as an admin to access this page.") + |> redirect(to: "/") + |> halt() + end + end + defp maybe_store_return_to(%{method: "GET", request_path: request_path} = conn) do put_session(conn, :user_return_to, request_path) end diff --git a/lib/wiki_web/router.ex b/lib/wiki_web/router.ex index f93dc1c..e7af0c3 100644 --- a/lib/wiki_web/router.ex +++ b/lib/wiki_web/router.ex @@ -2,6 +2,7 @@ defmodule WikiWeb.Router do use WikiWeb, :router import WikiWeb.UserAuth + import Phoenix.LiveDashboard.Router pipeline :browser do plug :accepts, ["html"] @@ -21,22 +22,6 @@ defmodule WikiWeb.Router do # pipe_through :api # end - # Enables LiveDashboard only for development - # - # If you want to use the LiveDashboard in production, you should put - # it behind authentication and allow only admins to access it. - # If your application does not have an admins-only section yet, - # you can use Plug.BasicAuth to set up some basic authentication - # as long as you are also using SSL (which you should anyway). - if Mix.env() in [:dev, :test] do - import Phoenix.LiveDashboard.Router - - scope "/" do - pipe_through :browser - live_dashboard "/dashboard", metrics: WikiWeb.Telemetry - end - end - ## Authentication routes scope "/", WikiWeb do @@ -68,6 +53,12 @@ defmodule WikiWeb.Router do delete "/pages/:id/uploads/:upload_id", PageController, :delete_upload end + scope "/", WikiWeb do + pipe_through [:browser, :require_authenticated_user, :require_admin_user] + + live_dashboard "/dashboard", metrics: WikiWeb.Telemetry + end + scope "/", WikiWeb do pipe_through [:browser] diff --git a/lib/wiki_web/templates/layout/app.html.eex b/lib/wiki_web/templates/layout/app.html.eex index ef1f233..ab493ed 100644 --- a/lib/wiki_web/templates/layout/app.html.eex +++ b/lib/wiki_web/templates/layout/app.html.eex @@ -17,9 +17,9 @@ <%= if @current_user do %>
  • <%= link "New Page", to: Routes.page_path(@conn, :new) %>
  • <%= link "Random", to: Routes.page_path(@conn, :random) %>
  • - <% end %> - <%= if function_exported?(Routes, :live_dashboard_path, 2) do %> -
  • <%= link "LiveDashboard", to: Routes.live_dashboard_path(@conn, :home) %>
  • + <%= if @current_user.is_admin do %> +
  • <%= link "LiveDashboard", to: Routes.live_dashboard_path(@conn, :home) %>
  • + <% end %> <% end %> <%= render "_user_menu.html", assigns %> diff --git a/priv/repo/migrations/20210410184709_users_add_is_admin.exs b/priv/repo/migrations/20210410184709_users_add_is_admin.exs new file mode 100644 index 0000000..479e3b0 --- /dev/null +++ b/priv/repo/migrations/20210410184709_users_add_is_admin.exs @@ -0,0 +1,9 @@ +defmodule Wiki.Repo.Migrations.UsersAddIsAdmin do + use Ecto.Migration + + def change do + alter table(:users) do + add :is_admin, :boolean, default: false + end + end +end