add loader plugs

This commit is contained in:
byte[] 2019-12-14 14:46:50 -05:00
parent ff854fce73
commit e5266db21e
23 changed files with 247 additions and 284 deletions

View file

@ -245,7 +245,6 @@ defmodule Philomena.Topics do
|> Repo.update() |> Repo.update()
end end
def clear_notification(nil, _user), do: nil
def clear_notification(_topic, nil), do: nil def clear_notification(_topic, nil), do: nil
def clear_notification(topic, user) do def clear_notification(topic, user) do
Notifications.delete_unread_notification("Topic", topic.id, user) Notifications.delete_unread_notification("Topic", topic.id, user)

View file

@ -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, SubnetBan), do: true
def can?(%User{role: "moderator"}, _action, FingerprintBan), do: true def can?(%User{role: "moderator"}, _action, FingerprintBan), do: true
# Hide topics
def can?(%User{role: "moderator"}, :hide, %Topic{}), do: true
# #
# Assistants can... # Assistants can...
# #
@ -102,6 +105,7 @@ defimpl Canada.Can, for: [Atom, Philomena.Users.User] do
# Topic assistant actions # 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"}}, :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"}}, :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"}}, :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"}}, :edit, %Post{}), do: true
def can?(%User{role: "assistant", role_map: %{"Topic" => "moderator"}}, :hide, %Post{}), do: true def can?(%User{role: "assistant", role_map: %{"Topic" => "moderator"}}, :hide, %Post{}), do: true

View file

@ -12,7 +12,7 @@ defmodule PhilomenaWeb.ForumController do
forums = forums =
Forum Forum
|> order_by(asc: :name) |> order_by(asc: :name)
|> preload([last_post: [:topic, :user]]) |> preload([last_post: [:user, topic: :forum]])
|> Repo.all() |> Repo.all()
|> Enum.filter(&Canada.Can.can?(user, :show, &1)) |> Enum.filter(&Canada.Can.can?(user, :show, &1))

View file

@ -3,14 +3,14 @@ defmodule PhilomenaWeb.Image.Comment.HistoryController do
alias Philomena.Versions.Version alias Philomena.Versions.Version
alias Philomena.Versions alias Philomena.Versions
alias Philomena.Comments.Comment
alias Philomena.Images.Image alias Philomena.Images.Image
alias Philomena.Repo alias Philomena.Repo
import Ecto.Query import Ecto.Query
plug PhilomenaWeb.CanaryMapPlug, index: :show plug PhilomenaWeb.CanaryMapPlug, index: :show
plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true 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 def index(conn, _params) do
comment = conn.assigns.comment comment = conn.assigns.comment

View file

@ -3,7 +3,6 @@ defmodule PhilomenaWeb.Image.Comment.ReportController do
alias PhilomenaWeb.ReportController alias PhilomenaWeb.ReportController
alias PhilomenaWeb.ReportView alias PhilomenaWeb.ReportView
alias Philomena.Comments.Comment
alias Philomena.Images.Image alias Philomena.Images.Image
alias Philomena.Reports.Report alias Philomena.Reports.Report
alias Philomena.Reports alias Philomena.Reports
@ -11,9 +10,11 @@ defmodule PhilomenaWeb.Image.Comment.ReportController do
plug PhilomenaWeb.FilterBannedUsersPlug plug PhilomenaWeb.FilterBannedUsersPlug
plug PhilomenaWeb.UserAttributionPlug plug PhilomenaWeb.UserAttributionPlug
plug PhilomenaWeb.CaptchaPlug when action in [:create] plug PhilomenaWeb.CaptchaPlug when action in [:create]
plug PhilomenaWeb.CanaryMapPlug, new: :show, create: :show 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: 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 def new(conn, _params) do
comment = conn.assigns.comment comment = conn.assigns.comment

View file

@ -8,15 +8,16 @@ defmodule PhilomenaWeb.Image.CommentController do
alias Philomena.Repo alias Philomena.Repo
import Ecto.Query 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 PhilomenaWeb.CanaryMapPlug, create: :create_comment, edit: :create_comment, update: :create_comment
plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true plug :load_and_authorize_resource, model: Image, id_name: "image_id", persisted: true
# Undo the previous private parameter screwery # 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 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 :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]
def index(conn, %{"comment_id" => comment_id}) do def index(conn, %{"comment_id" => comment_id}) do
comment = comment =

