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()
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)

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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!")

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

@ -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))
' &raquo;
=> 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.