Skip to content

Commit

Permalink
Merge pull request #16 from groupher/batch-delete-article
Browse files Browse the repository at this point in the history
feat(article): batch delete by id list
  • Loading branch information
mydearxym authored Jul 1, 2023
2 parents 91d135d + fbed45c commit 00ccaef
Show file tree
Hide file tree
Showing 14 changed files with 558 additions and 28 deletions.
2 changes: 2 additions & 0 deletions lib/groupher_server/cms/cms.ex
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ defmodule GroupherServer.CMS do
defdelegate undo_sink_article(thread, id), to: ArticleCURD

defdelegate archive_articles(thread), to: ArticleCURD
defdelegate batch_mark_delete_articles(community, thread, id_list), to: ArticleCURD
defdelegate batch_undo_mark_delete_articles(community, thread, id_list), to: ArticleCURD

defdelegate paged_citing_contents(type, id, filter), to: CitedArtiment

Expand Down
80 changes: 61 additions & 19 deletions lib/groupher_server/cms/delegates/article_curd.ex
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
@doc """
read articles for un-logined user
"""
def read_article(community_slug, thread, id) when thread in @article_threads do
with {:ok, article} <- check_article_pending(community_slug, thread, id) do
def read_article(community_slug, thread, inner_id) when thread in @article_threads do
with {:ok, article} <- if_article_legal(community_slug, thread, inner_id) do
do_read_article(article, thread)
end
end

