From e5266db21ea13737ad3298dd1cecb9c7f69a9489 Mon Sep 17 00:00:00 2001 From: "byte[]" Date: Sat, 14 Dec 2019 14:46:50 -0500 Subject: [PATCH] add loader plugs --- lib/philomena/topics.ex | 1 - lib/philomena/users/ability.ex | 4 + .../controllers/forum_controller.ex | 2 +- .../image/comment/history_controller.ex | 6 +- .../image/comment/report_controller.ex | 7 +- .../controllers/image/comment_controller.ex | 9 +- .../controllers/topic/hide_controller.ex | 21 ++--- .../controllers/topic/lock_controller.ex | 23 ++--- .../controllers/topic/move_controller.ex | 32 +++---- .../controllers/topic/post/hide_controller.ex | 2 + .../topic/post/history_controller.ex | 52 +---------- .../topic/post/report_controller.ex | 55 +---------- .../controllers/topic/post_controller.ex | 31 +------ .../controllers/topic/read_controller.ex | 22 ++--- .../controllers/topic/stick_controller.ex | 23 ++--- .../topic/subscription_controller.ex | 27 ++---- .../controllers/topic_controller.ex | 10 +- lib/philomena_web/plugs/load_comment_plug.ex | 35 +++++++ lib/philomena_web/plugs/load_post_plug.ex | 35 +++++++ lib/philomena_web/plugs/load_topic_plug.ex | 35 +++++++ .../templates/forum/index.html.slime | 4 +- .../templates/forum/show.html.slime | 2 +- .../templates/topic/show.html.slime | 93 ++++++++++--------- 23 files changed, 247 insertions(+), 284 deletions(-) create mode 100644 lib/philomena_web/plugs/load_comment_plug.ex create mode 100644 lib/philomena_web/plugs/load_post_plug.ex create mode 100644 lib/philomena_web/plugs/load_topic_plug.ex diff --git a/lib/philomena/topics.ex b/lib/philomena/topics.ex index 1753b0fb..741343db 100644 --- a/lib/philomena/topics.ex +++ b/lib/philomena/topics.ex @@ -245,7 +245,6 @@ defmodule Philomena.Topics do |> Repo.update() end - def clear_notification(nil, _user), do: nil def clear_notification(_topic, nil), do: nil def clear_notification(topic, user) do Notifications.delete_unread_notification("Topic", topic.id, user) diff --git a/lib/philomena/users/ability.ex b/lib/philomena/users/ability.ex index 540f364f..174cd8d3 100644 --- a/lib/philomena/users/ability.ex +++ b/lib/philomena/users/ability.ex @@ -77,6 +77,9 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do def can?(%User{role: "moderator"}, _action, SubnetBan), do: true def can?(%User{role: "moderator"}, _action, FingerprintBan), do: true + # Hide topics + def can?(%User{role: "moderator"}, :hide, %Topic{}), do: true + # # Assistants can... # @@ -102,6 +105,7 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do # Topic assistant actions def can?(%User{role: "assistant", role_map: %{"Topic" => "moderator"}}, :show, %Topic{}), do: true def can?(%User{role: "assistant", role_map: %{"Topic" => "moderator"}}, :edit, %Topic{}), do: true + def can?(%User{role: "assistant", role_map: %{"Topic" => "moderator"}}, :hide, %Topic{}), do: true def can?(%User{role: "assistant", role_map: %{"Topic" => "moderator"}}, :show, %Post{}), do: true def can?(%User{role: "assistant", role_map: %{"Topic" => "moderator"}}, :edit, %Post{}), do: true def can?(%User{role: "assistant", role_map: %{"Topic" => "moderator"}}, :hide, %Post{}), do: true diff --git a/lib/philomena_web/controllers/forum_controller.ex b/lib/philomena_web/controllers/forum_controller.ex index 4ae34a22..7eac8537 100644 --- a/lib/philomena_web/controllers/forum_controller.ex +++ b/lib/philomena_web/controllers/forum_controller.ex @@ -12,7 +12,7 @@ defmodule PhilomenaWeb.ForumController do forums = Forum |> order_by(asc: :name) - |> preload([last_post: [:topic, :user]]) + |> preload([last_post: [:user, topic: :forum]]) |> Repo.all() |> Enum.filter(&Canada.Can.can?(user, :show, &1)) diff --git a/lib/philomena_web/controllers/image/comment/history_controller.ex b/lib/philomena_web/controllers/image/comment/history_controller.ex index b2bae9e0..1c7f409e 100644 --- a/lib/philomena_web/controllers/image/comment/history_controller.ex +++ b/lib/philomena_web/controllers/image/comment/history_controller.ex @@ -3,14 +3,14 @@ defmodule PhilomenaWeb.Image.Comment.HistoryController do alias Philomena.Versions.Version alias Philomena.Versions - alias Philomena.Comments.Comment alias Philomena.Images.Image alias Philomena.Repo import Ecto.Query plug PhilomenaWeb.CanaryMapPlug, index: :show plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true - plug :load_and_authorize_resource, model: Comment, id_name: "comment_id", persisted: true, preload: [:image, user: [awards: :badge]] + + plug PhilomenaWeb.LoadCommentPlug def index(conn, _params) do comment = conn.assigns.comment @@ -25,4 +25,4 @@ defmodule PhilomenaWeb.Image.Comment.HistoryController do render(conn, "index.html", versions: versions) end -end \ No newline at end of file +end diff --git a/lib/philomena_web/controllers/image/comment/report_controller.ex b/lib/philomena_web/controllers/image/comment/report_controller.ex index ae8a00dd..6cb85df4 100644 --- a/lib/philomena_web/controllers/image/comment/report_controller.ex +++ b/lib/philomena_web/controllers/image/comment/report_controller.ex @@ -3,7 +3,6 @@ defmodule PhilomenaWeb.Image.Comment.ReportController do alias PhilomenaWeb.ReportController alias PhilomenaWeb.ReportView - alias Philomena.Comments.Comment alias Philomena.Images.Image alias Philomena.Reports.Report alias Philomena.Reports @@ -11,9 +10,11 @@ defmodule PhilomenaWeb.Image.Comment.ReportController do plug PhilomenaWeb.FilterBannedUsersPlug plug PhilomenaWeb.UserAttributionPlug plug PhilomenaWeb.CaptchaPlug when action in [:create] + plug PhilomenaWeb.CanaryMapPlug, new: :show, create: :show plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true, preload: [:tags] - plug :load_and_authorize_resource, model: Comment, id_name: "comment_id", persisted: true, preload: [:image] + + plug PhilomenaWeb.LoadCommentPlug def new(conn, _params) do comment = conn.assigns.comment @@ -33,4 +34,4 @@ defmodule PhilomenaWeb.Image.Comment.ReportController do ReportController.create(conn, action, comment, "Comment", params) end -end \ No newline at end of file +end diff --git a/lib/philomena_web/controllers/image/comment_controller.ex b/lib/philomena_web/controllers/image/comment_controller.ex index 4dca629c..0dc6f46b 100644 --- a/lib/philomena_web/controllers/image/comment_controller.ex +++ b/lib/philomena_web/controllers/image/comment_controller.ex @@ -8,15 +8,16 @@ defmodule PhilomenaWeb.Image.CommentController do alias Philomena.Repo import Ecto.Query + plug PhilomenaWeb.FilterBannedUsersPlug when action in [:create, :edit, :update] + plug PhilomenaWeb.UserAttributionPlug when action in [:create] + plug PhilomenaWeb.CanaryMapPlug, create: :create_comment, edit: :create_comment, update: :create_comment plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true # Undo the previous private parameter screwery + plug PhilomenaWeb.LoadCommentPlug, [param: "id"] when action in [:edit, :update] plug PhilomenaWeb.CanaryMapPlug, create: :create, edit: :edit, update: :edit - plug :load_and_authorize_resource, model: Comment, only: [:show, :edit, :update], preload: [:image, user: [awards: :badge]] - - plug PhilomenaWeb.FilterBannedUsersPlug when action in [:create, :edit, :update] - plug PhilomenaWeb.UserAttributionPlug when action in [:create] + plug :authorize_resource, model: Comment, only: [:show, :edit, :update], preload: [:image, user: [awards: :badge]] def index(conn, %{"comment_id" => comment_id}) do comment = diff --git a/lib/philomena_web/controllers/topic/hide_controller.ex b/lib/philomena_web/controllers/topic/hide_controller.ex index 5eec402c..beaf420d 100644 --- a/lib/philomena_web/controllers/topic/hide_controller.ex +++ b/lib/philomena_web/controllers/topic/hide_controller.ex @@ -2,14 +2,16 @@ defmodule PhilomenaWeb.Topic.HideController do import Plug.Conn use PhilomenaWeb, :controller + alias Philomena.Forums.Forum alias Philomena.Topics.Topic alias Philomena.Topics - alias Philomena.Repo - import Ecto.Query - plug :load_topic + plug PhilomenaWeb.CanaryMapPlug, create: :show, delete: :show + plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true + + plug PhilomenaWeb.LoadTopicPlug plug PhilomenaWeb.CanaryMapPlug, create: :hide, delete: :hide - plug :authorize_resource, model: Topic, id_name: "topic_id", persisted: true + plug :authorize_resource, model: Topic, persisted: true def create(conn, %{"topic" => topic_params}) do topic = conn.assigns.topic @@ -21,6 +23,7 @@ defmodule PhilomenaWeb.Topic.HideController do conn |> put_flash(:info, "Topic successfully hidden!") |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) + {:error, _changeset} -> conn |> put_flash(:error, "Unable to hide the topic!") @@ -36,19 +39,11 @@ defmodule PhilomenaWeb.Topic.HideController do conn |> put_flash(:info, "Topic successfully restored!") |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) + {:error, _changeset} -> conn |> put_flash(:error, "Unable to restore the topic!") |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) end end - - defp load_topic(conn, _opts) do - topic = Topic - |> where(forum_id: ^conn.params["forum_id"], slug: ^conn.params["topic_id"]) - |> preload([:forum]) - |> Repo.one() - - Plug.Conn.assign(conn, :topic, topic) - end end diff --git a/lib/philomena_web/controllers/topic/lock_controller.ex b/lib/philomena_web/controllers/topic/lock_controller.ex index 6a50ddcc..b1ade7ab 100644 --- a/lib/philomena_web/controllers/topic/lock_controller.ex +++ b/lib/philomena_web/controllers/topic/lock_controller.ex @@ -2,14 +2,16 @@ defmodule PhilomenaWeb.Topic.LockController do import Plug.Conn use PhilomenaWeb, :controller + alias Philomena.Forums.Forum alias Philomena.Topics.Topic alias Philomena.Topics - alias Philomena.Repo - import Ecto.Query - plug :load_topic - plug PhilomenaWeb.CanaryMapPlug, create: :lock, delete: :unlock - plug :authorize_resource, model: Topic, id_name: "topic_id", persisted: true + plug PhilomenaWeb.CanaryMapPlug, create: :show, delete: :show + plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true + + plug PhilomenaWeb.LoadTopicPlug + plug PhilomenaWeb.CanaryMapPlug, create: :hide, delete: :hide + plug :authorize_resource, model: Topic, persisted: true def create(conn, %{"topic" => topic_params}) do topic = conn.assigns.topic @@ -20,6 +22,7 @@ defmodule PhilomenaWeb.Topic.LockController do conn |> put_flash(:info, "Topic successfully locked!") |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) + {:error, _changeset} -> conn |> put_flash(:error, "Unable to lock the topic!") @@ -35,19 +38,11 @@ defmodule PhilomenaWeb.Topic.LockController do conn |> put_flash(:info, "Topic successfully unlocked!") |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) + {:error, _changeset} -> conn |> put_flash(:error, "Unable to unlock the topic!") |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) end end - - defp load_topic(conn, _opts) do - topic = Topic - |> where(forum_id: ^conn.params["forum_id"], slug: ^conn.params["topic_id"]) - |> preload([:forum]) - |> Repo.one() - - Plug.Conn.assign(conn, :topic, topic) - end end diff --git a/lib/philomena_web/controllers/topic/move_controller.ex b/lib/philomena_web/controllers/topic/move_controller.ex index 86767640..efee8401 100644 --- a/lib/philomena_web/controllers/topic/move_controller.ex +++ b/lib/philomena_web/controllers/topic/move_controller.ex @@ -2,42 +2,34 @@ defmodule PhilomenaWeb.Topic.MoveController do import Plug.Conn use PhilomenaWeb, :controller + alias Philomena.Forums.Forum alias Philomena.Topics.Topic alias Philomena.Topics alias Philomena.Repo - import Ecto.Query - plug :load_topic - plug PhilomenaWeb.CanaryMapPlug, create: :move - plug :authorize_resource, model: Topic, id_name: "topic_id", persisted: true + plug PhilomenaWeb.CanaryMapPlug, create: :show, delete: :show + plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true - # intentionally blank - # todo: moving - def create(conn, %{"topic" => topic_params}) do + plug PhilomenaWeb.LoadTopicPlug + plug PhilomenaWeb.CanaryMapPlug, create: :hide, delete: :hide + plug :authorize_resource, model: Topic, persisted: true + + def create(conn, %{"topic" => %{"target_forum_id" => target_id}}) do topic = conn.assigns.topic - target_forum_id = String.to_integer(topic_params["target_forum_id"]) + target_forum_id = String.to_integer(target_id) case Topics.move_topic(topic, target_forum_id) do {:ok, %{topic: topic}} -> - topic = Repo.preload(topic, :forum) + topic = Repo.preload(topic, :forum, force: true) conn |> put_flash(:info, "Topic successfully moved!") |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) - {:error, _changeset} -> - topic = Repo.preload(topic, :forum) + {:error, _changeset} -> conn |> put_flash(:error, "Unable to move the topic!") - |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) + |> redirect(to: Routes.forum_topic_path(conn, :show, conn.assigns.forum, topic)) end end - - defp load_topic(conn, _opts) do - topic = Topic - |> where(forum_id: ^conn.params["forum_id"], slug: ^conn.params["topic_id"]) - |> Repo.one() - - Plug.Conn.assign(conn, :topic, topic) - end end diff --git a/lib/philomena_web/controllers/topic/post/hide_controller.ex b/lib/philomena_web/controllers/topic/post/hide_controller.ex index c659b91b..9725090f 100644 --- a/lib/philomena_web/controllers/topic/post/hide_controller.ex +++ b/lib/philomena_web/controllers/topic/post/hide_controller.ex @@ -18,6 +18,7 @@ defmodule PhilomenaWeb.Topic.Post.HideController do conn |> put_flash(:info, "Post successfully hidden!") |> redirect(to: Routes.forum_topic_path(conn, :show, post.topic.forum, post.topic) <> "#post_#{post.id}") + {:error, _changeset} -> conn |> put_flash(:error, "Unable to hide post!") @@ -35,6 +36,7 @@ defmodule PhilomenaWeb.Topic.Post.HideController do conn |> put_flash(:info, "Post successfully unhidden!") |> redirect(to: Routes.forum_topic_path(conn, :show, post.topic.forum, post.topic) <> "#post_#{post.id}") + {:error, _changeset} -> conn |> put_flash(:error, "Unable to unhide post!") diff --git a/lib/philomena_web/controllers/topic/post/history_controller.ex b/lib/philomena_web/controllers/topic/post/history_controller.ex index fb4556d4..3a6947a2 100644 --- a/lib/philomena_web/controllers/topic/post/history_controller.ex +++ b/lib/philomena_web/controllers/topic/post/history_controller.ex @@ -4,15 +4,14 @@ defmodule PhilomenaWeb.Topic.Post.HistoryController do alias Philomena.Versions.Version alias Philomena.Versions alias Philomena.Forums.Forum - alias Philomena.Topics.Topic - alias Philomena.Posts.Post alias Philomena.Repo import Ecto.Query plug PhilomenaWeb.CanaryMapPlug, index: :show plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true - plug :load_topic - plug :load_post + + plug PhilomenaWeb.LoadTopicPlug + plug PhilomenaWeb.LoadPostPlug def index(conn, _params) do post = conn.assigns.post @@ -27,47 +26,4 @@ defmodule PhilomenaWeb.Topic.Post.HistoryController do render(conn, "index.html", versions: versions) end - - defp load_topic(conn, _opts) do - user = conn.assigns.current_user - forum = conn.assigns.forum - topic = - Topic - |> where(forum_id: ^forum.id, slug: ^conn.params["topic_id"]) - |> preload(:forum) - |> Repo.one() - - cond do - is_nil(topic) -> - PhilomenaWeb.NotFoundPlug.call(conn) - - not Canada.Can.can?(user, :show, topic) -> - PhilomenaWeb.NotAuthorizedPlug.call(conn) - - true -> - Plug.Conn.assign(conn, :topic, topic) - end - end - - defp load_post(conn, _opts) do - user = conn.assigns.current_user - topic = conn.assigns.topic - - post = - Post - |> where(topic_id: ^topic.id, id: ^conn.params["post_id"]) - |> preload(topic: :forum, user: [awards: :badge]) - |> Repo.one() - - cond do - is_nil(post) -> - PhilomenaWeb.NotFoundPlug.call(conn) - - not Canada.Can.can?(user, :show, post) -> - PhilomenaWeb.NotAuthorizedPlug.call(conn) - - true -> - Plug.Conn.assign(conn, :post, post) - end - end -end \ No newline at end of file +end diff --git a/lib/philomena_web/controllers/topic/post/report_controller.ex b/lib/philomena_web/controllers/topic/post/report_controller.ex index 20e6e23e..88d4db46 100644 --- a/lib/philomena_web/controllers/topic/post/report_controller.ex +++ b/lib/philomena_web/controllers/topic/post/report_controller.ex @@ -4,20 +4,18 @@ defmodule PhilomenaWeb.Topic.Post.ReportController do alias PhilomenaWeb.ReportController alias PhilomenaWeb.ReportView alias Philomena.Forums.Forum - alias Philomena.Topics.Topic - alias Philomena.Posts.Post alias Philomena.Reports.Report alias Philomena.Reports - alias Philomena.Repo - import Ecto.Query plug PhilomenaWeb.FilterBannedUsersPlug plug PhilomenaWeb.UserAttributionPlug plug PhilomenaWeb.CaptchaPlug when action in [:create] + plug PhilomenaWeb.CanaryMapPlug, new: :show, create: :show plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true - plug :load_topic - plug :load_post + + plug PhilomenaWeb.LoadTopicPlug + plug PhilomenaWeb.LoadPostPlug def new(conn, _params) do topic = conn.assigns.topic @@ -39,47 +37,4 @@ defmodule PhilomenaWeb.Topic.Post.ReportController do ReportController.create(conn, action, post, "Post", params) end - - defp load_topic(conn, _opts) do - user = conn.assigns.current_user - forum = conn.assigns.forum - topic = - Topic - |> where(forum_id: ^forum.id, slug: ^conn.params["topic_id"]) - |> preload(:forum) - |> Repo.one() - - cond do - is_nil(topic) -> - PhilomenaWeb.NotFoundPlug.call(conn) - - not Canada.Can.can?(user, :show, topic) -> - PhilomenaWeb.NotAuthorizedPlug.call(conn) - - true -> - Plug.Conn.assign(conn, :topic, topic) - end - end - - defp load_post(conn, _opts) do - user = conn.assigns.current_user - topic = conn.assigns.topic - - post = - Post - |> where(topic_id: ^topic.id, id: ^conn.params["post_id"]) - |> preload(topic: :forum) - |> Repo.one() - - cond do - is_nil(post) -> - PhilomenaWeb.NotFoundPlug.call(conn) - - not Canada.Can.can?(user, :show, post) -> - PhilomenaWeb.NotAuthorizedPlug.call(conn) - - true -> - Plug.Conn.assign(conn, :post, post) - end - end -end \ No newline at end of file +end diff --git a/lib/philomena_web/controllers/topic/post_controller.ex b/lib/philomena_web/controllers/topic/post_controller.ex index 7e11f389..b046921a 100644 --- a/lib/philomena_web/controllers/topic/post_controller.ex +++ b/lib/philomena_web/controllers/topic/post_controller.ex @@ -4,20 +4,20 @@ defmodule PhilomenaWeb.Topic.PostController do alias Philomena.{Forums.Forum, Topics.Topic, Posts.Post} alias Philomena.Posts alias Philomena.UserStatistics - alias Philomena.Repo - import Ecto.Query plug PhilomenaWeb.FilterBannedUsersPlug plug PhilomenaWeb.UserAttributionPlug + plug PhilomenaWeb.CanaryMapPlug, create: :show, edit: :show, update: :show plug :load_and_authorize_resource, model: Forum, id_field: "short_name", id_name: "forum_id", persisted: true - plug :load_topic + plug PhilomenaWeb.LoadTopicPlug plug PhilomenaWeb.CanaryMapPlug, create: :create_post, edit: :create_post, update: :create_post - plug :authorize_resource, model: Topic, id_field: "slug", id_name: "topic_id", persisted: true + plug :authorize_resource, model: Topic, persisted: true + plug PhilomenaWeb.LoadPostPlug, [param: "id"] when action in [:edit, :update] plug PhilomenaWeb.CanaryMapPlug, edit: :edit, update: :edit - plug :load_and_authorize_resource, model: Post, only: [:edit, :update], preload: [topic: :forum] + plug :authorize_resource, model: Post, only: [:edit, :update] def create(conn, %{"post" => post_params}) do attributes = conn.assigns.attributes @@ -62,25 +62,4 @@ defmodule PhilomenaWeb.Topic.PostController do render(conn, "edit.html", post: conn.assigns.post, changeset: changeset) end end - - defp load_topic(conn, _opts) do - user = conn.assigns.current_user - forum = conn.assigns.forum - topic = - Topic - |> where(forum_id: ^forum.id, slug: ^conn.params["topic_id"]) - |> preload(:forum) - |> Repo.one() - - cond do - is_nil(topic) -> - PhilomenaWeb.NotFoundPlug.call(conn) - - not Canada.Can.can?(user, :show, topic) -> - PhilomenaWeb.NotAuthorizedPlug.call(conn) - - true -> - Plug.Conn.assign(conn, :topic, topic) - end - end end diff --git a/lib/philomena_web/controllers/topic/read_controller.ex b/lib/philomena_web/controllers/topic/read_controller.ex index 01684c36..aac0ae20 100644 --- a/lib/philomena_web/controllers/topic/read_controller.ex +++ b/lib/philomena_web/controllers/topic/read_controller.ex @@ -3,28 +3,18 @@ defmodule PhilomenaWeb.Topic.ReadController do use PhilomenaWeb, :controller alias Philomena.Forums.Forum - alias Philomena.Topics.Topic alias Philomena.Topics - alias Philomena.Repo - import Ecto.Query + plug PhilomenaWeb.CanaryMapPlug, create: :show plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true - def create(conn, %{"topic_id" => slug}) do - topic = load_topic(conn, slug) + plug PhilomenaWeb.LoadTopicPlug, show_hidden: true + + def create(conn, _params) do user = conn.assigns.current_user - Topics.clear_notification(topic, user) + Topics.clear_notification(conn.assigns.topic, user) send_resp(conn, :ok, "") end - - defp load_topic(conn, slug) do - forum = conn.assigns.forum - - Topic - |> where(forum_id: ^forum.id, slug: ^slug, hidden_from_users: false) - |> preload(:user) - |> Repo.one() - end -end \ No newline at end of file +end diff --git a/lib/philomena_web/controllers/topic/stick_controller.ex b/lib/philomena_web/controllers/topic/stick_controller.ex index e6d4ecc0..522f3529 100644 --- a/lib/philomena_web/controllers/topic/stick_controller.ex +++ b/lib/philomena_web/controllers/topic/stick_controller.ex @@ -2,14 +2,16 @@ defmodule PhilomenaWeb.Topic.StickController do import Plug.Conn use PhilomenaWeb, :controller + alias Philomena.Forums.Forum alias Philomena.Topics.Topic alias Philomena.Topics - alias Philomena.Repo - import Ecto.Query - plug :load_topic - plug PhilomenaWeb.CanaryMapPlug, create: :stick, delete: :stick - plug :authorize_resource, model: Topic, id_name: "topic_id", persisted: true + plug PhilomenaWeb.CanaryMapPlug, create: :show + plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true + + plug PhilomenaWeb.LoadTopicPlug + plug PhilomenaWeb.CanaryMapPlug, create: :hide, delete: :hide + plug :authorize_resource, model: Topic, persisted: true def create(conn, _opts) do topic = conn.assigns.topic @@ -19,6 +21,7 @@ defmodule PhilomenaWeb.Topic.StickController do conn |> put_flash(:info, "Topic successfully stickied!") |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) + {:error, _changeset} -> conn |> put_flash(:error, "Unable to stick the topic!") @@ -34,19 +37,11 @@ defmodule PhilomenaWeb.Topic.StickController do conn |> put_flash(:info, "Topic successfully unstickied!") |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) + {:error, _changeset} -> conn |> put_flash(:error, "Unable to unstick the topic!") |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) end end - - defp load_topic(conn, _opts) do - topic = Topic - |> where(forum_id: ^conn.params["forum_id"], slug: ^conn.params["topic_id"]) - |> preload([:forum]) - |> Repo.one() - - Plug.Conn.assign(conn, :topic, topic) - end end diff --git a/lib/philomena_web/controllers/topic/subscription_controller.ex b/lib/philomena_web/controllers/topic/subscription_controller.ex index d46280a8..921f2559 100644 --- a/lib/philomena_web/controllers/topic/subscription_controller.ex +++ b/lib/philomena_web/controllers/topic/subscription_controller.ex @@ -1,15 +1,17 @@ defmodule PhilomenaWeb.Topic.SubscriptionController do use PhilomenaWeb, :controller - alias Philomena.{Topics, Topics.Topic, Forums.Forum} - alias Philomena.Repo - import Ecto.Query + alias Philomena.Forums.Forum + alias Philomena.Topics plug PhilomenaWeb.CanaryMapPlug, create: :show, delete: :show plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true - def create(conn, %{"topic_id" => slug}) do - topic = load_topic(conn, slug) + plug PhilomenaWeb.LoadTopicPlug, [show_hidden: true] when action in [:delete] + plug PhilomenaWeb.LoadTopicPlug when action in [:create] + + def create(conn, _params) do + topic = conn.assigns.topic user = conn.assigns.current_user case Topics.create_subscription(topic, user) do @@ -21,8 +23,8 @@ defmodule PhilomenaWeb.Topic.SubscriptionController do end end - def delete(conn, %{"topic_id" => slug}) do - topic = load_topic(conn, slug) + def delete(conn, _params) do + topic = conn.assigns.topic user = conn.assigns.current_user case Topics.delete_subscription(topic, user) do @@ -33,13 +35,4 @@ defmodule PhilomenaWeb.Topic.SubscriptionController do render(conn, "_error.html", layout: false) end end - - defp load_topic(conn, slug) do - forum = conn.assigns.forum - - Topic - |> where(forum_id: ^forum.id, slug: ^slug, hidden_from_users: false) - |> preload(:user) - |> Repo.one() - end -end \ No newline at end of file +end diff --git a/lib/philomena_web/controllers/topic_controller.ex b/lib/philomena_web/controllers/topic_controller.ex index e557026f..36dd46d7 100644 --- a/lib/philomena_web/controllers/topic_controller.ex +++ b/lib/philomena_web/controllers/topic_controller.ex @@ -15,13 +15,11 @@ defmodule PhilomenaWeb.TopicController do plug PhilomenaWeb.CanaryMapPlug, new: :show, create: :show plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true - def show(conn, %{"id" => slug} = params) do + plug PhilomenaWeb.LoadTopicPlug, [param: "id"] when action in [:show] + + def show(conn, params) do forum = conn.assigns.forum - topic = - Topic - |> where(forum_id: ^forum.id, slug: ^slug) - |> preload([:deleted_by, :user, poll: :options]) - |> Repo.one() + topic = conn.assigns.topic user = conn.assigns.current_user diff --git a/lib/philomena_web/plugs/load_comment_plug.ex b/lib/philomena_web/plugs/load_comment_plug.ex new file mode 100644 index 00000000..06e6228a --- /dev/null +++ b/lib/philomena_web/plugs/load_comment_plug.ex @@ -0,0 +1,35 @@ +defmodule PhilomenaWeb.LoadCommentPlug do + alias Philomena.Comments.Comment + alias Philomena.Repo + + import Plug.Conn, only: [assign: 3] + import Canada.Can, only: [can?: 3] + import Ecto.Query + + def init(opts), + do: opts + + def call(%{assigns: %{image: image}} = conn, opts) do + param = Keyword.get(opts, :param, "comment_id") + show_hidden = Keyword.get(opts, :show_hidden, false) + + Comment + |> where(image_id: ^image.id, id: ^to_string(conn.params[param])) + |> preload([:image, user: [awards: :badge]]) + |> Repo.one() + |> maybe_hide_comment(conn, show_hidden) + end + + defp maybe_hide_comment(nil, conn, _show_hidden), + do: PhilomenaWeb.NotFoundPlug.call(conn) + + defp maybe_hide_comment(%{hidden_from_users: false} = comment, conn, _show_hidden), + do: assign(conn, :comment, comment) + + defp maybe_hide_comment(comment, %{assigns: %{current_user: user}} = conn, show_hidden) do + case show_hidden or can?(user, :show, comment) do + true -> assign(conn, :comment, comment) + false -> PhilomenaWeb.NotAuthorizedPlug.call(conn) + end + end +end diff --git a/lib/philomena_web/plugs/load_post_plug.ex b/lib/philomena_web/plugs/load_post_plug.ex new file mode 100644 index 00000000..60dec97a --- /dev/null +++ b/lib/philomena_web/plugs/load_post_plug.ex @@ -0,0 +1,35 @@ +defmodule PhilomenaWeb.LoadPostPlug do + alias Philomena.Posts.Post + alias Philomena.Repo + + import Plug.Conn, only: [assign: 3] + import Canada.Can, only: [can?: 3] + import Ecto.Query + + def init(opts), + do: opts + + def call(%{assigns: %{topic: topic}} = conn, opts) do + param = Keyword.get(opts, :param, "post_id") + show_hidden = Keyword.get(opts, :show_hidden, false) + + Post + |> where(topic_id: ^topic.id, id: ^to_string(conn.params[param])) + |> preload([topic: :forum, user: [awards: :badge]]) + |> Repo.one() + |> maybe_hide_post(conn, show_hidden) + end + + defp maybe_hide_post(nil, conn, _show_hidden), + do: PhilomenaWeb.NotFoundPlug.call(conn) + + defp maybe_hide_post(%{hidden_from_users: false} = post, conn, _show_hidden), + do: assign(conn, :post, post) + + defp maybe_hide_post(post, %{assigns: %{current_user: user}} = conn, show_hidden) do + case show_hidden or can?(user, :show, post) do + true -> assign(conn, :post, post) + false -> PhilomenaWeb.NotAuthorizedPlug.call(conn) + end + end +end diff --git a/lib/philomena_web/plugs/load_topic_plug.ex b/lib/philomena_web/plugs/load_topic_plug.ex new file mode 100644 index 00000000..06c5dc7c --- /dev/null +++ b/lib/philomena_web/plugs/load_topic_plug.ex @@ -0,0 +1,35 @@ +defmodule PhilomenaWeb.LoadTopicPlug do + alias Philomena.Topics.Topic + alias Philomena.Repo + + import Plug.Conn, only: [assign: 3] + import Canada.Can, only: [can?: 3] + import Ecto.Query + + def init(opts), + do: opts + + def call(%{assigns: %{forum: forum}} = conn, opts) do + param = Keyword.get(opts, :param, "topic_id") + show_hidden = Keyword.get(opts, :show_hidden, false) + + Topic + |> where(forum_id: ^forum.id, slug: ^to_string(conn.params[param])) + |> preload([:user, :poll, :forum]) + |> Repo.one() + |> maybe_hide_topic(conn, show_hidden) + end + + defp maybe_hide_topic(nil, conn, _show_hidden), + do: PhilomenaWeb.NotFoundPlug.call(conn) + + defp maybe_hide_topic(%{hidden_from_users: false} = topic, conn, _show_hidden), + do: assign(conn, :topic, topic) + + defp maybe_hide_topic(topic, %{assigns: %{current_user: user}} = conn, show_hidden) do + case show_hidden or can?(user, :show, topic) do + true -> assign(conn, :topic, topic) + false -> PhilomenaWeb.NotAuthorizedPlug.call(conn) + end + end +end diff --git a/lib/philomena_web/templates/forum/index.html.slime b/lib/philomena_web/templates/forum/index.html.slime index 10315e49..a82ed50e 100644 --- a/lib/philomena_web/templates/forum/index.html.slime +++ b/lib/philomena_web/templates/forum/index.html.slime @@ -24,9 +24,9 @@ h1 Discussion Forums td.table--communication-list__last-post = if forum.last_post do strong - => link(forum.last_post.topic.title, to: Routes.forum_topic_path(@conn, :show, forum, forum.last_post.topic)) + => link(forum.last_post.topic.title, to: Routes.forum_topic_path(@conn, :show, forum.last_post.topic.forum, forum.last_post.topic)) br - => link("Go to post", to: Routes.forum_topic_path(@conn, :show, forum, forum.last_post.topic, post_id: forum.last_post.id) <> "#post_#{forum.last_post.id}") + => link("Go to post", to: Routes.forum_topic_path(@conn, :show, forum.last_post.topic.forum, forum.last_post.topic, post_id: forum.last_post.id) <> "#post_#{forum.last_post.id}") ' by => render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: forum.last_post, conn: @conn br diff --git a/lib/philomena_web/templates/forum/show.html.slime b/lib/philomena_web/templates/forum/show.html.slime index d84d7bfa..a045daf6 100644 --- a/lib/philomena_web/templates/forum/show.html.slime +++ b/lib/philomena_web/templates/forum/show.html.slime @@ -46,7 +46,7 @@ h1 = @forum.name td.table--communication-list__stats.hide-mobile = topic.post_count td.table--communication-list__last-post = if topic.last_post do - => link("Go to post", to: Routes.forum_topic_path(@conn, :show, @forum, topic, post_id: topic.last_post) <> "#post_#{topic.last_post.id}") + => link("Go to post", to: Routes.forum_topic_path(@conn, :show, topic.forum, topic, post_id: topic.last_post) <> "#post_#{topic.last_post.id}") ' by = render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: topic.last_post, conn: @conn br diff --git a/lib/philomena_web/templates/topic/show.html.slime b/lib/philomena_web/templates/topic/show.html.slime index b5de8509..fe1ab5b0 100644 --- a/lib/philomena_web/templates/topic/show.html.slime +++ b/lib/philomena_web/templates/topic/show.html.slime @@ -1,8 +1,8 @@ -elixir: - route = fn p -> Routes.forum_topic_path(@conn, :show, @forum, @topic, p) end - pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @posts, route: route, last: true +- route = fn p -> Routes.forum_topic_path(@conn, :show, @forum, @topic, p) end +- pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @posts, route: route, last: true h1 = @topic.title + = if @topic.hidden_from_users do .block.block--fixed.block--danger h4 This topic has been deleted by a moderator @@ -10,16 +10,19 @@ h1 = @topic.title strong> Reason: em = @topic.deletion_reason - = if can?(@conn, :unhide, @topic) do + + = if can?(@conn, :hide, @topic) do p strong> Deleted by: em strong = link(@topic.deleted_by.name, to: Routes.profile_path(@conn, :show, @topic.deleted_by)) + p - = link(to: Routes.forum_topic_hide_path(@conn, :delete, @forum.id, @topic), method: :delete, class: "button") do + = link(to: Routes.forum_topic_hide_path(@conn, :delete, @forum, @topic), method: :delete, class: "button") do i.fas.fa-check> ' Restore + / Header section .block .block__header @@ -28,6 +31,7 @@ h1 = @topic.title => link(@forum.name, to: Routes.forum_path(@conn, :show, @forum)) ' » => link(@topic.title, to: Routes.forum_topic_path(@conn, :show, @forum, @topic)) + = if not @topic.hidden_from_users or can?(@conn, :hide, @topic) do a href=Routes.post_path(@conn, :index, pq: "topic_id:#{@topic.id}") i.fa.fa-fw.fa-search> @@ -61,9 +65,6 @@ h1 = @topic.title = if @conn.assigns.advert do = render PhilomenaWeb.AdvertView, "_box.html", advert: @conn.assigns.advert, conn: @conn - / Post editability data for JS - /.js-editable-posts data-editable=editable_communications(@posts).to_json - / Footer section .block .block__header.block__header--light @@ -79,6 +80,7 @@ h1 = @topic.title p ' Lock reason: em = @topic.lock_reason + / Post form = cond do - @conn.assigns.current_ban -> @@ -97,7 +99,8 @@ h1 = @topic.title p For various reasons, we'd like to ask you to start a new topic. - true -> - = if can?(@conn, :assist, Topic) do + + = if can?(@conn, :hide, @topic) do .block__content input.toggle-box id="administrator_tools" type="checkbox" checked=false label for="administrator_tools" Manage Topic @@ -105,41 +108,41 @@ h1 = @topic.title .toggle-box-container__content p = if not @topic.hidden_from_users do - = cond do - - can?(@conn, :lock, @topic) and is_nil(@topic.locked_at) -> - = form_for :topic, Routes.forum_topic_lock_path(@conn, :create, @forum.id, @topic), [method: :post, class: "hform"], fn f -> - = text_input f, :lock_reason, class: "input hform__text", placeholder: "Lock reason", required: true - = submit class: "hform__button button" do - i.fas.fa-lock> - ' Lock - - can?(@conn, :unlock, @topic) and not is_nil(@topic.locked_at) -> - = link(to: Routes.forum_topic_lock_path(@conn, :delete, @forum.id, @topic), method: :delete, class: "button") do - i.fas.fa-unlock> - ' Unlock - - true -> - = cond do - - can?(@conn, :stick, @topic) and @topic.sticky -> - = link(to: Routes.forum_topic_stick_path(@conn, :delete, @forum.id, @topic), method: :delete, class: "button") do - i.fas.fa-thumbtack> - ' Unstick - - can?(@conn, :stick, @topic) and not @topic.sticky -> - = link(to: Routes.forum_topic_stick_path(@conn, :create, @forum.id, @topic), method: :post, class: "button") do - i.fas.fa-thumbtack> - ' Stick - - true -> - = if can?(@conn, :move, @topic) do - = form_for :topic, Routes.forum_topic_move_path(@conn, :create, @forum.id, @topic), [method: :post, class: "hform"], fn f -> - .field - = select f, :target_forum_id, @conn.assigns.forums |> Enum.map(fn forum -> {forum.name, forum.id} end), class: "input hform__text" - = submit class: "hform__button button" do - i.fas.fa-truck> - ' Move - = if can?(@conn, :hide, @topic) do - = form_for :topic, Routes.forum_topic_hide_path(@conn, :create, @forum.id, @topic), [method: :post, class: "hform"], fn f -> - .field - = text_input f, :deletion_reason, class: "input hform__text", placeholder: "Deletion reason", required: true - = submit class: "hform__button button" do - i.fas.fa-trash> - ' Delete + = if @topic.locked_at do + = link(to: Routes.forum_topic_lock_path(@conn, :delete, @forum, @topic), method: :delete, class: "button") do + i.fas.fa-unlock> + ' Unlock + + - else + = form_for :topic, Routes.forum_topic_lock_path(@conn, :create, @forum, @topic), [method: :post, class: "hform"], fn f -> + = text_input f, :lock_reason, class: "input hform__text", placeholder: "Lock reason", required: true + = submit class: "hform__button button" do + i.fas.fa-lock> + ' Lock + + = if @topic.sticky do + = link(to: Routes.forum_topic_stick_path(@conn, :delete, @forum, @topic), method: :delete, class: "button") do + i.fas.fa-thumbtack> + ' Unstick + + - else + = link(to: Routes.forum_topic_stick_path(@conn, :create, @forum, @topic), method: :post, class: "button") do + i.fas.fa-thumbtack> + ' Stick + + = form_for :topic, Routes.forum_topic_move_path(@conn, :create, @forum, @topic), [method: :post, class: "hform"], fn f -> + .field + = select f, :target_forum_id, Enum.map(@conn.assigns.forums, &{&1.name, &1.id}), class: "input hform__text" + = submit class: "hform__button button" do + i.fas.fa-truck> + ' Move + + = form_for :topic, Routes.forum_topic_hide_path(@conn, :create, @forum, @topic), [method: :post, class: "hform"], fn f -> + .field + = text_input f, :deletion_reason, class: "input hform__text", placeholder: "Deletion reason", required: true + = submit class: "hform__button button" do + i.fas.fa-trash> + ' Delete + - else | Moderation tools unavailable for deleted topics.