From eb69e14599d3742f2380329c99717e7c8e44e5ef Mon Sep 17 00:00:00 2001 From: Byron Mulvogue Date: Mon, 20 Jul 2020 02:03:57 +0000 Subject: [PATCH] Adding comment index view, comment creation, and comment editing --- .../api/json/comment_controller.ex | 53 ++++++++- .../api/json/image/comment_controller.ex | 112 ++++++++++++++++++ lib/philomena_web/router.ex | 4 +- .../views/api/json/comment_view.ex | 6 + 4 files changed, 173 insertions(+), 2 deletions(-) create mode 100755 lib/philomena_web/controllers/api/json/image/comment_controller.ex diff --git a/lib/philomena_web/controllers/api/json/comment_controller.ex b/lib/philomena_web/controllers/api/json/comment_controller.ex index 1d8457023..cc502b620 100644 --- a/lib/philomena_web/controllers/api/json/comment_controller.ex +++ b/lib/philomena_web/controllers/api/json/comment_controller.ex @@ -2,9 +2,13 @@ defmodule PhilomenaWeb.Api.Json.CommentController do use PhilomenaWeb, :controller alias Philomena.Comments.Comment + alias Philomena.Comments alias Philomena.Repo import Ecto.Query + plug PhilomenaWeb.ApiRequireAuthorizationPlug when action in [:update] + plug PhilomenaWeb.UserAttributionPlug when action in [:update] + def show(conn, %{"id" => id}) do comment = Comment @@ -18,7 +22,7 @@ defmodule PhilomenaWeb.Api.Json.CommentController do |> put_status(:not_found) |> text("") - comment.image.hidden_from_users -> + not Canada.Can.can?(conn.assigns.current_user, :show, comment) -> conn |> put_status(:forbidden) |> text("") @@ -27,4 +31,51 @@ defmodule PhilomenaWeb.Api.Json.CommentController do render(conn, "show.json", comment: comment) end end + + def update(conn, %{"comment" => comment_params, "id" => comment_id}) do + orig_comment = + Comment + |> where(id: ^comment_id) + |> preload([:image, :user]) + |> Repo.one() + + cond do + is_nil(orig_comment) or orig_comment.destroyed_content -> + conn + |> put_status(:not_found) + |> text("") + + not Canada.Can.can?(conn.assigns.current_user, :show, orig_comment) -> + conn + |> put_status(:forbidden) + |> text("") + + not Canada.Can.can?(conn.assigns.current_user, :update, orig_comment) -> + conn + |> put_status(:forbidden) + |> text("") + + true -> + case Comments.update_comment(orig_comment, conn.assigns.current_user, comment_params) do + {:ok, %{comment: comment}} -> + PhilomenaWeb.Endpoint.broadcast!( + "firehose", + "comment:update", + PhilomenaWeb.Api.Json.CommentView.render("show.json", %{ + comment: comment, + current_user: conn.assigns.current_user + }) + ) + + Comments.reindex_comment(comment) + + render(conn, "show.json", %{comment: comment, current_user: conn.assigns.current_user}) + + {:error, :comment, changeset, _changes} -> + conn + |> put_status(:bad_request) + |> render("error.json", changeset: changeset) + end + end + end end diff --git a/lib/philomena_web/controllers/api/json/image/comment_controller.ex b/lib/philomena_web/controllers/api/json/image/comment_controller.ex new file mode 100755 index 000000000..92e71fa9d --- /dev/null +++ b/lib/philomena_web/controllers/api/json/image/comment_controller.ex @@ -0,0 +1,112 @@ +defmodule PhilomenaWeb.Api.Json.Image.CommentController do + use PhilomenaWeb, :controller + + alias Philomena.{Images.Image, Comments.Comment} + alias Philomena.UserStatistics + alias Philomena.Comments + alias Philomena.Images + alias Philomena.Repo + import Ecto.Query + + plug PhilomenaWeb.ApiRequireAuthorizationPlug when action in [:create] + plug PhilomenaWeb.UserAttributionPlug when action in [:create] + + def show(conn, %{"image_id" => image_id, "id" => id}) do + comment = + Comment + |> where(id: ^id) + |> where(image_id: ^image_id) + |> preload([:image, :user]) + |> Repo.one() + + cond do + is_nil(comment) or comment.destroyed_content -> + conn + |> put_status(:not_found) + |> text("") + + not Canada.Can.can?(conn.assigns.current_user, :show, comment) -> + conn + |> put_status(:forbidden) + |> text("") + + true -> + conn + |> put_view(PhilomenaWeb.Api.Json.CommentView) + |> render("show.json", comment: comment) + end + end + + def index(conn, %{"image_id" => image_id}) do + comments = + Comment + |> where(image_id: ^image_id) + |> where(destroyed_content: false) + |> preload([:image, :user]) + |> order_by(asc: :id) + |> Repo.paginate(conn.assigns.scrivener) + + cond do + Enum.empty?(comments.entries) or + Canada.Can.can?(conn.assigns.current_user, :show, hd(comments.entries).image) -> + conn + |> put_view(PhilomenaWeb.Api.Json.CommentView) + |> render("index.json", comments: comments, total: comments.total_entries) + + true -> + conn + |> put_status(:forbidden) + |> text("") + end + end + + def create(conn, %{"comment" => comment_params, "image_id" => image_id}) do + attributes = conn.assigns.attributes + + image = + Image + |> where(id: ^image_id) + |> preload([:tags, :user, :intensity]) + |> Repo.one() + + cond do + is_nil(image) -> + conn + |> put_status(:not_found) + |> text("") + + not Canada.Can.can?(conn.assigns.current_user, :create_comment, image) -> + conn + |> put_status(:forbidden) + |> text("") + + true -> + case Comments.create_comment(image, attributes, comment_params) do + {:ok, %{comment: comment}} -> + PhilomenaWeb.Endpoint.broadcast!( + "firehose", + "comment:create", + PhilomenaWeb.Api.Json.CommentView.render("show.json", + comment: comment, + current_user: conn.assigns.current_user + ) + ) + + Comments.notify_comment(comment) + Comments.reindex_comment(comment) + Images.reindex_image(image) + UserStatistics.inc_stat(conn.assigns.current_user, :comments_posted) + + conn + |> put_view(PhilomenaWeb.Api.Json.CommentView) + |> render("show.json", comment: comment, current_user: conn.assigns.current_user) + + {:error, :comment, changeset, _} -> + conn + |> put_status(:bad_request) + |> put_view(PhilomenaWeb.Api.Json.CommentView) + |> render("error.json", changeset: changeset) + end + end + end +end diff --git a/lib/philomena_web/router.ex b/lib/philomena_web/router.ex index 129f3ab69..3ac517ec5 100644 --- a/lib/philomena_web/router.ex +++ b/lib/philomena_web/router.ex @@ -111,7 +111,9 @@ defmodule PhilomenaWeb.Router do resources "/featured", FeaturedController, only: [:show], singleton: true end - resources "/images", ImageController, only: [:show, :create] + resources "/images", ImageController, only: [:show, :create] do + resources "/comments", Image.CommentController, only: [:index, :create] + end scope "/search", Search, as: :search do resources "/reverse", ReverseController, only: [:create] diff --git a/lib/philomena_web/views/api/json/comment_view.ex b/lib/philomena_web/views/api/json/comment_view.ex index 5d80b42b7..a75c58250 100644 --- a/lib/philomena_web/views/api/json/comment_view.ex +++ b/lib/philomena_web/views/api/json/comment_view.ex @@ -60,4 +60,10 @@ defmodule PhilomenaWeb.Api.Json.CommentView do edit_reason: comment.edit_reason } end + + def render("error.json", %{changeset: changeset}) do + %{ + errors: Ecto.Changeset.traverse_errors(changeset, &translate_error/1) + } + end end