diff --git a/lib/code_corps/policy/helpers.ex b/lib/code_corps/policy/helpers.ex index 5b27d33a8..1aa835a1b 100644 --- a/lib/code_corps/policy/helpers.ex +++ b/lib/code_corps/policy/helpers.ex @@ -48,6 +48,7 @@ defmodule CodeCorps.Policy.Helpers do Returns `CodeCorps.Organization` """ @spec get_organization(struct | Changeset.t | any) :: Organization.t + def get_organization(%{"organization_id" => id}), do: Organization |> Repo.get(id) def get_organization(%{organization_id: id}), do: Organization |> Repo.get(id) def get_organization(%Changeset{changes: %{organization_id: id}}), do: Organization |> Repo.get(id) def get_organization(_), do: nil diff --git a/lib/code_corps/policy/policy.ex b/lib/code_corps/policy/policy.ex index b97f61012..fc5f7d2cf 100644 --- a/lib/code_corps/policy/policy.ex +++ b/lib/code_corps/policy/policy.ex @@ -34,6 +34,8 @@ defmodule CodeCorps.Policy do defp can?(%User{} = current_user, :create, %UserTask{}, %{} = params), do: Policy.UserTask.create?(current_user, params) defp can?(%User{} = current_user, :update, %UserTask{} = user_task, %{}), do: Policy.UserTask.update?(current_user, user_task) defp can?(%User{} = current_user, :delete, %UserTask{} = user_task, %{}), do: Policy.UserTask.delete?(current_user, user_task) + defp can?(%User{} = current_user, :create, %Project{}, %{} = params), do: Policy.Project.create?(current_user, params) + defp can?(%User{} = current_user, :update, %Project{} = project, %{}), do: Policy.Project.update?(current_user, project) defimpl Canada.Can, for: User do # NOTE: Canary sets an :unauthorized and a :not_found handler on a config level @@ -61,9 +63,6 @@ defmodule CodeCorps.Policy do def can?(%User{} = user, :create, %Changeset{data: %Preview{}} = changeset), do: Policy.Preview.create?(user, changeset) - def can?(%User{} = user, :create, %Changeset{data: %Project{}} = changeset), do: Policy.Project.create?(user, changeset) - def can?(%User{} = user, :update, %Project{} = project), do: Policy.Project.update?(user, project) - def can?(%User{} = user, :create, %Changeset{data: %ProjectCategory{}} = changeset), do: Policy.ProjectCategory.create?(user, changeset) def can?(%User{} = user, :delete, %ProjectCategory{} = project_category), do: Policy.ProjectCategory.delete?(user, project_category) diff --git a/lib/code_corps/policy/project.ex b/lib/code_corps/policy/project.ex index 807c795a2..0d34620be 100644 --- a/lib/code_corps/policy/project.ex +++ b/lib/code_corps/policy/project.ex @@ -5,9 +5,9 @@ defmodule CodeCorps.Policy.Project do alias CodeCorps.{Project, User} alias Ecto.Changeset - @spec create?(User.t, Changeset.t) :: boolean - def create?(%User{} = user, %Changeset{} = changeset) do - changeset |> get_organization() |> owned_by?(user) + @spec create?(User.t, map) :: boolean + def create?(%User{} = user, params) do + params |> get_organization() |> owned_by?(user) end @spec update?(User.t, Project.t) :: boolean diff --git a/lib/code_corps_web/controllers/project_controller.ex b/lib/code_corps_web/controllers/project_controller.ex index 5d2987059..4a3abf2ad 100644 --- a/lib/code_corps_web/controllers/project_controller.ex +++ b/lib/code_corps_web/controllers/project_controller.ex @@ -1,39 +1,56 @@ defmodule CodeCorpsWeb.ProjectController do use CodeCorpsWeb, :controller - use JaResource - import CodeCorps.Helpers.Query, only: [approved_filter: 2, slug_finder: 2] + alias CodeCorps.{Helpers.Query, Project, User} - alias CodeCorps.Project + action_fallback CodeCorpsWeb.FallbackController + plug CodeCorpsWeb.Plug.DataToAttributes - plug :load_and_authorize_changeset, model: Project, only: [:create] - plug :load_and_authorize_resource, model: Project, only: [:update] - plug JaResource - - @spec model :: module - def model, do: CodeCorps.Project - - def record(%Plug.Conn{params: %{"project_slug" => project_slug}}, nil) do - Project |> slug_finder(project_slug) + @spec index(Conn.t, map) :: Conn.t + def index(%Conn{} = conn, _params) do + with projects <- Project |> Query.approved_filter(true) |> Repo.all do + conn |> render("index.json-api", data: projects) + end end - def record(%Plug.Conn{} = conn, id), do: super(conn, id) - def handle_index(_conn, %{"slug" => slug}) do - slugged_route = CodeCorps.SluggedRoute |> slug_finder(slug) + @spec index(Conn.t, map) :: Conn.t + def index(%Conn{} = conn, %{"slug" => slug}) do + slugged_route = CodeCorps.SluggedRoute |> Query.slug_finder(slug) + with projects <- Project |> Repo.all(organization_id: slugged_route.organization_id) do + conn |> render("index.json-api", data: projects) + end + end - Project - |> Repo.all(organization_id: slugged_route.organization_id) + @spec show(Conn.t, map) :: Conn.t + def show(%Conn{} = conn, %{"id" => id}) do + with %Project{} = project <- Project |> Repo.get(id) do + conn |> render("show.json-api", data: project) + end end - def handle_index(_conn, _params) do - Project - |> approved_filter(true) + + @spec show(Conn.t, map) :: Conn.t + def show(%Conn{} = conn, %{"project_slug" => project_slug}) do + with %Project{} = project <- Project |> Query.slug_finder(project_slug) do + conn |> render("show.json-api", data: project) + end end - def handle_create(_conn, attributes) do - %Project{} |> Project.create_changeset(attributes) + @spec create(Plug.Conn.t, map) :: Conn.t + def create(%Conn{} = conn, %{} = params) do + with %User{} = current_user <- conn |> Guardian.Plug.current_resource, + {:ok, :authorized} <- current_user |> Policy.authorize(:create, %Project{}, params), + {:ok, %Project{} = project} <- %Project{} |> Project.create_changeset(params) |> Repo.insert do + conn |> put_status(:created) |> render("show.json-api", data: project) + end end - def handle_update(_conn, project, attributes) do - project |> Project.update_changeset(attributes) + @spec update(Conn.t, map) :: Conn.t + def update(%Conn{} = conn, %{"id" => id} = params) do + with %Project{} = project <- Project |> Repo.get(id), + %User{} = current_user <- conn |> Guardian.Plug.current_resource, + {:ok, :authorized} <- current_user |> Policy.authorize(:update, project), + {:ok, %Project{} = project} <- project |> Project.changeset(params) |> Repo.update do + conn |> render("show.json-api", data: project) + end end end