diff --git a/lib/open_pantry/plugs/setup_user.ex b/lib/open_pantry/plugs/setup_user.ex index eaba55e..a54e8d1 100644 --- a/lib/open_pantry/plugs/setup_user.ex +++ b/lib/open_pantry/plugs/setup_user.ex @@ -46,11 +46,15 @@ defmodule OpenPantry.Plugs.SetupUser do end defp user_from_token({:ok, token}, conn) do - %{"aud" => <<"User:", id :: binary >>} = Guardian.decode_and_verify!(token) - user = String.to_integer(id) - |> User.query - |> Repo.one - {conn, user} + try do + %{"aud" => <<"User:", id :: binary >>} = Guardian.decode_and_verify!(token) + user = String.to_integer(id) + |> User.query + |> Repo.one + {conn, user} + rescue + RuntimeError -> {conn, User.guest()} + end end defp user_from_token({:error, :no_token}, conn) do diff --git a/lib/open_pantry/repo.ex b/lib/open_pantry/repo.ex index 5054614..e0f43ff 100644 --- a/lib/open_pantry/repo.ex +++ b/lib/open_pantry/repo.ex @@ -1,4 +1,20 @@ defmodule OpenPantry.Repo do use Ecto.Repo, otp_app: :open_pantry use Scrivener, page_size: 10 + + import Ecto.Query, only: [from: 2] + + alias OpenPantry.User + + def filter_facility(query, conn) do + user = Guardian.Plug.current_resource(conn) + case user do + %User{role: :superadmin} -> + query + %User{role: :admin, facility_id: facility_id} when facility_id > 0 -> + from q in query, where: q.facility_id == ^facility_id + _ -> + from q in query, where: is_nil(q.facility_id) + end + end end diff --git a/lib/open_pantry/web/controllers/facility_controller.ex b/lib/open_pantry/web/controllers/facility_controller.ex index cd6abb7..f4a2b94 100644 --- a/lib/open_pantry/web/controllers/facility_controller.ex +++ b/lib/open_pantry/web/controllers/facility_controller.ex @@ -3,6 +3,8 @@ defmodule OpenPantry.Web.FacilityController do alias OpenPantry.Facility + plug Guardian.Plug.EnsurePermissions, handler: OpenPantry.Web.AuthController, role: [:superadmin] + def index(conn, _params) do facilities = Repo.all(Facility) render(conn, "index.html", facilities: facilities) diff --git a/lib/open_pantry/web/controllers/stock_controller.ex b/lib/open_pantry/web/controllers/stock_controller.ex index 3d05827..acad1fb 100644 --- a/lib/open_pantry/web/controllers/stock_controller.ex +++ b/lib/open_pantry/web/controllers/stock_controller.ex @@ -17,6 +17,7 @@ defmodule OpenPantry.Web.StockController do ), preload: [:food, :meal, :offer] ) + |> Repo.filter_facility(conn) |> Repo.all() render(conn, "index.html", stocks: stocks) end @@ -39,18 +40,18 @@ defmodule OpenPantry.Web.StockController do end def show(conn, %{"id" => id}) do - stock = Repo.get!(Stock, id) + stock = get_stock(id, conn) render(conn, "show.html", stock: stock) end def edit(conn, %{"id" => id}) do - stock = Repo.get!(Stock, id) + stock = get_stock(id, conn) changeset = Stock.changeset(stock) render(conn, "edit.html", stock: stock, changeset: changeset) end def update(conn, %{"id" => id, "stock" => stock_params}) do - stock = Repo.get!(Stock, id) + stock = get_stock(id, conn) changeset = Stock.changeset(stock, stock_params) case Repo.update(changeset) do @@ -64,7 +65,7 @@ defmodule OpenPantry.Web.StockController do end def delete(conn, %{"id" => id}) do - stock = Repo.get!(Stock, id) + stock = get_stock(id, conn) # Here we use delete! (with a bang) because we expect # it to always work (and if it does not, it will raise). @@ -74,4 +75,8 @@ defmodule OpenPantry.Web.StockController do |> put_flash(:info, "Stock deleted successfully.") |> redirect(to: stock_path(conn, :index)) end + + defp get_stock(id, conn) do + Stock |> Repo.filter_facility(conn) |> Repo.get!(id) + end end diff --git a/lib/open_pantry/web/controllers/user_controller.ex b/lib/open_pantry/web/controllers/user_controller.ex index c1c5cce..787645d 100644 --- a/lib/open_pantry/web/controllers/user_controller.ex +++ b/lib/open_pantry/web/controllers/user_controller.ex @@ -5,7 +5,7 @@ defmodule OpenPantry.Web.UserController do alias OpenPantry.User def index(conn, _params) do - users = Repo.all(User) + users = User |> Repo.filter_facility(conn) |> Repo.all render(conn, "index.html", users: users) end @@ -26,18 +26,18 @@ defmodule OpenPantry.Web.UserController do end def show(conn, %{"id" => id}) do - user = get_user(id) + user = get_user(id, conn) render(conn, "show.html", user: user) end def edit(conn, %{"id" => id}) do - user = get_user(id) + user = get_user(id, conn) changeset = User.changeset(user, %{}) render(conn, "edit.html", user: user, changeset: changeset) end def update(conn, %{"id" => id, "user" => user_params}) do - user = get_user(id) + user = get_user(id, conn) case update_user(user, user_params) do {:ok, user} -> @@ -50,7 +50,7 @@ defmodule OpenPantry.Web.UserController do end def delete(conn, %{"id" => id}) do - user = Repo.get!(User, id) + user = get_user(id, conn) {:ok, _user} = Repo.delete(user) conn @@ -58,8 +58,8 @@ defmodule OpenPantry.Web.UserController do |> redirect(to: user_path(conn, :index)) end - defp get_user(id) do - User |> Repo.get!(id) + defp get_user(id, conn) do + User |> Repo.filter_facility(conn) |> Repo.get!(id) end defp create_user(attrs \\ %{}) do diff --git a/lib/open_pantry/web/controllers/user_order_controller.ex b/lib/open_pantry/web/controllers/user_order_controller.ex index faca951..a936646 100644 --- a/lib/open_pantry/web/controllers/user_order_controller.ex +++ b/lib/open_pantry/web/controllers/user_order_controller.ex @@ -1,33 +1,56 @@ defmodule OpenPantry.Web.UserOrderController do use OpenPantry.Web, :controller + require Ecto.Query + + alias Ecto.Query + alias OpenPantry.User alias OpenPantry.UserOrder def index(conn, params) do + orders = + UserOrder + |> Query.preload(:user) + |> filter_facility(conn) + |> orders_for_params(params) + |> Repo.all conn |> setup_channel_credentials(params) - |> render("index.html", orders: orders_for_params(params), conn: conn) + |> render("index.html", orders: orders, conn: conn) end def show(conn, %{"id" => id}) do - order = UserOrder.find(String.to_integer(id), [:user, :stock_distributions, :stocks, :foods, :meals, :offers] ) + order = + UserOrder + |> Query.preload([:user, :stock_distributions, :stocks, :foods, :meals, :offers]) + |> filter_facility(conn) + |> Repo.get!(id) render(conn, "show.html", order: order) end - defp orders_for_params(%{"all" => _}) do - UserOrder.all(:user) + defp orders_for_params(query, %{"all" => _}) do + query end - defp orders_for_params(%{"ready" => _}) do - UserOrder.all(:user) - |> Enum.filter(&(&1.ready_for_pickup)) + defp orders_for_params(query, %{"ready" => _}) do + query |> Query.where(ready_for_pickup: true) end - defp orders_for_params(_) do - UserOrder.all(:user) - |> Enum.filter(&(&1.finalized && !&1.ready_for_pickup)) + defp orders_for_params(query, _) do + query |> Query.where(finalized: true) |> Query.where(ready_for_pickup: false) end + defp filter_facility(query, conn) do + user = Guardian.Plug.current_resource(conn) + case user do + %User{role: :superadmin} -> + query + %User{role: :admin, facility_id: facility_id} when facility_id > 0 -> + Query.from q in query, join: u in assoc(q, :user), where: u.facility_id == ^facility_id + _ -> + Query.from q in query, join: u in assoc(q, :user), where: is_nil(u.facility_id) + end + end # Temporary hack while hardcoding to facility 1, but needs some kind of user token for websocket auth defp setup_channel_credentials(conn, _params) do diff --git a/lib/open_pantry/web/router.ex b/lib/open_pantry/web/router.ex index ba0746c..821a108 100644 --- a/lib/open_pantry/web/router.ex +++ b/lib/open_pantry/web/router.ex @@ -32,7 +32,8 @@ defmodule OpenPantry.Web.Router do pipeline :admin_auth do plug Guardian.Plug.EnsureAuthenticated, handler: OpenPantry.Web.AuthController - plug Guardian.Plug.EnsurePermissions, handler: OpenPantry.Web.AuthController, role: [:superadmin] + plug Guardian.Plug.EnsurePermissions, handler: OpenPantry.Web.AuthController, + one_of: [%{role: [:admin]}, %{role: [:superadmin]}] end pipeline :user_required do