View file

@ -2,14 +2,16 @@ defmodule PhilomenaWeb.Topic.HideController do
import Plug.Conn import Plug.Conn
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.Forums.Forum
alias Philomena.Topics.Topic alias Philomena.Topics.Topic
alias Philomena.Topics 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 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 def create(conn, %{"topic" => topic_params}) do
topic = conn.assigns.topic topic = conn.assigns.topic
@ -21,6 +23,7 @@ defmodule PhilomenaWeb.Topic.HideController do
conn conn
|> put_flash(:info, "Topic successfully hidden!") |> put_flash(:info, "Topic successfully hidden!")
|> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic))
{:error, _changeset} -> {:error, _changeset} ->
conn conn
|> put_flash(:error, "Unable to hide the topic!") |> put_flash(:error, "Unable to hide the topic!")
@ -36,19 +39,11 @@ defmodule PhilomenaWeb.Topic.HideController do
conn conn
|> put_flash(:info, "Topic successfully restored!") |> put_flash(:info, "Topic successfully restored!")
|> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic))
{:error, _changeset} -> {:error, _changeset} ->
conn conn
|> put_flash(:error, "Unable to restore the topic!") |> put_flash(:error, "Unable to restore the topic!")
|> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic))
end end
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 end

View file

@ -2,14 +2,16 @@ defmodule PhilomenaWeb.Topic.LockController do
import Plug.Conn import Plug.Conn
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.Forums.Forum
alias Philomena.Topics.Topic alias Philomena.Topics.Topic
alias Philomena.Topics alias Philomena.Topics
alias Philomena.Repo
import Ecto.Query
plug :load_topic plug PhilomenaWeb.CanaryMapPlug, create: :show, delete: :show
plug PhilomenaWeb.CanaryMapPlug, create: :lock, delete: :unlock plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true
plug :authorize_resource, model: Topic, id_name: "topic_id", 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 def create(conn, %{"topic" => topic_params}) do
topic = conn.assigns.topic topic = conn.assigns.topic
@ -20,6 +22,7 @@ defmodule PhilomenaWeb.Topic.LockController do
conn conn
|> put_flash(:info, "Topic successfully locked!") |> put_flash(:info, "Topic successfully locked!")
|> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic))
{:error, _changeset} -> {:error, _changeset} ->
conn conn
|> put_flash(:error, "Unable to lock the topic!") |> put_flash(:error, "Unable to lock the topic!")
@ -35,19 +38,11 @@ defmodule PhilomenaWeb.Topic.LockController do
conn conn
|> put_flash(:info, "Topic successfully unlocked!") |> put_flash(:info, "Topic successfully unlocked!")
|> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic))
{:error, _changeset} -> {:error, _changeset} ->
conn conn
|> put_flash(:error, "Unable to unlock the topic!") |> put_flash(:error, "Unable to unlock the topic!")
|> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic))
end end
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 end

View file

@ -2,42 +2,34 @@ defmodule PhilomenaWeb.Topic.MoveController do
import Plug.Conn import Plug.Conn
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.Forums.Forum
alias Philomena.Topics.Topic alias Philomena.Topics.Topic
alias Philomena.Topics alias Philomena.Topics
alias Philomena.Repo alias Philomena.Repo
import Ecto.Query
plug :load_topic plug PhilomenaWeb.CanaryMapPlug, create: :show, delete: :show
plug PhilomenaWeb.CanaryMapPlug, create: :move plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true
plug :authorize_resource, model: Topic, id_name: "topic_id", persisted: true
# intentionally blank plug PhilomenaWeb.LoadTopicPlug
# todo: moving plug PhilomenaWeb.CanaryMapPlug, create: :hide, delete: :hide
def create(conn, %{"topic" => topic_params}) do plug :authorize_resource, model: Topic, persisted: true
def create(conn, %{"topic" => %{"target_forum_id" => target_id}}) do
topic = conn.assigns.topic 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 case Topics.move_topic(topic, target_forum_id) do
{:ok, %{topic: topic}} -> {:ok, %{topic: topic}} ->
topic = Repo.preload(topic, :forum) topic = Repo.preload(topic, :forum, force: true)
conn conn
|> put_flash(:info, "Topic successfully moved!") |> put_flash(:info, "Topic successfully moved!")
|> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic))
{:error, _changeset} ->
topic = Repo.preload(topic, :forum)
{:error, _changeset} ->
conn conn
|> put_flash(:error, "Unable to move the topic!") |> 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
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 end

