From ae5bfe14e4cd6877725324d6982f4d6371bdd957 Mon Sep 17 00:00:00 2001 From: SomewhatDamaged Date: Fri, 3 Jan 2020 09:47:12 +1100 Subject: [PATCH] Add /forums API Endpoints (#14) * Adding routes for /forums Adding routes for new /forums endpoints * New API Routes `/forum` `/forum/:forum_id` * Add New API Routes `/forums/:forum_id/topics/:topic_id/` `/forums/:forum_id/topics/:topic_id/:post_id` * Adds New API Routes `/forums/:forum_id/topics` `/forums/:forum_id/topics/:topic_id` * Forum JSON formatter * Updated Correctly filters out things that should not be shown. * Added topic JSON filter * Added correct pagination * Spacing and neatened * Cleaned up Consolidated queries and neatened up spacing. Fixed name * Removed unneeded aliases * Cleaned up Consolidated queries Fixed spacing Removed unneeded aliases * Cleaned up Spacing * Cleaned up spacing * Depluralized * Cleaned up Removed space * Removed extra spaces * Removed extra spaces * Removed extra spaces * Removed preloads * Cleaned up Grouped clauses * Consolodated further * Cleaned up preloads * Cleaned up Preloads consolidated clauses grouped clauses * Cleaned up removed `id` `locked` * Removed topic_id Not useful since the API client should already know it. * More consolodation of terms * Add total post count * Removed unneeded variable * Last cleanup, I swear. --- .../controllers/api/json/forums_controller.ex | 36 ++++++++++++++ .../controllers/api/json/posts_controller.ex | 49 +++++++++++++++++++ .../controllers/api/json/topics_controller.ex | 43 ++++++++++++++++ lib/philomena_web/forum_json.ex | 21 ++++++++ lib/philomena_web/post_json.ex | 21 ++++++-- lib/philomena_web/router.ex | 6 +++ lib/philomena_web/topic_json.ex | 30 ++++++++++++ 7 files changed, 203 insertions(+), 3 deletions(-) create mode 100644 lib/philomena_web/controllers/api/json/forums_controller.ex create mode 100644 lib/philomena_web/controllers/api/json/posts_controller.ex create mode 100644 lib/philomena_web/controllers/api/json/topics_controller.ex create mode 100644 lib/philomena_web/forum_json.ex create mode 100644 lib/philomena_web/topic_json.ex diff --git a/lib/philomena_web/controllers/api/json/forums_controller.ex b/lib/philomena_web/controllers/api/json/forums_controller.ex new file mode 100644 index 00000000..d3a4e9b3 --- /dev/null +++ b/lib/philomena_web/controllers/api/json/forums_controller.ex @@ -0,0 +1,36 @@ +defmodule PhilomenaWeb.Api.Json.ForumController do + use PhilomenaWeb, :controller + + alias PhilomenaWeb.ForumJson + alias Philomena.Forums.Forum + alias Philomena.Repo + import Ecto.Query + + def show(conn, %{"id" => id}) do + forum = + Forum + |> where(short_name: ^id) + |> where(access_level: "normal") + |> Repo.one() + + cond do + is_nil(forum) -> + conn + |> put_status(:not_found) + |> text("") + + true -> + json(conn, %{forum: ForumJson.as_json(forum)}) + end + end + + def index(conn, _params) do + forums = + Forum + |> where(access_level: "normal") + |> order_by(asc: :name) + |> Repo.all() + + json(conn, %{forums: Enum.map(forums, &ForumJson.as_json/1)}) + end +end diff --git a/lib/philomena_web/controllers/api/json/posts_controller.ex b/lib/philomena_web/controllers/api/json/posts_controller.ex new file mode 100644 index 00000000..aa63e641 --- /dev/null +++ b/lib/philomena_web/controllers/api/json/posts_controller.ex @@ -0,0 +1,49 @@ +defmodule PhilomenaWeb.Api.Json.PostController do + use PhilomenaWeb, :controller + + alias PhilomenaWeb.PostJson + alias Philomena.Posts.Post + alias Philomena.Repo + import Ecto.Query + + def show(conn, %{"forum_id" => forum_id, "topic_id" => topic_id, "id" => post_id}) do + post = + Post + |> join(:inner, [p], _ in assoc(p, :topic)) + |> join(:inner, [_p, t], _ in assoc(t, :forum)) + |> where(id: ^post_id) + |> where(destroyed_content: false) + |> where([_p, t], t.hidden_from_users == false and t.slug == ^topic_id) + |> where([_p, _t, f], f.access_level == "normal" and f.short_name == ^forum_id) + |> preload([:user]) + |> Repo.one() + + cond do + is_nil(post) -> + conn + |> put_status(:not_found) + |> text("") + + true -> + json(conn, %{post: PostJson.as_json(post)}) + end + end + + def index(conn, %{"forum_id" => forum_id, "topic_id" => topic_id}) do + page = conn.assigns.pagination.page_number + posts = + Post + |> join(:inner, [p], _ in assoc(p, :topic)) + |> join(:inner, [_p, t], _ in assoc(t, :forum)) + |> where(destroyed_content: false) + |> where([_p, t], t.hidden_from_users == false and t.slug == ^topic_id) + |> where([_p, _t, f], f.access_level == "normal" and f.short_name == ^forum_id) + |> where([p], p.topic_position >= ^(25 * (page - 1)) and p.topic_position < ^(25 * page)) + |> order_by(asc: :topic_position) + |> preload([:user]) + |> preload([_p, t, _f], topic: t) + |> Repo.all() + + json(conn, %{posts: Enum.map(posts, &PostJson.as_json/1), page: page, total: hd(posts).topic.post_count}) + end +end diff --git a/lib/philomena_web/controllers/api/json/topics_controller.ex b/lib/philomena_web/controllers/api/json/topics_controller.ex new file mode 100644 index 00000000..5b182ec6 --- /dev/null +++ b/lib/philomena_web/controllers/api/json/topics_controller.ex @@ -0,0 +1,43 @@ +defmodule PhilomenaWeb.Api.Json.TopicController do + use PhilomenaWeb, :controller + + alias PhilomenaWeb.TopicJson + alias Philomena.Topics.Topic + alias Philomena.Repo + import Ecto.Query + + def show(conn, %{"forum_id" => forum_id, "id" => id}) do + topic = + Topic + |> join(:inner, [t], _ in assoc(t, :forum)) + |> where(slug: ^id) + |> where(hidden_from_users: false) + |> where([_t, f], f.access_level == "normal" and f.short_name == ^forum_id) + |> order_by(desc: :sticky, desc: :last_replied_to_at) + |> preload([:user]) + |> Repo.one() + + cond do + is_nil(topic) -> + conn + |> put_status(:not_found) + |> text("") + + true -> + json(conn, %{topic: TopicJson.as_json(topic)}) + end + end + + def index(conn, %{"forum_id" => id}) do + topics = + Topic + |> join(:inner, [t], _ in assoc(t, :forum)) + |> where(hidden_from_users: false) + |> where([_t, f], f.access_level == "normal" and f.short_name == ^id) + |> order_by(desc: :sticky, desc: :last_replied_to_at) + |> preload([:user]) + |> Repo.paginate(conn.assigns.scrivener) + + json(conn, %{topic: Enum.map(topics, &TopicJson.as_json/1)}) + end +end diff --git a/lib/philomena_web/forum_json.ex b/lib/philomena_web/forum_json.ex new file mode 100644 index 00000000..c21236bb --- /dev/null +++ b/lib/philomena_web/forum_json.ex @@ -0,0 +1,21 @@ +defmodule PhilomenaWeb.ForumJson do + + def as_json(%{access_level: "normal"} = forum) do + %{ + name: forum.name, + short_name: forum.short_name, + description: forum.description, + topic_count: forum.topic_count, + post_count: forum.post_count + } + end + def as_json(_forum) do + %{ + name: nil, + short_name: nil, + description: nil, + topic_count: nil, + post_count: nil + } + end +end diff --git a/lib/philomena_web/post_json.ex b/lib/philomena_web/post_json.ex index fa2ba82a..92f8ac83 100644 --- a/lib/philomena_web/post_json.ex +++ b/lib/philomena_web/post_json.ex @@ -1,13 +1,28 @@ defmodule PhilomenaWeb.PostJson do alias PhilomenaWeb.UserAttributionView + def as_json(%{topic: %{hidden_from_users: true}} = post) do + %{ + id: post.id, + user_id: nil, + author: nil, + body: nil + } + end + def as_json(%{hidden_from_users: true} = post) do + %{ + id: post.id, + user_id: if(not post.anonymous, do: post.user_id), + author: if(post.anonymous or is_nil(post.user), do: UserAttributionView.anonymous_name(post), else: post.user.name), + body: nil + } + end def as_json(post) do %{ id: post.id, - topic_id: post.topic_id, user_id: if(not post.anonymous, do: post.user_id), author: if(post.anonymous or is_nil(post.user), do: UserAttributionView.anonymous_name(post), else: post.user.name), - body: if(not post.topic.hidden_from_users and not post.hidden_from_users, do: post.body) + body: post.body } end -end \ No newline at end of file +end diff --git a/lib/philomena_web/router.ex b/lib/philomena_web/router.ex index b7766fda..dbc8414a 100644 --- a/lib/philomena_web/router.ex +++ b/lib/philomena_web/router.ex @@ -112,6 +112,12 @@ defmodule PhilomenaWeb.Router do resources "/oembed", OembedController, only: [:index] resources "/tags", TagController, only: [:show] resources "/comments", CommentController, only: [:show] + resources "/forums", ForumController, only: [:show, :index] do + resources "/topics", TopicController, only: [:show, :index] do + resources "/posts", PostController, only: [:show, :index] + end + end + end scope "/", PhilomenaWeb do diff --git a/lib/philomena_web/topic_json.ex b/lib/philomena_web/topic_json.ex new file mode 100644 index 00000000..e1113122 --- /dev/null +++ b/lib/philomena_web/topic_json.ex @@ -0,0 +1,30 @@ +defmodule PhilomenaWeb.TopicJson do + alias PhilomenaWeb.UserAttributionView + + def as_json(%{hidden_from_users: true}) do + %{ + slug: nil, + title: nil, + post_count: nil, + view_count: nil, + sticky: nil, + last_replied_to_at: nil, + locked: nil, + user_id: nil, + author: nil + } + end + def as_json(topic) do + %{ + slug: topic.slug, + title: topic.title, + post_count: topic.post_count, + view_count: topic.view_count, + sticky: topic.sticky, + last_replied_to_at: topic.last_replied_to_at, + locked: not is_nil(topic.locked_at), + user_id: if(not topic.anonymous, do: topic.user.id), + author: if(topic.anonymous or is_nil(topic.user), do: UserAttributionView.anonymous_name(topic), else: topic.user.name) + } + end +end