defmodule FrenzyWeb.PipelineController do use FrenzyWeb, :controller alias Frenzy.{Repo, Feed, PipelineStage} alias FrenzyWeb.Router.Helpers, as: Routes alias FrenzyWeb.Endpoint import Ecto.Query plug :user_owns_feed plug :user_owns_stage defp user_owns_feed(%Plug.Conn{path_params: %{"feed_id" => feed_id}} = conn, _opts) do user = conn.assigns[:user] feed = Repo.get(Feed, feed_id) |> Repo.preload(:pipeline_stages) if Enum.any?(user.groups, fn g -> g.id == feed.group_id end) do conn |> assign(:feed, feed) else conn |> put_flash(:error, "You do not have permission to access that resource.") |> redirect(to: Routes.group_path(Endpoint, :index)) |> halt() end end defp user_owns_feed(conn, _opts), do: conn defp user_owns_stage(%Plug.Conn{path_params: %{"stage_id" => stage_id}} = conn, _opts) do feed = conn.assigns[:feed] stage = Repo.get(PipelineStage, stage_id) if stage.feed_id == feed.id do conn |> assign(:stage, stage) else conn |> put_flash(:error, "You do not have permission to access that resource.") |> redirect(to: Routes.group_path(Endpoint, :index)) |> halt() end end defp user_owns_stage(conn, _opts), do: conn def edit(conn, %{"stage_id" => stage_id}) do feed = conn.assigns[:feed] stage = conn.assigns[:stage] {:ok, options_json} = Jason.encode(stage.options, pretty: true) changeset = PipelineStage.changeset(stage, %{ options: options_json }) render(conn, "edit.html", %{ feed: feed, stage: stage, changeset: changeset }) end def update(conn, %{"pipeline_stage" => %{"options" => options_json}}) do feed = conn.assigns[:feed] stage = conn.assigns[:stage] with {:ok, options} <- Jason.decode(options_json), {:ok, options} <- apply(String.to_existing_atom("Elixir." <> stage.module_name), :validate_opts, [ options ]) do changeset = PipelineStage.changeset(stage, %{options: options}) {:ok, _stage} = Repo.update(changeset) conn |> put_flash(:info, "Pipeline Stage updated") |> redirect(to: Routes.feed_path(Endpoint, :edit, feed.id)) else result -> error_changeset = PipelineStage.changeset(stage, %{options: options_json}) conn |> put_flash(:error, "Unable to update pipeline stage: #{inspect(result)}") |> render("edit.html", %{ feed: feed, stage: stage, changeset: error_changeset }) end end def new(conn, _params) do feed = conn.assigns[:feed] changeset = PipelineStage.changeset(%PipelineStage{}, %{ index: feed.pipeline_stages |> Enum.count(), options: "{}" }) render(conn, "new.html", %{ feed: feed, changeset: changeset }) end def create(conn, %{ "pipeline_stage" => %{ "index" => index, "module_name" => module_name, "options" => options_json } = params }) do feed = conn.assigns[:feed] with {index, _} <- Integer.parse(index), module_atom <- String.to_existing_atom("Elixir." <> module_name), {:ok, options} <- Jason.decode(options_json), {:ok, options} <- apply(module_atom, :validate_opts, [options]) do changeset = Ecto.build_assoc(feed, :pipeline_stages, %{ index: index, module_name: module_name, options: options }) {:ok, _stage} = Repo.insert(changeset) conn |> put_flash(:info, "Pipeline Stage created") |> redirect(to: Routes.feed_path(Endpoint, :edit, feed.id)) else result -> error_changeset = PipelineStage.changeset(%PipelineStage{}, params) conn |> put_flash(:error, "Unable to create pipeline stage: #{inspect(result)}") |> render("new.html", %{ feed: feed, changeset: error_changeset }) end end def delete(conn, _params) do feed = conn.assigns[:feed] stage = conn.assigns[:stage] {:ok, _stage} = Repo.delete(stage) conn |> put_flash(:info, "Pipeline Stage deleted") |> redirect(to: Routes.feed_path(Endpoint, :edit, feed.id)) end end