View file

@ -18,6 +18,7 @@ defmodule PhilomenaWeb.Topic.Post.HideController do
conn conn
|> put_flash(:info, "Post successfully hidden!") |> put_flash(:info, "Post successfully hidden!")
|> redirect(to: Routes.forum_topic_path(conn, :show, post.topic.forum, post.topic) <> "#post_#{post.id}") |> redirect(to: Routes.forum_topic_path(conn, :show, post.topic.forum, post.topic) <> "#post_#{post.id}")
{:error, _changeset} -> {:error, _changeset} ->
conn conn
|> put_flash(:error, "Unable to hide post!") |> put_flash(:error, "Unable to hide post!")
@ -35,6 +36,7 @@ defmodule PhilomenaWeb.Topic.Post.HideController do
conn conn
|> put_flash(:info, "Post successfully unhidden!") |> put_flash(:info, "Post successfully unhidden!")
|> redirect(to: Routes.forum_topic_path(conn, :show, post.topic.forum, post.topic) <> "#post_#{post.id}") |> redirect(to: Routes.forum_topic_path(conn, :show, post.topic.forum, post.topic) <> "#post_#{post.id}")
{:error, _changeset} -> {:error, _changeset} ->
conn conn
|> put_flash(:error, "Unable to unhide post!") |> put_flash(:error, "Unable to unhide post!")

View file

@ -4,15 +4,14 @@ defmodule PhilomenaWeb.Topic.Post.HistoryController do
alias Philomena.Versions.Version alias Philomena.Versions.Version
alias Philomena.Versions alias Philomena.Versions
alias Philomena.Forums.Forum alias Philomena.Forums.Forum
alias Philomena.Topics.Topic
alias Philomena.Posts.Post
alias Philomena.Repo alias Philomena.Repo
import Ecto.Query import Ecto.Query
plug PhilomenaWeb.CanaryMapPlug, index: :show plug PhilomenaWeb.CanaryMapPlug, index: :show
plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true 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 def index(conn, _params) do
post = conn.assigns.post post = conn.assigns.post
@ -27,47 +26,4 @@ defmodule PhilomenaWeb.Topic.Post.HistoryController do
render(conn, "index.html", versions: versions) render(conn, "index.html", versions: versions)
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
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 end

View file

@ -4,20 +4,18 @@ defmodule PhilomenaWeb.Topic.Post.ReportController do
alias PhilomenaWeb.ReportController alias PhilomenaWeb.ReportController
alias PhilomenaWeb.ReportView alias PhilomenaWeb.ReportView
alias Philomena.Forums.Forum alias Philomena.Forums.Forum
alias Philomena.Topics.Topic
alias Philomena.Posts.Post
alias Philomena.Reports.Report alias Philomena.Reports.Report
alias Philomena.Reports alias Philomena.Reports
alias Philomena.Repo
import Ecto.Query
plug PhilomenaWeb.FilterBannedUsersPlug plug PhilomenaWeb.FilterBannedUsersPlug
plug PhilomenaWeb.UserAttributionPlug plug PhilomenaWeb.UserAttributionPlug
plug PhilomenaWeb.CaptchaPlug when action in [:create] plug PhilomenaWeb.CaptchaPlug when action in [:create]
plug PhilomenaWeb.CanaryMapPlug, new: :show, create: :show 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_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 def new(conn, _params) do
topic = conn.assigns.topic topic = conn.assigns.topic
@ -39,47 +37,4 @@ defmodule PhilomenaWeb.Topic.Post.ReportController do
ReportController.create(conn, action, post, "Post", params) ReportController.create(conn, action, post, "Post", params)
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
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 end

View file

