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.
This commit is contained in:
SomewhatDamaged 2020-01-03 09:47:12 +11:00 committed by liamwhite
parent ab94b2f547
commit ae5bfe14e4
7 changed files with 203 additions and 3 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -1,13 +1,28 @@
defmodule PhilomenaWeb.PostJson do defmodule PhilomenaWeb.PostJson do
alias PhilomenaWeb.UserAttributionView 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 def as_json(post) do
%{ %{
id: post.id, id: post.id,
topic_id: post.topic_id,
user_id: if(not post.anonymous, do: post.user_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), 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
end end

View file

@ -112,6 +112,12 @@ defmodule PhilomenaWeb.Router do
resources "/oembed", OembedController, only: [:index] resources "/oembed", OembedController, only: [:index]
resources "/tags", TagController, only: [:show] resources "/tags", TagController, only: [:show]
resources "/comments", CommentController, 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 end
scope "/", PhilomenaWeb do scope "/", PhilomenaWeb do

View file

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