Skip to content

Commit

Permalink
Merge pull request #44 from epochtalk/moderation-log
Browse files Browse the repository at this point in the history
Moderation Log
  • Loading branch information
akinsey authored May 12, 2023
2 parents a9cb354 + 7aee216 commit 37169eb
Show file tree
Hide file tree
Showing 11 changed files with 3,601 additions and 23 deletions.
175 changes: 175 additions & 0 deletions lib/epochtalk_server/models/moderation_log.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
defmodule EpochtalkServer.Models.ModerationLog do
use Ecto.Schema
import Ecto.Changeset
import Ecto.Query
alias EpochtalkServer.Models.ModerationLog
alias EpochtalkServerWeb.Helpers.ModerationLogHelper
alias EpochtalkServerWeb.Helpers.Pagination
alias EpochtalkServerWeb.Helpers.QueryHelper
alias EpochtalkServer.Repo

@moduledoc """
`ModerationLog` model, for performing actions relating to the moderation log
"""
@type t :: %__MODULE__{
mod_username: String.t() | nil,
mod_id: non_neg_integer | nil,
mod_ip: String.t() | nil,
action_api_url: String.t() | nil,
action_api_method: String.t() | nil,
action_obj: map() | nil,
action_taken_at: NaiveDateTime.t() | nil,
action_type: String.t() | nil,
action_display_text: String.t() | nil,
action_display_url: String.t() | nil
}
@primary_key false
@derive {Jason.Encoder,
only: [
:mod_username,
:mod_id,
:mod_ip,
:action_api_url,
:action_api_method,
:action_obj,
:action_taken_at,
:action_type,
:action_display_text,
:action_display_url
]}
schema "moderation_log" do
field :mod_username, :string
field :mod_id, :integer
field :mod_ip, :string
field :action_api_url, :string
field :action_api_method, :string
field :action_obj, :map
field :action_taken_at, :naive_datetime
field :action_type, :string
field :action_display_text, :string
field :action_display_url, :string
end

## === Changesets Functions ===

@doc """
Create generic changeset for `ModerationLog` model
"""
@spec create_changeset(moderation_log :: t(), attrs :: map() | nil) :: Ecto.Changeset.t()
def create_changeset(moderation_log, attrs) do
now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second)

display_data = ModerationLogHelper.get_display_data(get_in(attrs, [:action, :type]))

action_obj =
if Map.has_key?(display_data, :data_query) do
display_data.data_query.(get_in(attrs, [:action, :obj]))
else
get_in(attrs, [:action, :obj])
end

attrs =
attrs
|> Map.put(:action_taken_at, now)
|> Map.put(:mod_username, get_in(attrs, [:mod, :username]))
|> Map.put(:mod_id, get_in(attrs, [:mod, :id]))
|> Map.put(:mod_ip, get_in(attrs, [:mod, :ip]))
|> Map.put(:action_api_url, get_in(attrs, [:action, :api_url]))
|> Map.put(:action_api_method, get_in(attrs, [:action, :api_method]))
|> Map.put(:action_obj, get_in(attrs, [:action, :obj]))
|> Map.put(:action_type, get_in(attrs, [:action, :type]))
|> Map.put(:action_display_text, display_data.get_display_text.(action_obj))
|> Map.put(:action_display_url, display_data.get_display_url.(action_obj))

moderation_log
|> cast(attrs, [
:mod_username,
:mod_id,
:mod_ip,
:action_api_url,
:action_api_method,
:action_obj,
:action_taken_at,
:action_type,
:action_display_text,
:action_display_url
])
end

## === Database Functions ===

@doc """
Creates a new `ModerationLog` in the database
"""
@spec create(attrs :: map()) :: {:ok, moderation_log :: t()} | {:error, Ecto.Changeset.t()}
def create(attrs) do
moderation_log_cs = ModerationLog.create_changeset(%ModerationLog{}, attrs)

case Repo.insert(moderation_log_cs) do
{:ok, moderation_log} ->
{:ok, moderation_log}

# changeset error
{:error, err} ->
{:error, err}
end
end

@doc """
Page `ModerationLog` models
"""
@spec page(attrs :: map(), page :: non_neg_integer, per_page: non_neg_integer) ::
{:ok, moderation_logs :: [t()] | [], pagination_data :: map()}
def page(attrs, page \\ 1, opts \\ []) do
from(ModerationLog)
|> where(^filter_where(attrs))
|> Pagination.page_simple(page, per_page: opts[:per_page])
end

defp filter_where(attrs) do
Enum.reduce(attrs, dynamic(true), fn
{"mod", mod}, dynamic ->
filter_mod(mod, dynamic)

{"action", action}, dynamic ->
QueryHelper.build_and(dynamic, :action_type, action)

{"keyword", keyword}, dynamic ->
like = "%#{keyword}%"
QueryHelper.build_and(dynamic, :action_display_text, %{"like" => like})

{"bdate", bdate}, dynamic ->
{:ok, bdate} = NaiveDateTime.from_iso8601(bdate <> " 00:00:00")
QueryHelper.build_and(dynamic, :action_taken_at, %{"<" => bdate})

{"adate", adate}, dynamic ->
{:ok, adate} = NaiveDateTime.from_iso8601(adate <> " 00:00:00")
QueryHelper.build_and(dynamic, :action_taken_at, %{">" => adate})

{"sdate", sdate}, dynamic ->
{:ok, sdate} = NaiveDateTime.from_iso8601(sdate <> " 00:00:00")
QueryHelper.build_and(dynamic, :action_taken_at, %{">" => sdate})

{"edate", edate}, dynamic ->
{:ok, edate} = NaiveDateTime.from_iso8601(edate <> " 00:00:00")
QueryHelper.build_and(dynamic, :action_taken_at, %{"<" => edate})

{_, _}, dynamic ->
# Not a where parameter
dynamic
end)
end

defp filter_mod(mod, dynamic) do
like = "%#{mod}%"

case Integer.parse(mod) do
{_, ""} ->
QueryHelper.build_and(dynamic, :mod_id, mod)

_ ->
dynamic = QueryHelper.build_and(dynamic, :mod_username, %{"like" => like})
QueryHelper.build_or(dynamic, :mod_ip, %{"like" => like})
end
end
end
32 changes: 32 additions & 0 deletions lib/epochtalk_server_web/controllers/moderation_log_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
defmodule EpochtalkServerWeb.ModerationLogController do
use EpochtalkServerWeb, :controller

@moduledoc """
Controller For `ModerationLog` related API requests
"""
alias EpochtalkServer.Auth.Guardian
alias EpochtalkServer.Models.ModerationLog
alias EpochtalkServerWeb.ErrorHelpers
alias EpochtalkServerWeb.Helpers.Validate

@doc """
Used to page `ModerationLog` models for moderation log view`
"""
def page(conn, attrs) do
with {:auth, true} <- {:auth, Guardian.Plug.authenticated?(conn)},
page <- Validate.cast(attrs, "page", :integer, min: 1),
limit <- Validate.cast(attrs, "limit", :integer, min: 1),
{:ok, moderation_logs, data} <- ModerationLog.page(attrs, page, per_page: limit) do
render(conn, "page.json", moderation_logs: moderation_logs, pagination_data: data)
else
{:auth, false} ->
ErrorHelpers.render_json_error(conn, 400, "Not logged in, cannot page moderation log")

{:error, data} ->
ErrorHelpers.render_json_error(conn, 400, data)

_ ->
ErrorHelpers.render_json_error(conn, 500, "There was an issue getting the moderation log")
end
end
end
Loading

0 comments on commit 37169eb

Please sign in to comment.