@ -4,20 +4,20 @@ defmodule PhilomenaWeb.Topic.PostController do
alias Philomena.{Forums.Forum, Topics.Topic, Posts.Post} alias Philomena.{Forums.Forum, Topics.Topic, Posts.Post}
alias Philomena.Posts alias Philomena.Posts
alias Philomena.UserStatistics alias Philomena.UserStatistics
alias Philomena.Repo
import Ecto.Query
plug PhilomenaWeb.FilterBannedUsersPlug plug PhilomenaWeb.FilterBannedUsersPlug
plug PhilomenaWeb.UserAttributionPlug plug PhilomenaWeb.UserAttributionPlug
plug PhilomenaWeb.CanaryMapPlug, create: :show, edit: :show, update: :show 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_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 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 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 def create(conn, %{"post" => post_params}) do
attributes = conn.assigns.attributes attributes = conn.assigns.attributes
@ -62,25 +62,4 @@ defmodule PhilomenaWeb.Topic.PostController do
render(conn, "edit.html", post: conn.assigns.post, changeset: changeset) render(conn, "edit.html", post: conn.assigns.post, changeset: changeset)
end end
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 end

View file

@ -3,28 +3,18 @@ defmodule PhilomenaWeb.Topic.ReadController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.Forums.Forum alias Philomena.Forums.Forum
alias Philomena.Topics.Topic
alias Philomena.Topics 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 plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true
def create(conn, %{"topic_id" => slug}) do plug PhilomenaWeb.LoadTopicPlug, show_hidden: true
topic = load_topic(conn, slug)
def create(conn, _params) do
user = conn.assigns.current_user user = conn.assigns.current_user
Topics.clear_notification(topic, user) Topics.clear_notification(conn.assigns.topic, user)
send_resp(conn, :ok, "") send_resp(conn, :ok, "")
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 end

View file

@ -2,14 +2,16 @@ defmodule PhilomenaWeb.Topic.StickController do
import Plug.Conn import Plug.Conn
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.Forums.Forum
alias Philomena.Topics.Topic alias Philomena.Topics.Topic
alias Philomena.Topics alias Philomena.Topics
alias Philomena.Repo
import Ecto.Query
plug :load_topic plug PhilomenaWeb.CanaryMapPlug, create: :show
plug PhilomenaWeb.CanaryMapPlug, create: :stick, delete: :stick plug :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true
plug :authorize_resource, model: Topic, id_name: "topic_id", persisted: true
plug PhilomenaWeb.LoadTopicPlug
plug PhilomenaWeb.CanaryMapPlug, create: :hide, delete: :hide
plug :authorize_resource, model: Topic, persisted: true
def create(conn, _opts) do def create(conn, _opts) do
topic = conn.assigns.topic topic = conn.assigns.topic
@ -19,6 +21,7 @@ defmodule PhilomenaWeb.Topic.StickController do
conn conn
|> put_flash(:info, "Topic successfully stickied!") |> put_flash(:info, "Topic successfully stickied!")
|> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic))
{:error, _changeset} -> {:error, _changeset} ->
conn conn
|> put_flash(:error, "Unable to stick the topic!") |> put_flash(:error, "Unable to stick the topic!")
@ -34,19 +37,11 @@ defmodule PhilomenaWeb.Topic.StickController do
conn conn
|> put_flash(:info, "Topic successfully unstickied!") |> put_flash(:info, "Topic successfully unstickied!")
|> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic))
{:error, _changeset} -> {:error, _changeset} ->
conn conn
|> put_flash(:error, "Unable to unstick the topic!") |> put_flash(:error, "Unable to unstick the topic!")
|> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic)) |> redirect(to: Routes.forum_topic_path(conn, :show, topic.forum, topic))
end end
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 end

View file

@ -1,15 +1,17 @@
defmodule PhilomenaWeb.Topic.SubscriptionController do defmodule PhilomenaWeb.Topic.SubscriptionController do
use PhilomenaWeb, :controller use PhilomenaWeb, :controller
alias Philomena.{Topics, Topics.Topic, Forums.Forum} alias Philomena.Forums.Forum
alias Philomena.Repo alias Philomena.Topics
import Ecto.Query
plug PhilomenaWeb.CanaryMapPlug, create: :show, delete: :show 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 :load_and_authorize_resource, model: Forum, id_name: "forum_id", id_field: "short_name", persisted: true
def create(conn, %{"topic_id" => slug}) do plug PhilomenaWeb.LoadTopicPlug, [show_hidden: true] when action in [:delete]
topic = load_topic(conn, slug) plug PhilomenaWeb.LoadTopicPlug when action in [:create]
def create(conn, _params) do
topic = conn.assigns.topic
user = conn.assigns.current_user user = conn.assigns.current_user
case Topics.create_subscription(topic, user) do case Topics.create_subscription(topic, user) do
@ -21,8 +23,8 @@ defmodule PhilomenaWeb.Topic.SubscriptionController do
end end
end end
def delete(conn, %{"topic_id" => slug}) do def delete(conn, _params) do
topic = load_topic(conn, slug) topic = conn.assigns.topic
user = conn.assigns.current_user user = conn.assigns.current_user
case Topics.delete_subscription(topic, user) do case Topics.delete_subscription(topic, user) do
@ -33,13 +35,4 @@ defmodule PhilomenaWeb.Topic.SubscriptionController do
render(conn, "_error.html", layout: false) render(conn, "_error.html", layout: false)
end end
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 end