def read_article(community_slug, thread, id, %User{id: user_id} = user)
def read_article(community_slug, thread, inner_id, %User{id: user_id} = user)
when thread in @article_threads do
with {:ok, article} <- check_article_pending(community_slug, thread, id, user) do
with {:ok, article} <- if_article_legal(community_slug, thread, inner_id, user) do
Multi.new()
|> Multi.run(:normal_read, fn _, _ -> do_read_article(article, thread) end)
|> Multi.run(:add_viewed_user, fn _, %{normal_read: article} ->
Expand Down Expand Up @@ -591,6 +591,47 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
end
end

@doc """
make sure the given ids are deleted
"""
def batch_mark_delete_articles(community, thread, inner_id_list) do
do_batch_mark_delete_articles(community, thread, inner_id_list, true)
end

@doc """
make sure the given ids are deleted
"""
def batch_undo_mark_delete_articles(community, thread, inner_id_list) do
do_batch_mark_delete_articles(community, thread, inner_id_list, false)
end

defp do_batch_mark_delete_articles(community, thread, inner_id_list, delete_flag) do
with {:ok, info} <- match(thread) do
batch_query =
info.model
|> where([article], article.original_community_slug == ^community)
|> where([article], article.inner_id in ^inner_id_list)

Multi.new()
|> Multi.run(:update_articles, fn _, _ ->
batch_query
|> Repo.update_all(set: [mark_delete: delete_flag])
|> done
end)
|> Multi.run(:update_community_article_count, fn _, _ ->
communities =
from(a in batch_query, preload: :communities)
|> Repo.all()
|> Enum.map(& &1.communities)
|> Enum.at(0)

CommunityCURD.update_community_count_field(communities, thread)
end)
|> Repo.transaction()
|> result()
end
end

@doc """
remove article forever
"""
Expand Down Expand Up @@ -669,62 +710,62 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do
|> result()
end

defp check_article_pending(community_slug, thread, id, user)
defp if_article_legal(community_slug, thread, inner_id, user)
when thread in @article_threads do
clauses = %{original_community_slug: community_slug, inner_id: id}
clauses = %{original_community_slug: community_slug, inner_id: inner_id}

with {:ok, info} <- match(thread),
{:ok, article} <- ORM.find_by(info.model, clauses, preload: :author) do
check_article_pending(article, user)
if_article_legal(article, user)
end
end

defp check_article_pending(community_slug, thread, id)
defp if_article_legal(community_slug, thread, inner_id)
when thread in @article_threads do
clauses = %{original_community_slug: community_slug, inner_id: id}
clauses = %{original_community_slug: community_slug, inner_id: inner_id}

with {:ok, info} <- match(thread),
{:ok, article} <- ORM.find_by(info.model, clauses) do
check_article_pending(article)
if_article_legal(article)
end
end

# pending article can be seen is viewer is author
defp check_article_pending(thread, id, %User{} = user) when thread in @article_threads do
defp if_article_legal(thread, id, %User{} = user) when thread in @article_threads do
with {:ok, info} <- match(thread),
{:ok, article} <- ORM.find(info.model, id, preload: :author) do
check_article_pending(article, user)
if_article_legal(article, user)
end
end

defp check_article_pending(%{pending: @audit_legal} = article, _) do
defp if_article_legal(%{pending: @audit_legal} = article, _) do
{:ok, article}
end

defp check_article_pending(%{pending: @audit_failed} = article, _) do
defp if_article_legal(%{pending: @audit_failed} = article, _) do
{:ok, article}
end

defp check_article_pending(%{pending: @audit_illegal} = article, %User{id: user_id}) do
defp if_article_legal(%{pending: @audit_illegal} = article, %User{id: user_id}) do
case article.author.user_id == user_id do
true -> {:ok, article}
false -> raise_error(:pending, "this article is under audition")
end
end

# pending article should not be seen
defp check_article_pending(thread, id) when thread in @article_threads do
defp if_article_legal(thread, id) when thread in @article_threads do
with {:ok, info} <- match(thread),
{:ok, article} <- ORM.find(info.model, id) do
check_article_pending(article)
if_article_legal(article)
end
end

defp check_article_pending(%{pending: @audit_illegal}) do
defp if_article_legal(%{pending: @audit_illegal}) do
raise_error(:pending, "this article is under audition")
end

defp check_article_pending(article), do: {:ok, article}
defp if_article_legal(article), do: {:ok, article}

defp add_pin_articles_ifneed(articles, querable, %{community: community} = filter) do
thread = module_to_atom(querable)
Expand Down Expand Up @@ -853,6 +894,7 @@ defmodule GroupherServer.CMS.Delegate.ArticleCURD do

defp result({:ok, %{update_edit_status: result}}), do: {:ok, result}
defp result({:ok, %{update_article: result}}), do: {:ok, result}
defp result({:ok, %{update_articles: result}}), do: {:ok, %{done: true}}
defp result({:ok, %{delete_article: result}}), do: {:ok, result}
# NOTE: for read article, order is import
defp result({:ok, %{set_viewer_has_states: result}}), do: result |> done()
Expand Down
2 changes: 1 addition & 1 deletion lib/groupher_server/cms/delegates/community_curd.ex
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ defmodule GroupherServer.CMS.Delegate.CommunityCURD do
end

def update_community_count_field(communities, thread) when is_list(communities) do
case Enum.all?(communities, &({:ok, _} = update_community_count_field(&1, thread))) do
case Enum.all?(Enum.uniq(communities), &({:ok, _} = update_community_count_field(&1, thread))) do
true -> {:ok, :pass}
false -> {:error, "update_community_count_field"}
end
Expand Down
8 changes: 8 additions & 0 deletions lib/groupher_server_web/resolvers/cms_resolver.ex
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,14 @@ defmodule GroupherServerWeb.Resolvers.CMS do
CMS.mark_delete_article(thread, id)
end

def batch_mark_delete_articles(_root, ~m(community thread ids)a, _info) do
CMS.batch_mark_delete_articles(community, thread, ids)
end

def batch_undo_mark_delete_articles(_root, ~m(community thread ids)a, _info) do
CMS.batch_undo_mark_delete_articles(community, thread, ids)
end

def undo_mark_delete_article(_root, ~m(id thread)a, _info) do
CMS.undo_mark_delete_article(thread, id)
end
Expand Down
26 changes: 26 additions & 0 deletions lib/groupher_server_web/schema/Helper/mutations.ex
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ defmodule GroupherServerWeb.Schema.Helper.Mutations do
alias GroupherServerWeb.Middleware, as: M
alias GroupherServerWeb.Resolvers, as: R

import Helper.Utils, only: [plural: 1]

@doc """
add basic mutation reactions to article
"""
Expand Down Expand Up @@ -135,6 +137,30 @@ defmodule GroupherServerWeb.Schema.Helper.Mutations do

resolve(&R.CMS.undo_mark_delete_article/3)
end

@desc unquote("batch mark delete #{plural(thread)} type article, aka soft-delete")
field unquote(:"batch_mark_delete_#{plural(thread)}"), :done_state do
arg(:community, non_null(:string))
arg(:ids, list_of(:id))
arg(:thread, unquote(:"#{thread}_thread"), default_value: unquote(thread))

middleware(M.Authorize, :login)
middleware(M.Passport, claim: unquote("cms->#{to_string(thread)}.mark_delete"))

resolve(&R.CMS.batch_mark_delete_articles/3)
end

@desc unquote("batch undo mark delete #{plural(thread)} type article, aka soft-delete")
field unquote(:"batch_undo_mark_delete_#{plural(thread)}"), :done_state do
arg(:community, non_null(:string))
arg(:ids, list_of(:id))
arg(:thread, unquote(:"#{thread}_thread"), default_value: unquote(thread))

middleware(M.Authorize, :login)
middleware(M.Passport, claim: unquote("cms->#{to_string(thread)}.mark_delete"))

resolve(&R.CMS.batch_undo_mark_delete_articles/3)
end
end
end

Expand Down
4 changes: 4 additions & 0 deletions lib/groupher_server_web/schema/cms/cms_types.ex
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ defmodule GroupherServerWeb.Schema.CMS.Types do
field(:exist, :boolean)
end

object :done_state do
field(:done, :boolean)
end

######
# common stands for minimal info of the type
# usually used in abuse_report, feeds, etc ..
Expand Down
44 changes: 44 additions & 0 deletions test/groupher_server/cms/articles/blog_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,50 @@ defmodule GroupherServer.Test.CMS.Articles.Blog do
end
end

describe "[cms blog batch delete]" do
test "can batch delete blogs with inner_ids", ~m(user community blog_attrs)a do
{:ok, blog1} = CMS.create_article(community, :blog, blog_attrs, user)
{:ok, blog2} = CMS.create_article(community, :blog, blog_attrs, user)
{:ok, blog3} = CMS.create_article(community, :blog, blog_attrs, user)

CMS.batch_mark_delete_articles(community.slug, :blog, [
blog1.inner_id,
blog2.inner_id
])

{:ok, blog1} = ORM.find(Blog, blog1.id)
{:ok, blog2} = ORM.find(Blog, blog2.id)
{:ok, blog3} = ORM.find(Blog, blog3.id)

assert blog1.mark_delete == true
assert blog2.mark_delete == true
assert blog3.mark_delete == false
end

test "can undo batch delete blogs with inner_ids", ~m(user community blog_attrs)a do
{:ok, blog1} = CMS.create_article(community, :blog, blog_attrs, user)
{:ok, blog2} = CMS.create_article(community, :blog, blog_attrs, user)
{:ok, blog3} = CMS.create_article(community, :blog, blog_attrs, user)

CMS.batch_mark_delete_articles(community.slug, :blog, [
blog1.inner_id,
blog2.inner_id
])

CMS.batch_undo_mark_delete_articles(community.slug, :blog, [
blog1.inner_id,
blog2.inner_id
])

{:ok, blog1} = ORM.find(Blog, blog1.id)
{:ok, blog2} = ORM.find(Blog, blog2.id)
{:ok, blog3} = ORM.find(Blog, blog3.id)

assert blog1.mark_delete == false
assert blog2.mark_delete == false
end
end

describe "[cms blog document]" do
test "will create related document after create", ~m(user community blog_attrs)a do
{:ok, blog} = CMS.create_article(community, :blog, blog_attrs, user)
Expand Down
44 changes: 44 additions & 0 deletions test/groupher_server/cms/articles/changelog_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,50 @@ defmodule GroupherServer.Test.CMS.Articles.Changelog do
end
end

describe "[cms changelog batch delete]" do
test "can batch delete changelogs with inner_ids", ~m(user community changelog_attrs)a do
{:ok, changelog1} = CMS.create_article(community, :changelog, changelog_attrs, user)
{:ok, changelog2} = CMS.create_article(community, :changelog, changelog_attrs, user)
{:ok, changelog3} = CMS.create_article(community, :changelog, changelog_attrs, user)

CMS.batch_mark_delete_articles(community.slug, :changelog, [
changelog1.inner_id,
changelog2.inner_id
])

{:ok, changelog1} = ORM.find(Changelog, changelog1.id)
{:ok, changelog2} = ORM.find(Changelog, changelog2.id)
{:ok, changelog3} = ORM.find(Changelog, changelog3.id)

assert changelog1.mark_delete == true
assert changelog2.mark_delete == true
assert changelog3.mark_delete == false
end

test "can undo batch delete changelogs with inner_ids", ~m(user community changelog_attrs)a do
{:ok, changelog1} = CMS.create_article(community, :changelog, changelog_attrs, user)
{:ok, changelog2} = CMS.create_article(community, :changelog, changelog_attrs, user)
{:ok, changelog3} = CMS.create_article(community, :changelog, changelog_attrs, user)

CMS.batch_mark_delete_articles(community.slug, :changelog, [
changelog1.inner_id,
changelog2.inner_id
])

CMS.batch_undo_mark_delete_articles(community.slug, :changelog, [
changelog1.inner_id,
changelog2.inner_id
])

{:ok, changelog1} = ORM.find(Changelog, changelog1.id)
{:ok, changelog2} = ORM.find(Changelog, changelog2.id)
{:ok, changelog3} = ORM.find(Changelog, changelog3.id)

assert changelog1.mark_delete == false
assert changelog2.mark_delete == false
end
end

describe "[cms changelog document]" do
test "will create related document after create", ~m(user community changelog_attrs)a do
{:ok, changelog} = CMS.create_article(community, :changelog, changelog_attrs, user)
Expand Down
44 changes: 44 additions & 0 deletions test/groupher_server/cms/articles/doc_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,50 @@ defmodule GroupherServer.Test.CMS.Articles.Doc do
end
end

describe "[cms doc batch delete]" do
test "can batch delete docs with inner_ids", ~m(user community doc_attrs)a do
{:ok, doc1} = CMS.create_article(community, :doc, doc_attrs, user)
{:ok, doc2} = CMS.create_article(community, :doc, doc_attrs, user)
{:ok, doc3} = CMS.create_article(community, :doc, doc_attrs, user)

CMS.batch_mark_delete_articles(community.slug, :doc, [
doc1.inner_id,
doc2.inner_id
])

{:ok, doc1} = ORM.find(Doc, doc1.id)
{:ok, doc2} = ORM.find(Doc, doc2.id)
{:ok, doc3} = ORM.find(Doc, doc3.id)

assert doc1.mark_delete == true
assert doc2.mark_delete == true
assert doc3.mark_delete == false
end

test "can undo batch delete docs with inner_ids", ~m(user community doc_attrs)a do
{:ok, doc1} = CMS.create_article(community, :doc, doc_attrs, user)
{:ok, doc2} = CMS.create_article(community, :doc, doc_attrs, user)
{:ok, doc3} = CMS.create_article(community, :doc, doc_attrs, user)

CMS.batch_mark_delete_articles(community.slug, :doc, [
doc1.inner_id,
doc2.inner_id
])

CMS.batch_undo_mark_delete_articles(community.slug, :doc, [
doc1.inner_id,
doc2.inner_id
])

{:ok, doc1} = ORM.find(Doc, doc1.id)
{:ok, doc2} = ORM.find(Doc, doc2.id)
{:ok, doc3} = ORM.find(Doc, doc3.id)

assert doc1.mark_delete == false
assert doc2.mark_delete == false
end
end

describe "[cms doc document]" do
test "will create related document after create", ~m(user community doc_attrs)a do
{:ok, doc} = CMS.create_article(community, :doc, doc_attrs, user)
Expand Down
Loading

0 comments on commit 00ccaef

Please sign in to comment.