View file

@ -15,13 +15,11 @@ defmodule PhilomenaWeb.TopicController do
plug PhilomenaWeb.CanaryMapPlug, new: :show, create: :show 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_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 forum = conn.assigns.forum
topic = topic = conn.assigns.topic
Topic
|> where(forum_id: ^forum.id, slug: ^slug)
|> preload([:deleted_by, :user, poll: :options])
|> Repo.one()
user = conn.assigns.current_user user = conn.assigns.current_user

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -24,9 +24,9 @@ h1 Discussion Forums
td.table--communication-list__last-post td.table--communication-list__last-post
= if forum.last_post do = if forum.last_post do
strong 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 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 ' by
=> render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: forum.last_post, conn: @conn => render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: forum.last_post, conn: @conn
br br

View file

@ -46,7 +46,7 @@ h1 = @forum.name
td.table--communication-list__stats.hide-mobile = topic.post_count td.table--communication-list__stats.hide-mobile = topic.post_count
td.table--communication-list__last-post td.table--communication-list__last-post
= if topic.last_post do = 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 ' by
= render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: topic.last_post, conn: @conn = render PhilomenaWeb.UserAttributionView, "_anon_user.html", object: topic.last_post, conn: @conn
br br

View file

@ -1,8 +1,8 @@
elixir: - route = fn p -> Routes.forum_topic_path(@conn, :show, @forum, @topic, p) end
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
pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @posts, route: route, last: true
h1 = @topic.title h1 = @topic.title
= if @topic.hidden_from_users do = if @topic.hidden_from_users do
.block.block--fixed.block--danger .block.block--fixed.block--danger
h4 This topic has been deleted by a moderator h4 This topic has been deleted by a moderator
@ -10,16 +10,19 @@ h1 = @topic.title
strong> Reason: strong> Reason:
em em
= @topic.deletion_reason = @topic.deletion_reason
= if can?(@conn, :unhide, @topic) do
= if can?(@conn, :hide, @topic) do
p p
strong> Deleted by: strong> Deleted by:
em em
strong strong
= link(@topic.deleted_by.name, to: Routes.profile_path(@conn, :show, @topic.deleted_by)) = link(@topic.deleted_by.name, to: Routes.profile_path(@conn, :show, @topic.deleted_by))
p 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> i.fas.fa-check>
' Restore ' Restore
/ Header section / Header section
.block .block
.block__header .block__header
@ -28,6 +31,7 @@ h1 = @topic.title
=> link(@forum.name, to: Routes.forum_path(@conn, :show, @forum)) => link(@forum.name, to: Routes.forum_path(@conn, :show, @forum))
' &raquo; ' &raquo;
=> link(@topic.title, to: Routes.forum_topic_path(@conn, :show, @forum, @topic)) => link(@topic.title, to: Routes.forum_topic_path(@conn, :show, @forum, @topic))
= if not @topic.hidden_from_users or can?(@conn, :hide, @topic) do = if not @topic.hidden_from_users or can?(@conn, :hide, @topic) do
a href=Routes.post_path(@conn, :index, pq: "topic_id:#{@topic.id}") a href=Routes.post_path(@conn, :index, pq: "topic_id:#{@topic.id}")
i.fa.fa-fw.fa-search> i.fa.fa-fw.fa-search>
@ -61,9 +65,6 @@ h1 = @topic.title
= if @conn.assigns.advert do = if @conn.assigns.advert do
= render PhilomenaWeb.AdvertView, "_box.html", advert: @conn.assigns.advert, conn: @conn = 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 / Footer section
.block .block
.block__header.block__header--light .block__header.block__header--light
@ -79,6 +80,7 @@ h1 = @topic.title
p p
' Lock reason: ' Lock reason:
em = @topic.lock_reason em = @topic.lock_reason
/ Post form / Post form
= cond do = cond do
- @conn.assigns.current_ban -> - @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. p For various reasons, we'd like to ask you to start a new topic.
- true -> - true ->
= if can?(@conn, :assist, Topic) do
= if can?(@conn, :hide, @topic) do
.block__content .block__content
input.toggle-box id="administrator_tools" type="checkbox" checked=false input.toggle-box id="administrator_tools" type="checkbox" checked=false
label for="administrator_tools" Manage Topic label for="administrator_tools" Manage Topic
@ -105,41 +108,41 @@ h1 = @topic.title
.toggle-box-container__content .toggle-box-container__content
p p
= if not @topic.hidden_from_users do = if not @topic.hidden_from_users do
= cond do = if @topic.locked_at do
- can?(@conn, :lock, @topic) and is_nil(@topic.locked_at) -> = link(to: Routes.forum_topic_lock_path(@conn, :delete, @forum, @topic), method: :delete, class: "button") do
= form_for :topic, Routes.forum_topic_lock_path(@conn, :create, @forum.id, @topic), [method: :post, class: "hform"], fn f -> i.fas.fa-unlock>
= text_input f, :lock_reason, class: "input hform__text", placeholder: "Lock reason", required: true ' Unlock
= submit class: "hform__button button" do
i.fas.fa-lock> - else
' Lock = form_for :topic, Routes.forum_topic_lock_path(@conn, :create, @forum, @topic), [method: :post, class: "hform"], fn f ->
- can?(@conn, :unlock, @topic) and not is_nil(@topic.locked_at) -> = text_input f, :lock_reason, class: "input hform__text", placeholder: "Lock reason", required: true
= link(to: Routes.forum_topic_lock_path(@conn, :delete, @forum.id, @topic), method: :delete, class: "button") do = submit class: "hform__button button" do
i.fas.fa-unlock> i.fas.fa-lock>
' Unlock ' Lock
- true ->
= cond do = if @topic.sticky do
- can?(@conn, :stick, @topic) and @topic.sticky -> = link(to: Routes.forum_topic_stick_path(@conn, :delete, @forum, @topic), method: :delete, class: "button") do
= link(to: Routes.forum_topic_stick_path(@conn, :delete, @forum.id, @topic), method: :delete, class: "button") do i.fas.fa-thumbtack>
i.fas.fa-thumbtack> ' Unstick
' Unstick
- can?(@conn, :stick, @topic) and not @topic.sticky -> - else
= link(to: Routes.forum_topic_stick_path(@conn, :create, @forum.id, @topic), method: :post, class: "button") do = link(to: Routes.forum_topic_stick_path(@conn, :create, @forum, @topic), method: :post, class: "button") do
i.fas.fa-thumbtack> i.fas.fa-thumbtack>
' Stick ' Stick
- true ->
= if can?(@conn, :move, @topic) do = form_for :topic, Routes.forum_topic_move_path(@conn, :create, @forum, @topic), [method: :post, class: "hform"], fn f ->
= form_for :topic, Routes.forum_topic_move_path(@conn, :create, @forum.id, @topic), [method: :post, class: "hform"], fn f -> .field
.field = select f, :target_forum_id, Enum.map(@conn.assigns.forums, &{&1.name, &1.id}), class: "input hform__text"
= 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
= submit class: "hform__button button" do i.fas.fa-truck>
i.fas.fa-truck> ' Move
' Move
= if can?(@conn, :hide, @topic) do = form_for :topic, Routes.forum_topic_hide_path(@conn, :create, @forum, @topic), [method: :post, class: "hform"], fn f ->
= form_for :topic, Routes.forum_topic_hide_path(@conn, :create, @forum.id, @topic), [method: :post, class: "hform"], fn f -> .field
.field = text_input f, :deletion_reason, class: "input hform__text", placeholder: "Deletion reason", required: true
= text_input f, :deletion_reason, class: "input hform__text", placeholder: "Deletion reason", required: true = submit class: "hform__button button" do
= submit class: "hform__button button" do i.fas.fa-trash>
i.fas.fa-trash> ' Delete
' Delete
- else - else
| Moderation tools unavailable for deleted topics. | Moderation tools unavailable for deleted topics.