From dbd4ed76f30bcc6ab15906091e12294ef63e858f Mon Sep 17 00:00:00 2001 From: Anthony Kinsey Date: Tue, 27 Aug 2024 14:08:25 -1000 Subject: [PATCH 01/17] refactor(thread-move): wip fix thread move queries last post info update --- lib/epochtalk_server/models/metadata_board.ex | 39 ++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/lib/epochtalk_server/models/metadata_board.ex b/lib/epochtalk_server/models/metadata_board.ex index 25334629..bd6b6aed 100644 --- a/lib/epochtalk_server/models/metadata_board.ex +++ b/lib/epochtalk_server/models/metadata_board.ex @@ -104,6 +104,7 @@ defmodule EpochtalkServer.Models.MetadataBoard do on: u.id == p.user_id, where: t.board_id == ^board_id, order_by: [desc: p.created_at], + limit: 1, select: %{ thread_id: p.thread_id, created_at: p.created_at, @@ -111,6 +112,42 @@ defmodule EpochtalkServer.Models.MetadataBoard do position: p.position } + # SELECT + # t.board_id, + # t.id as thread_id, + # (SELECT p.content->>'title' as title FROM posts p WHERE p.thread_id = t.id ORDER BY created_at ASC LIMIT 1), + # (SELECT u.username FROM users u WHERE u.id = lp.user_id), + # lp.created_at, + # lp.position + # FROM threads t + # JOIN + # (SELECT p2.thread_id, p2.created_at, p2.user_id, p2.position + # FROM posts p2 + # WHERE p2.thread_id = (SELECT id from threads WHERE board_id = $1 limit 1) + # ORDER BY p2.created_at DESC LIMIT 1) lp + # ON lp.thread_id = (SELECT id from threads WHERE board_id = $1 limit 1) + # WHERE t.board_id = $1 ORDER BY t.created_at DESC LIMIT 1; + # var q = ` + # SELECT + # t.board_id, + # t.id as thread_id, + # (SELECT p.content->>'title' as title FROM posts p WHERE p.thread_id = t.id ORDER BY created_at ASC LIMIT 1), (SELECT u.username FROM users u WHERE u.id = lp.user_id), + # lp.created_at, + # lp.position + # FROM threads t JOIN + # ( + # SELECT p2.thread_id, p2.created_at, p2.user_id, p2.position + # FROM posts p2 WHERE p2.thread_id = (SELECT id from threads WHERE board_id = $1 limit 1) ORDER BY p2.created_at DESC LIMIT 1) lp ON lp.thread_id = (SELECT id from threads WHERE board_id = $1 limit 1) WHERE t.board_id = $1 ORDER BY t.created_at DESC LIMIT 1;`; + + # last_post_thread_title_subquery = + # from p2 in Post, + # order_by: [asc: p2.created_at], + # limit: 1, + # select: %{ + # title: p2.content["title"], + # thread_id: p2.thread_id + # } + # query most recent thread in board, join last post subquery last_post_query = from t in Thread, @@ -124,7 +161,7 @@ defmodule EpochtalkServer.Models.MetadataBoard do select: %{ board_id: t.board_id, thread_id: t.id, - title: p.content["title"], + title: fragment("SELECT p.content->>'title' as title FROM posts p WHERE p.thread_id = ? ORDER BY created_at ASC LIMIT 1", t.id), username: lp.username, created_at: lp.created_at, position: lp.position From 5b0c2a7bfe2aef4a20e9c059653026e149256fe4 Mon Sep 17 00:00:00 2001 From: Anthony Kinsey Date: Tue, 27 Aug 2024 15:18:28 -1000 Subject: [PATCH 02/17] fix(thread-move): fix issue with thread move updating last post info incorrectly --- lib/epochtalk_server/models/metadata_board.ex | 81 +++++-------------- 1 file changed, 19 insertions(+), 62 deletions(-) diff --git a/lib/epochtalk_server/models/metadata_board.ex b/lib/epochtalk_server/models/metadata_board.ex index bd6b6aed..bdbdcf7a 100644 --- a/lib/epochtalk_server/models/metadata_board.ex +++ b/lib/epochtalk_server/models/metadata_board.ex @@ -96,7 +96,7 @@ defmodule EpochtalkServer.Models.MetadataBoard do @spec update_last_post_info(metadata_board :: t(), board_id :: non_neg_integer) :: t() def update_last_post_info(metadata_board, board_id) do # query most recent post in thread and it's authoring user's data - last_post_subquery = + last_post_query = from t in Thread, left_join: p in Post, on: t.id == p.thread_id, @@ -112,81 +112,38 @@ defmodule EpochtalkServer.Models.MetadataBoard do position: p.position } - # SELECT - # t.board_id, - # t.id as thread_id, - # (SELECT p.content->>'title' as title FROM posts p WHERE p.thread_id = t.id ORDER BY created_at ASC LIMIT 1), - # (SELECT u.username FROM users u WHERE u.id = lp.user_id), - # lp.created_at, - # lp.position - # FROM threads t - # JOIN - # (SELECT p2.thread_id, p2.created_at, p2.user_id, p2.position - # FROM posts p2 - # WHERE p2.thread_id = (SELECT id from threads WHERE board_id = $1 limit 1) - # ORDER BY p2.created_at DESC LIMIT 1) lp - # ON lp.thread_id = (SELECT id from threads WHERE board_id = $1 limit 1) - # WHERE t.board_id = $1 ORDER BY t.created_at DESC LIMIT 1; - # var q = ` - # SELECT - # t.board_id, - # t.id as thread_id, - # (SELECT p.content->>'title' as title FROM posts p WHERE p.thread_id = t.id ORDER BY created_at ASC LIMIT 1), (SELECT u.username FROM users u WHERE u.id = lp.user_id), - # lp.created_at, - # lp.position - # FROM threads t JOIN - # ( - # SELECT p2.thread_id, p2.created_at, p2.user_id, p2.position - # FROM posts p2 WHERE p2.thread_id = (SELECT id from threads WHERE board_id = $1 limit 1) ORDER BY p2.created_at DESC LIMIT 1) lp ON lp.thread_id = (SELECT id from threads WHERE board_id = $1 limit 1) WHERE t.board_id = $1 ORDER BY t.created_at DESC LIMIT 1;`; - - # last_post_thread_title_subquery = - # from p2 in Post, - # order_by: [asc: p2.created_at], - # limit: 1, - # select: %{ - # title: p2.content["title"], - # thread_id: p2.thread_id - # } + # query most recent thread in board title + last_post_info = + if lp = Repo.one(last_post_query) do + last_thread_title_query = + from p in Post, + where: p.thread_id == ^lp.thread_id, + order_by: [asc: p.created_at], + limit: 1, + select: p.content["title"] - # query most recent thread in board, join last post subquery - last_post_query = - from t in Thread, - left_join: p in Post, - on: p.thread_id == t.id, - left_join: lp in subquery(last_post_subquery), - on: p.thread_id == lp.thread_id, - where: t.board_id == ^board_id, - order_by: [desc: t.created_at], - limit: 1, - select: %{ - board_id: t.board_id, - thread_id: t.id, - title: fragment("SELECT p.content->>'title' as title FROM posts p WHERE p.thread_id = ? ORDER BY created_at ASC LIMIT 1", t.id), - username: lp.username, - created_at: lp.created_at, - position: lp.position - } + last_thread_title = Repo.one(last_thread_title_query) - # update board metadata using queried data - updated_metadata_board = - if lp = Repo.one(last_post_query) do - change(metadata_board, + %{ last_post_username: lp.username, last_post_created_at: lp.created_at, last_thread_id: lp.thread_id, - last_thread_title: lp.title, + last_thread_title: last_thread_title, last_post_position: lp.position - ) + } else - change(metadata_board, + %{ last_post_username: nil, last_post_created_at: nil, last_thread_id: nil, last_thread_title: nil, last_post_position: nil - ) + } end + # update board metadata using queried data + updated_metadata_board = change(metadata_board, last_post_info) + Repo.update!(updated_metadata_board) end end From 7a06e404b8fa867f908bb9687104e114f682dd7c Mon Sep 17 00:00:00 2001 From: Anthony Kinsey Date: Thu, 29 Aug 2024 14:57:02 -1000 Subject: [PATCH 03/17] feat(test-post): allow passing in created_at timestamp when creating posts and threads for test purposes --- lib/epochtalk_server/models/post.ex | 44 +++++++++++++++++++++++++-- lib/epochtalk_server/models/thread.ex | 25 ++++++++++----- 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/lib/epochtalk_server/models/post.ex b/lib/epochtalk_server/models/post.ex index bf84d487..98a8535d 100644 --- a/lib/epochtalk_server/models/post.ex +++ b/lib/epochtalk_server/models/post.ex @@ -60,9 +60,13 @@ defmodule EpochtalkServer.Models.Post do @doc """ Create changeset for `Post` model """ - @spec create_changeset(post :: t(), attrs :: map() | nil) :: Ecto.Changeset.t() - def create_changeset(post, attrs) do - now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + @spec create_changeset( + post :: t(), + attrs :: map() | nil, + now_override :: NaiveDateTime.t() | nil + ) :: Ecto.Changeset.t() + def create_changeset(post, attrs, now_override \\ nil) do + now = now_override || NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) # set default values and timestamps post = @@ -190,6 +194,40 @@ defmodule EpochtalkServer.Models.Post do end) end + @doc """ + Creates a new `Post` in the database, used during testing. Allows modification of created_at + """ + @spec create_for_test(post_attrs :: map(), timestamp :: NaiveDateTime.t()) :: + {:ok, post :: t()} | {:error, Ecto.Changeset.t()} + def create_for_test(post_attrs, timestamp) do + Repo.transaction(fn -> + post_cs = create_changeset(%Post{}, post_attrs, timestamp) + + case Repo.insert(post_cs) do + # changeset valid, insert success, update metadata threads and return thread + {:ok, db_post} -> + # Increment user post count + Profile.increment_post_count(db_post.user_id) + + # Set thread created_at and updated_at + Thread.set_timestamps(db_post.thread_id) + + # Set post position + Post.set_position_using_thread(db_post.id, db_post.thread_id) + + # Increment thread post ocunt + Thread.increment_post_count(db_post.thread_id) + + # Requery post with position and thread slug info + Repo.one(from p in Post, where: p.id == ^db_post.id, preload: [:thread]) + + # changeset error + {:error, cs} -> + Repo.rollback(cs) + end + end) + end + @doc """ Creates a new `Post` in the database """ diff --git a/lib/epochtalk_server/models/thread.ex b/lib/epochtalk_server/models/thread.ex index afd4f25a..8bd1fb56 100644 --- a/lib/epochtalk_server/models/thread.ex +++ b/lib/epochtalk_server/models/thread.ex @@ -90,9 +90,13 @@ defmodule EpochtalkServer.Models.Thread do @doc """ Create changeset for creation of `Thread` model """ - @spec create_changeset(thread :: t(), attrs :: map() | nil) :: Ecto.Changeset.t() - def create_changeset(thread, attrs) do - now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + @spec create_changeset( + thread :: t(), + attrs :: map() | nil, + now_override :: NaiveDateTime.t() | nil + ) :: Ecto.Changeset.t() + def create_changeset(thread, attrs, now_override \\ nil) do + now = now_override || NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) # set default values and timestamps thread = @@ -125,9 +129,9 @@ defmodule EpochtalkServer.Models.Thread do @doc """ Creates a new `Thread` in the database """ - @spec create(thread_attrs :: map(), user :: map()) :: + @spec create(thread_attrs :: map(), user :: map(), timestamp :: NaiveDateTime.t() | nil) :: {:ok, thread :: t()} | {:error, Ecto.Changeset.t()} - def create(thread_attrs, user) do + def create(thread_attrs, user, timestamp \\ nil) do thread_cs = create_changeset(%Thread{}, thread_attrs) case Repo.transaction(fn -> @@ -143,7 +147,7 @@ defmodule EpochtalkServer.Models.Thread do # create poll, if necessary db_poll = handle_create_poll(db_thread.id, thread_attrs["poll"], user) # create post - db_post = handle_create_post(db_thread.id, thread_attrs, user) + db_post = handle_create_post(db_thread.id, thread_attrs, user, timestamp) # return post (preloaded thread) and poll data %{post: db_post, poll: db_poll} end) do @@ -890,7 +894,7 @@ defmodule EpochtalkServer.Models.Thread do end end - defp handle_create_post(thread_id, thread_attrs, user) do + defp handle_create_post(thread_id, thread_attrs, user, timestamp) do post_attrs = %{ thread_id: thread_id, user_id: user.id, @@ -901,7 +905,12 @@ defmodule EpochtalkServer.Models.Thread do } } - case Post.create(post_attrs) do + if is_nil(timestamp) do + Post.create(post_attrs) + else + Post.create_for_test(post_attrs, timestamp) + end + |> case do {:ok, post} -> post {:error, cs} -> Repo.rollback(cs) end From 0e15419348b1e08179be2301b435d9e32c72b9b7 Mon Sep 17 00:00:00 2001 From: Anthony Kinsey Date: Fri, 30 Aug 2024 12:08:48 -1000 Subject: [PATCH 04/17] refactor(factories): update post and thread factories to allow sequenced timestamps --- test/support/factories/post.ex | 5 ++++- test/support/factories/thread.ex | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/test/support/factories/post.ex b/test/support/factories/post.ex index c9e78af9..be2e98e0 100644 --- a/test/support/factories/post.ex +++ b/test/support/factories/post.ex @@ -20,7 +20,10 @@ defmodule Test.Support.Factories.Post do def post_factory(%{user: user, thread: thread} = attrs) do attributes = build(:post_attributes, attrs) - Post.create(attributes) + timestamp = + sequence(:post_timestamp, &NaiveDateTime.add(~N[1970-01-01 00:00:00], &1 * 60 * 60)) + + Post.create_for_test(attributes, timestamp) end end end diff --git a/test/support/factories/thread.ex b/test/support/factories/thread.ex index 4c1998e7..fe316491 100644 --- a/test/support/factories/thread.ex +++ b/test/support/factories/thread.ex @@ -23,7 +23,10 @@ defmodule Test.Support.Factories.Thread do def thread_factory(%{board: board, user: user} = attrs) do attributes = build(:thread_attributes, attrs) - Thread.create(attributes, user) + timestamp = + sequence(:post_timestamp, &NaiveDateTime.add(~N[1970-01-01 00:00:00], &1 * 60 * 60)) + + Thread.create(attributes, user, timestamp) |> case do {:ok, thread} -> thread_id = thread.post.thread.id From e59ca8cc1269aa1e3d4b5a85be2205035c336fc6 Mon Sep 17 00:00:00 2001 From: Anthony Kinsey Date: Fri, 30 Aug 2024 17:53:52 -1000 Subject: [PATCH 05/17] test(move-thread): add test that checks last post info after moving thread --- lib/epochtalk_server/models/metadata_board.ex | 2 +- .../controllers/thread_test.exs | 123 +++++++++++++++--- 2 files changed, 105 insertions(+), 20 deletions(-) diff --git a/lib/epochtalk_server/models/metadata_board.ex b/lib/epochtalk_server/models/metadata_board.ex index bdbdcf7a..8a82e959 100644 --- a/lib/epochtalk_server/models/metadata_board.ex +++ b/lib/epochtalk_server/models/metadata_board.ex @@ -112,7 +112,7 @@ defmodule EpochtalkServer.Models.MetadataBoard do position: p.position } - # query most recent thread in board title + # query most recent thread's, in board, title last_post_info = if lp = Repo.one(last_post_query) do last_thread_title_query = diff --git a/test/epochtalk_server_web/controllers/thread_test.exs b/test/epochtalk_server_web/controllers/thread_test.exs index 1686452d..ee1f2a31 100644 --- a/test/epochtalk_server_web/controllers/thread_test.exs +++ b/test/epochtalk_server_web/controllers/thread_test.exs @@ -2,18 +2,22 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do use Test.Support.ConnCase, async: true import Test.Support.Factory alias EpochtalkServerWeb.CustomErrors.InvalidPermission + alias EpochtalkServer.Repo alias EpochtalkServer.Models.User alias EpochtalkServer.Models.Board + alias EpochtalkServer.Models.Thread + alias EpochtalkServer.Models.BoardMapping setup %{ users: %{ user: user, + mod_user: mod_user, admin_user: admin_user, super_admin_user: super_admin_user } } do board = build(:board) - test_move_board = build(:board) + move_board = build(:board) admin_board = build(:board, viewable_by: 1) super_admin_board = build(:board, viewable_by: 1, postable_by: 0) category = build(:category) @@ -24,27 +28,36 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do [board: board, category: category, view_order: 1], [board: admin_board, category: category, view_order: 2], [board: super_admin_board, category: category, view_order: 3], - [board: test_move_board, category: category, view_order: 4] + [board: move_board, category: category, view_order: 4] ] ) factory_threads = build_list(3, :thread, board: board, user: user) + admin_priority_thread = build(:thread, board: board, user: admin_user) + admin_board_thread = build(:thread, board: admin_board, user: admin_user) + super_admin_board_thread = build(:thread, board: super_admin_board, user: super_admin_user) + + # create thread and replies in move_board to compare last post info in tests below + move_board_thread = build(:thread, board: move_board, user: user) + + # create posts in thread created above, this is to get a specific number of thread replies + [_, {:ok, move_board_last_post}] = build_list(2, :post, user: mod_user, thread: move_board_thread.post.thread) num_thread_replies = 3 thread_post_count = num_thread_replies + 1 thread = build(:thread, board: board, user: user) - # create posts in thread created above, this is to get a speciic number of thread replies - build_list(num_thread_replies, :post, user: user, thread: thread.post.thread) - - admin_priority_thread = build(:thread, board: board, user: admin_user) - admin_board_thread = build(:thread, board: admin_board, user: admin_user) - super_admin_board_thread = build(:thread, board: super_admin_board, user: super_admin_user) + # create posts in thread created above, this is to get a specific number of thread replies + [_, _, {:ok, board_last_post}] = build_list(num_thread_replies, :post, user: user, thread: thread.post.thread) + # NOTE: building additional posts or threads within "thread" or "move_board_thread" + # will break move thread tests which tests last post info { :ok, board: board, - test_move_board: test_move_board, + move_board: move_board, + board_last_post: board_last_post, + move_board_last_post: move_board_last_post, admin_board: admin_board, super_admin_board: super_admin_board, factory_threads: factory_threads, @@ -765,7 +778,7 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do test "when unauthenticated, returns Unauthorized error", %{ conn: conn, thread: %{post: %{thread_id: thread_id}}, - test_move_board: %{id: board_id} + move_board: %{id: board_id} } do response = conn @@ -779,7 +792,7 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do @tag authenticated: :admin test "given nonexistant thread, does not move thread", %{ conn: conn, - test_move_board: %{id: board_id} + move_board: %{id: board_id} } do response = conn @@ -795,7 +808,7 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do %{ conn: conn, admin_board_thread: %{post: %{thread_id: thread_id}}, - test_move_board: %{id: board_id} + move_board: %{id: board_id} } do response = conn @@ -811,7 +824,7 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do %{ conn: conn, super_admin_board_thread: %{post: %{thread_id: thread_id}}, - test_move_board: %{id: board_id} + move_board: %{id: board_id} } do response = conn @@ -826,7 +839,7 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do test "when authenticated with banned user, throws InvalidPermission forbidden error", %{ conn: conn, thread: %{post: %{thread_id: thread_id}}, - test_move_board: %{id: board_id} + move_board: %{id: board_id} } do assert_raise InvalidPermission, ~r/^Forbidden, invalid permissions to perform this action/, @@ -842,7 +855,7 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do %{ conn: conn, admin_priority_thread: %{post: %{thread_id: thread_id}}, - test_move_board: %{id: board_id} + move_board: %{id: board_id} } do response = conn @@ -859,7 +872,7 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do test "when authenticated, with insufficient permissions, does not move thread", %{ conn: conn, thread: %{post: %{thread_id: thread_id}}, - test_move_board: %{id: board_id} + move_board: %{id: board_id} } do assert_raise InvalidPermission, ~r/^Forbidden, invalid permissions to perform this action/, @@ -875,7 +888,7 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do conn: conn, thread: %{post: %{thread_id: thread_id}}, board: %{id: old_board_id, name: old_board_name}, - test_move_board: %{id: new_board_id} + move_board: %{id: new_board_id} } do response = conn @@ -891,7 +904,7 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do conn: conn, thread: %{post: %{thread_id: thread_id}}, board: %{id: old_board_id}, - test_move_board: %{id: new_board_id}, + move_board: %{id: new_board_id}, thread_post_count: thread_post_count } do {:ok, old_board} = Board.find_by_id(old_board_id) @@ -915,7 +928,7 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do test "after moving thread, increases new board's post count and thread count", %{ conn: conn, thread: %{post: %{thread_id: thread_id}}, - test_move_board: %{id: new_board_id}, + move_board: %{id: new_board_id}, thread_post_count: thread_post_count } do {:ok, new_board} = Board.find_by_id(new_board_id) @@ -934,5 +947,77 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do assert new_post_count == old_post_count + thread_post_count assert new_thread_count == old_thread_count + 1 end + + @tag authenticated: :global_mod + test "after moving thread, updates last post info of each board", %{ + conn: conn, + board: %{id: old_board_id}, + move_board: %{id: new_board_id}, + board_last_post: old_board_last_post, + admin_priority_thread: old_board_second_to_last_thread, + move_board_last_post: new_board_last_post, + } do + all_boards = BoardMapping.all() + [old_board_before_move] = Enum.filter(all_boards, fn bm -> bm.board_id == old_board_id end) + [new_board_before_move] = Enum.filter(all_boards, fn bm -> bm.board_id == new_board_id end) + + old_board_last_thread = Thread.find(old_board_last_post.thread_id) + new_board_last_thread = Thread.find(new_board_last_post.thread_id) + + old_board_last_post = old_board_last_post |> Repo.preload(:user) + new_board_last_post = new_board_last_post |> Repo.preload(:user) + + # Check each board's last post info before moving + assert old_board_before_move.stats.last_thread_id == old_board_last_post.thread_id + assert old_board_before_move.stats.last_post_created_at == old_board_last_post.created_at + assert old_board_before_move.stats.last_post_position == old_board_last_post.position + assert old_board_before_move.stats.last_post_username == old_board_last_post.user.username + assert old_board_before_move.stats.last_thread_title == old_board_last_thread.title + assert old_board_before_move.stats.last_thread_id == old_board_last_thread.id + + assert new_board_before_move.stats.last_thread_id == new_board_last_post.thread_id + assert new_board_before_move.stats.last_post_created_at == new_board_last_post.created_at + assert new_board_before_move.stats.last_post_position == new_board_last_post.position + assert new_board_before_move.stats.last_post_username == new_board_last_post.user.username + assert new_board_before_move.stats.last_thread_title == new_board_last_thread.title + assert new_board_before_move.stats.last_thread_id == new_board_last_thread.id + + thread_id = old_board_before_move.stats.last_thread_id + conn + |> post(Routes.thread_path(conn, :move, thread_id), %{new_board_id: new_board_id}) + |> json_response(200) + + all_boards = BoardMapping.all() + [old_board_after_move] = Enum.filter(all_boards, fn bm -> bm.board_id == old_board_id end) + [new_board_after_move] = Enum.filter(all_boards, fn bm -> bm.board_id == new_board_id end) + + old_board_last_thread = Thread.find(old_board_last_post.thread_id) + old_board_new_last_thread = Thread.find(old_board_second_to_last_thread.post.thread_id) + old_board_new_last_post = old_board_second_to_last_thread.post |> Repo.preload(:user) + + # Check old board's last post info after moving, should not be the same + assert old_board_after_move.stats.last_thread_id != old_board_last_post.thread_id + assert old_board_after_move.stats.last_post_created_at != old_board_last_post.created_at + assert old_board_after_move.stats.last_post_position != old_board_last_post.position + assert old_board_after_move.stats.last_post_username != old_board_last_post.user.username + assert old_board_after_move.stats.last_thread_title != old_board_last_thread.title + assert old_board_after_move.stats.last_thread_id != old_board_last_thread.id + + # Check old board's last post is now the previous second to last post that was in the board + assert old_board_after_move.stats.last_thread_id == old_board_new_last_post.thread_id + assert old_board_after_move.stats.last_post_created_at == old_board_new_last_post.created_at + assert old_board_after_move.stats.last_post_position == old_board_new_last_post.position + assert old_board_after_move.stats.last_post_username == old_board_new_last_post.user.username + assert old_board_after_move.stats.last_thread_title == old_board_new_last_thread.title + assert old_board_after_move.stats.last_thread_id == old_board_new_last_thread.id + + # Check new board's last post info after moving, should be the old boards last post + assert new_board_after_move.stats.last_thread_id == old_board_last_post.thread_id + assert new_board_after_move.stats.last_post_created_at == old_board_last_post.created_at + assert new_board_after_move.stats.last_post_position == old_board_last_post.position + assert new_board_after_move.stats.last_post_username == old_board_last_post.user.username + assert new_board_after_move.stats.last_thread_title == old_board_last_thread.title + assert new_board_after_move.stats.last_thread_id == old_board_last_thread.id + end end end From 0df86d76454946ca1dc49d67c57f825521db664c Mon Sep 17 00:00:00 2001 From: Anthony Kinsey Date: Fri, 30 Aug 2024 18:51:15 -1000 Subject: [PATCH 06/17] style(format): run mix format --- lib/epochtalk_server/models/post.ex | 71 +++++++------------ .../controllers/thread_test.exs | 14 ++-- 2 files changed, 37 insertions(+), 48 deletions(-) diff --git a/lib/epochtalk_server/models/post.ex b/lib/epochtalk_server/models/post.ex index 98a8535d..abe58c84 100644 --- a/lib/epochtalk_server/models/post.ex +++ b/lib/epochtalk_server/models/post.ex @@ -169,28 +169,7 @@ defmodule EpochtalkServer.Models.Post do Repo.transaction(fn -> post_cs = create_changeset(%Post{}, post_attrs) - case Repo.insert(post_cs) do - # changeset valid, insert success, update metadata threads and return thread - {:ok, db_post} -> - # Increment user post count - Profile.increment_post_count(db_post.user_id) - - # Set thread created_at and updated_at - Thread.set_timestamps(db_post.thread_id) - - # Set post position - Post.set_position_using_thread(db_post.id, db_post.thread_id) - - # Increment thread post ocunt - Thread.increment_post_count(db_post.thread_id) - - # Requery post with position and thread slug info - Repo.one(from p in Post, where: p.id == ^db_post.id, preload: [:thread]) - - # changeset error - {:error, cs} -> - Repo.rollback(cs) - end + create_post_shared(post_cs) end) end @@ -203,28 +182,7 @@ defmodule EpochtalkServer.Models.Post do Repo.transaction(fn -> post_cs = create_changeset(%Post{}, post_attrs, timestamp) - case Repo.insert(post_cs) do - # changeset valid, insert success, update metadata threads and return thread - {:ok, db_post} -> - # Increment user post count - Profile.increment_post_count(db_post.user_id) - - # Set thread created_at and updated_at - Thread.set_timestamps(db_post.thread_id) - - # Set post position - Post.set_position_using_thread(db_post.id, db_post.thread_id) - - # Increment thread post ocunt - Thread.increment_post_count(db_post.thread_id) - - # Requery post with position and thread slug info - Repo.one(from p in Post, where: p.id == ^db_post.id, preload: [:thread]) - - # changeset error - {:error, cs} -> - Repo.rollback(cs) - end + create_post_shared(post_cs) end) end @@ -535,4 +493,29 @@ defmodule EpochtalkServer.Models.Post do |> Map.delete("user_id") |> Map.delete("title") end + + defp create_post_shared(post_cs) do + case Repo.insert(post_cs) do + # changeset valid, insert success, update metadata threads and return thread + {:ok, db_post} -> + # Increment user post count + Profile.increment_post_count(db_post.user_id) + + # Set thread created_at and updated_at + Thread.set_timestamps(db_post.thread_id) + + # Set post position + Post.set_position_using_thread(db_post.id, db_post.thread_id) + + # Increment thread post ocunt + Thread.increment_post_count(db_post.thread_id) + + # Requery post with position and thread slug info + Repo.one(from p in Post, where: p.id == ^db_post.id, preload: [:thread]) + + # changeset error + {:error, cs} -> + Repo.rollback(cs) + end + end end diff --git a/test/epochtalk_server_web/controllers/thread_test.exs b/test/epochtalk_server_web/controllers/thread_test.exs index ee1f2a31..c45c0fd9 100644 --- a/test/epochtalk_server_web/controllers/thread_test.exs +++ b/test/epochtalk_server_web/controllers/thread_test.exs @@ -41,14 +41,16 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do move_board_thread = build(:thread, board: move_board, user: user) # create posts in thread created above, this is to get a specific number of thread replies - [_, {:ok, move_board_last_post}] = build_list(2, :post, user: mod_user, thread: move_board_thread.post.thread) + [_, {:ok, move_board_last_post}] = + build_list(2, :post, user: mod_user, thread: move_board_thread.post.thread) num_thread_replies = 3 thread_post_count = num_thread_replies + 1 thread = build(:thread, board: board, user: user) # create posts in thread created above, this is to get a specific number of thread replies - [_, _, {:ok, board_last_post}] = build_list(num_thread_replies, :post, user: user, thread: thread.post.thread) + [_, _, {:ok, board_last_post}] = + build_list(num_thread_replies, :post, user: user, thread: thread.post.thread) # NOTE: building additional posts or threads within "thread" or "move_board_thread" # will break move thread tests which tests last post info @@ -955,7 +957,7 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do move_board: %{id: new_board_id}, board_last_post: old_board_last_post, admin_priority_thread: old_board_second_to_last_thread, - move_board_last_post: new_board_last_post, + move_board_last_post: new_board_last_post } do all_boards = BoardMapping.all() [old_board_before_move] = Enum.filter(all_boards, fn bm -> bm.board_id == old_board_id end) @@ -983,6 +985,7 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do assert new_board_before_move.stats.last_thread_id == new_board_last_thread.id thread_id = old_board_before_move.stats.last_thread_id + conn |> post(Routes.thread_path(conn, :move, thread_id), %{new_board_id: new_board_id}) |> json_response(200) @@ -1007,7 +1010,10 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do assert old_board_after_move.stats.last_thread_id == old_board_new_last_post.thread_id assert old_board_after_move.stats.last_post_created_at == old_board_new_last_post.created_at assert old_board_after_move.stats.last_post_position == old_board_new_last_post.position - assert old_board_after_move.stats.last_post_username == old_board_new_last_post.user.username + + assert old_board_after_move.stats.last_post_username == + old_board_new_last_post.user.username + assert old_board_after_move.stats.last_thread_title == old_board_new_last_thread.title assert old_board_after_move.stats.last_thread_id == old_board_new_last_thread.id From 2886818fb34b94d2ae597c8b7f4089039fa40392 Mon Sep 17 00:00:00 2001 From: Anthony Kinsey Date: Fri, 30 Aug 2024 21:05:48 -1000 Subject: [PATCH 07/17] test(credo): disable credo error , this same code is in posts create changeset and does not cause an error --- lib/epochtalk_server/models/post.ex | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/epochtalk_server/models/post.ex b/lib/epochtalk_server/models/post.ex index abe58c84..ec6c9ce7 100644 --- a/lib/epochtalk_server/models/post.ex +++ b/lib/epochtalk_server/models/post.ex @@ -65,6 +65,7 @@ defmodule EpochtalkServer.Models.Post do attrs :: map() | nil, now_override :: NaiveDateTime.t() | nil ) :: Ecto.Changeset.t() + # credo:disable-for-next-line def create_changeset(post, attrs, now_override \\ nil) do now = now_override || NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) From 56174d1750feb7890f0229d71488ba56b9a4d976 Mon Sep 17 00:00:00 2001 From: unenglishable Date: Fri, 6 Sep 2024 13:43:34 -0700 Subject: [PATCH 08/17] refactor(): convert :naive_datetime to :naive_datetime_usec storing higher precision date time allows test results to be accurate changes models to use :naive_datetime_usec and changeset functions use NaiveDateTime.utc_now() without truncating subject to change; especially in `lib/epochtalk_server/models/post.ex` where code sets `now = now` --- .../models/auto_moderation.ex | 6 +-- lib/epochtalk_server/models/ban.ex | 10 ++--- lib/epochtalk_server/models/banned_address.ex | 8 ++-- lib/epochtalk_server/models/board.ex | 8 ++-- lib/epochtalk_server/models/category.ex | 2 +- .../models/image_reference.ex | 8 ++-- lib/epochtalk_server/models/invitation.ex | 4 +- lib/epochtalk_server/models/mention.ex | 4 +- lib/epochtalk_server/models/metadata_board.ex | 2 +- lib/epochtalk_server/models/moderation_log.ex | 4 +- lib/epochtalk_server/models/notification.ex | 2 +- lib/epochtalk_server/models/poll.ex | 2 +- lib/epochtalk_server/models/post.ex | 10 ++--- lib/epochtalk_server/models/post_draft.ex | 4 +- lib/epochtalk_server/models/profile.ex | 6 +-- lib/epochtalk_server/models/role.ex | 6 +-- lib/epochtalk_server/models/thread.ex | 8 ++-- lib/epochtalk_server/models/trust_feedback.ex | 2 +- lib/epochtalk_server/models/user.ex | 8 ++-- lib/epochtalk_server/models/user_activity.ex | 6 +-- lib/epochtalk_server/models/user_ignored.ex | 2 +- lib/epochtalk_server/models/user_ip.ex | 4 +- .../models/user_thread_view.ex | 4 +- lib/epochtalk_server_web/json/poll_json.ex | 2 +- priv/repo/seed_roles.exs | 40 +++++++++---------- 25 files changed, 81 insertions(+), 81 deletions(-) diff --git a/lib/epochtalk_server/models/auto_moderation.ex b/lib/epochtalk_server/models/auto_moderation.ex index 1d7d8529..110cf20e 100644 --- a/lib/epochtalk_server/models/auto_moderation.ex +++ b/lib/epochtalk_server/models/auto_moderation.ex @@ -47,8 +47,8 @@ defmodule EpochtalkServer.Models.AutoModeration do field :conditions, {:array, :map} field :actions, {:array, :string} field :options, :map - field :created_at, :naive_datetime - field :updated_at, :naive_datetime + field :created_at, :naive_datetime_usec + field :updated_at, :naive_datetime_usec end ## === Changesets Functions === @@ -85,7 +85,7 @@ defmodule EpochtalkServer.Models.AutoModeration do """ @spec update_changeset(auto_moderation :: t(), attrs :: map() | nil) :: Ecto.Changeset.t() def update_changeset(auto_moderation, attrs \\ %{}) do - updated_at = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + updated_at = NaiveDateTime.utc_now() auto_moderation = auto_moderation diff --git a/lib/epochtalk_server/models/ban.ex b/lib/epochtalk_server/models/ban.ex index ba5b0b00..16b07adf 100644 --- a/lib/epochtalk_server/models/ban.ex +++ b/lib/epochtalk_server/models/ban.ex @@ -26,9 +26,9 @@ defmodule EpochtalkServer.Models.Ban do @derive {Jason.Encoder, only: [:user_id, :expiration, :created_at, :updated_at]} schema "bans" do belongs_to :user, User, primary_key: true - field :expiration, :naive_datetime - field :created_at, :naive_datetime - field :updated_at, :naive_datetime + field :expiration, :naive_datetime_usec + field :created_at, :naive_datetime_usec + field :updated_at, :naive_datetime_usec end ## === Changesets Functions === @@ -48,7 +48,7 @@ defmodule EpochtalkServer.Models.Ban do """ @spec ban_changeset(ban :: t(), attrs :: map() | nil) :: Ecto.Changeset.t() def ban_changeset(ban, attrs \\ %{}) do - now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + now = NaiveDateTime.utc_now() attrs = attrs @@ -69,7 +69,7 @@ defmodule EpochtalkServer.Models.Ban do """ @spec unban_changeset(ban :: t(), attrs :: map() | nil) :: Ecto.Changeset.t() def unban_changeset(ban, attrs \\ %{}) do - now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + now = NaiveDateTime.utc_now() # set ban expiration to now when unbanning attrs = diff --git a/lib/epochtalk_server/models/banned_address.ex b/lib/epochtalk_server/models/banned_address.ex index e11b5ffb..db0527dc 100644 --- a/lib/epochtalk_server/models/banned_address.ex +++ b/lib/epochtalk_server/models/banned_address.ex @@ -37,9 +37,9 @@ defmodule EpochtalkServer.Models.BannedAddress do field :ip4, :integer field :weight, :decimal field :decay, :boolean, default: false - field :imported_at, :naive_datetime - field :created_at, :naive_datetime - field :updates, {:array, :naive_datetime} + field :imported_at, :naive_datetime_usec + field :created_at, :naive_datetime_usec + field :updates, {:array, :naive_datetime_usec} end ## === Changesets Functions === @@ -49,7 +49,7 @@ defmodule EpochtalkServer.Models.BannedAddress do """ @spec upsert_changeset(banned_address :: t(), attrs :: map() | nil) :: Ecto.Changeset.t() def upsert_changeset(banned_address, attrs \\ %{}) do - now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + now = NaiveDateTime.utc_now() attrs = attrs diff --git a/lib/epochtalk_server/models/board.ex b/lib/epochtalk_server/models/board.ex index cbe20d8b..3a46e000 100644 --- a/lib/epochtalk_server/models/board.ex +++ b/lib/epochtalk_server/models/board.ex @@ -51,9 +51,9 @@ defmodule EpochtalkServer.Models.Board do field :viewable_by, :integer field :postable_by, :integer field :right_to_left, :boolean, default: false - field :created_at, :naive_datetime - field :imported_at, :naive_datetime - field :updated_at, :naive_datetime + field :created_at, :naive_datetime_usec + field :imported_at, :naive_datetime_usec + field :updated_at, :naive_datetime_usec field :meta, :map many_to_many :category, Category, join_through: BoardMapping end @@ -95,7 +95,7 @@ defmodule EpochtalkServer.Models.Board do """ @spec create_changeset(board :: t(), attrs :: map() | nil) :: Ecto.Changeset.t() def create_changeset(board, attrs) do - now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + now = NaiveDateTime.utc_now() attrs = attrs diff --git a/lib/epochtalk_server/models/category.ex b/lib/epochtalk_server/models/category.ex index d6b246f1..81e9285d 100644 --- a/lib/epochtalk_server/models/category.ex +++ b/lib/epochtalk_server/models/category.ex @@ -61,7 +61,7 @@ defmodule EpochtalkServer.Models.Category do """ @spec create_changeset(category :: t(), attrs :: map() | nil) :: Ecto.Changeset.t() def create_changeset(category, attrs) do - now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + now = NaiveDateTime.utc_now() attrs = attrs diff --git a/lib/epochtalk_server/models/image_reference.ex b/lib/epochtalk_server/models/image_reference.ex index 2a0a6749..267f7526 100644 --- a/lib/epochtalk_server/models/image_reference.ex +++ b/lib/epochtalk_server/models/image_reference.ex @@ -34,8 +34,8 @@ defmodule EpochtalkServer.Models.ImageReference do field :length, :integer field :type, :string field :checksum, :string - field :expiration, :naive_datetime - field :created_at, :naive_datetime + field :expiration, :naive_datetime_usec + field :created_at, :naive_datetime_usec many_to_many :posts, Post, join_through: PostImageReference # many_to_many :messages, Message, join_through: MessageImageReference many_to_many :profiles, Profile, join_through: ProfileImageReference @@ -76,7 +76,7 @@ defmodule EpochtalkServer.Models.ImageReference do """ @spec create_changeset(image_reference :: t(), attrs :: map() | nil) :: Ecto.Changeset.t() def create_changeset(image_reference, attrs) do - now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + now = NaiveDateTime.utc_now() uuid = Ecto.UUID.generate() attrs = @@ -174,7 +174,7 @@ defmodule EpochtalkServer.Models.ImageReference do end defp query_expired() do - now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + now = NaiveDateTime.utc_now() from i in ImageReference, where: i.expiration < ^now and i.posts == [] and i.messages == [] and i.profiles == [] diff --git a/lib/epochtalk_server/models/invitation.ex b/lib/epochtalk_server/models/invitation.ex index de850e18..6fe3beee 100644 --- a/lib/epochtalk_server/models/invitation.ex +++ b/lib/epochtalk_server/models/invitation.ex @@ -18,7 +18,7 @@ defmodule EpochtalkServer.Models.Invitation do schema "invitations" do field :email, :string field :hash, :string - field :created_at, :naive_datetime + field :created_at, :naive_datetime_usec end ## === Changesets Functions === @@ -28,7 +28,7 @@ defmodule EpochtalkServer.Models.Invitation do """ @spec create_changeset(invitation :: t(), attrs :: map() | nil) :: Ecto.Changeset.t() def create_changeset(invitation, attrs \\ %{}) do - now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + now = NaiveDateTime.utc_now() attrs = attrs diff --git a/lib/epochtalk_server/models/mention.ex b/lib/epochtalk_server/models/mention.ex index ba661f85..b71e2cf8 100644 --- a/lib/epochtalk_server/models/mention.ex +++ b/lib/epochtalk_server/models/mention.ex @@ -32,7 +32,7 @@ defmodule EpochtalkServer.Models.Mention do belongs_to :post, Post belongs_to :mentioner, User belongs_to :mentionee, User - field :created_at, :naive_datetime + field :created_at, :naive_datetime_usec field :viewed, :boolean, virtual: true field :notification_id, :integer, virtual: true end @@ -44,7 +44,7 @@ defmodule EpochtalkServer.Models.Mention do """ @spec create_changeset(mention :: t(), attrs :: map() | nil) :: Ecto.Changeset.t() def create_changeset(mention, attrs) do - now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + now = NaiveDateTime.utc_now() mention = mention diff --git a/lib/epochtalk_server/models/metadata_board.ex b/lib/epochtalk_server/models/metadata_board.ex index 8a82e959..a736bae7 100644 --- a/lib/epochtalk_server/models/metadata_board.ex +++ b/lib/epochtalk_server/models/metadata_board.ex @@ -48,7 +48,7 @@ defmodule EpochtalkServer.Models.MetadataBoard do field :total_post, :integer field :total_thread_count, :integer field :last_post_username, :string - field :last_post_created_at, :naive_datetime + field :last_post_created_at, :naive_datetime_usec field :last_thread_id, :integer field :last_thread_title, :string field :last_post_position, :integer diff --git a/lib/epochtalk_server/models/moderation_log.ex b/lib/epochtalk_server/models/moderation_log.ex index f3ec60d4..d93296af 100644 --- a/lib/epochtalk_server/models/moderation_log.ex +++ b/lib/epochtalk_server/models/moderation_log.ex @@ -44,7 +44,7 @@ defmodule EpochtalkServer.Models.ModerationLog do field :action_api_url, :string field :action_api_method, :string field :action_obj, :map - field :action_taken_at, :naive_datetime + field :action_taken_at, :naive_datetime_usec field :action_type, :string field :action_display_text, :string field :action_display_url, :string @@ -57,7 +57,7 @@ defmodule EpochtalkServer.Models.ModerationLog do """ @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) + now = NaiveDateTime.utc_now() display_data = ModerationLogHelper.get_display_data(get_in(attrs, [:action, :type])) diff --git a/lib/epochtalk_server/models/notification.ex b/lib/epochtalk_server/models/notification.ex index d247f629..cb3cceee 100644 --- a/lib/epochtalk_server/models/notification.ex +++ b/lib/epochtalk_server/models/notification.ex @@ -29,7 +29,7 @@ defmodule EpochtalkServer.Models.Notification do field :data, :map field :viewed, :boolean field :type, :string - field :created_at, :naive_datetime + field :created_at, :naive_datetime_usec end ## === Changesets Functions === diff --git a/lib/epochtalk_server/models/poll.ex b/lib/epochtalk_server/models/poll.ex index cf4e9c18..57265be7 100644 --- a/lib/epochtalk_server/models/poll.ex +++ b/lib/epochtalk_server/models/poll.ex @@ -40,7 +40,7 @@ defmodule EpochtalkServer.Models.Poll do field :question, :string field :locked, :boolean field :max_answers, :integer - field :expiration, :naive_datetime + field :expiration, :naive_datetime_usec field :change_vote, :boolean field :display_mode, Ecto.Enum, values: [:always, :voted, :expired] field :has_voted, :boolean, virtual: true diff --git a/lib/epochtalk_server/models/post.ex b/lib/epochtalk_server/models/post.ex index ec6c9ce7..03b44672 100644 --- a/lib/epochtalk_server/models/post.ex +++ b/lib/epochtalk_server/models/post.ex @@ -49,9 +49,9 @@ defmodule EpochtalkServer.Models.Post do field :position, :integer field :content, :map field :metadata, :map - field :created_at, :naive_datetime - field :updated_at, :naive_datetime - field :imported_at, :naive_datetime + field :created_at, :naive_datetime_usec + field :updated_at, :naive_datetime_usec + field :imported_at, :naive_datetime_usec # field :smf_message, :map, virtual: true end @@ -67,7 +67,7 @@ defmodule EpochtalkServer.Models.Post do ) :: Ecto.Changeset.t() # credo:disable-for-next-line def create_changeset(post, attrs, now_override \\ nil) do - now = now_override || NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + now = NaiveDateTime.utc_now() # set default values and timestamps post = @@ -476,7 +476,7 @@ defmodule EpochtalkServer.Models.Post do # update updated_at field if outside of 10 min grace period, # or if a moderator is editing a user's post - now = NaiveDateTime.truncate(now, :second) + now = now attrs = if (attrs.metadata != nil && Map.keys(attrs.metadata) != []) || outside_edit_window, diff --git a/lib/epochtalk_server/models/post_draft.ex b/lib/epochtalk_server/models/post_draft.ex index d1600a33..583fa8eb 100644 --- a/lib/epochtalk_server/models/post_draft.ex +++ b/lib/epochtalk_server/models/post_draft.ex @@ -25,7 +25,7 @@ defmodule EpochtalkServer.Models.PostDraft do schema "user_drafts" do belongs_to :user, User field :draft, :string - field :updated_at, :naive_datetime + field :updated_at, :naive_datetime_usec end ## === Changeset Functions === @@ -35,7 +35,7 @@ defmodule EpochtalkServer.Models.PostDraft do """ @spec upsert_changeset(draft :: PostDraft.t(), attrs :: map() | nil) :: Ecto.Changeset.t() def upsert_changeset(draft, attrs \\ %{}) do - updated_at = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + updated_at = NaiveDateTime.utc_now() draft = draft diff --git a/lib/epochtalk_server/models/profile.ex b/lib/epochtalk_server/models/profile.ex index 363c893e..74312aa3 100644 --- a/lib/epochtalk_server/models/profile.ex +++ b/lib/epochtalk_server/models/profile.ex @@ -29,7 +29,7 @@ defmodule EpochtalkServer.Models.Profile do field :raw_signature, :string field :post_count, :integer, default: 0 field :fields, :map - field :last_active, :naive_datetime + field :last_active, :naive_datetime_usec end ## === Changesets Functions === @@ -117,13 +117,13 @@ defmodule EpochtalkServer.Models.Profile do from(p in Profile, where: p.user_id == ^user_id) |> Repo.update_all( set: [ - last_active: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + last_active: NaiveDateTime.utc_now() ] ) end defp update_if_more_than_one_minute_has_passed(user_id, last_active) do - now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + now = NaiveDateTime.utc_now() last_active_plus_one_minute = NaiveDateTime.add(last_active, 1, :minute) at_least_one_minute_has_passed = diff --git a/lib/epochtalk_server/models/role.ex b/lib/epochtalk_server/models/role.ex index 7edae6fa..733b3a0c 100644 --- a/lib/epochtalk_server/models/role.ex +++ b/lib/epochtalk_server/models/role.ex @@ -49,8 +49,8 @@ defmodule EpochtalkServer.Models.Role do field :permissions, :map field :priority_restrictions, {:array, :integer} - field :created_at, :naive_datetime - field :updated_at, :naive_datetime + field :created_at, :naive_datetime_usec + field :updated_at, :naive_datetime_usec end ## === Changesets Functions === @@ -71,7 +71,7 @@ defmodule EpochtalkServer.Models.Role do """ @spec update_changeset(role :: Role.t(), attrs :: map() | nil) :: Ecto.Changeset.t() def update_changeset(role, attrs \\ %{}) do - updated_at = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + updated_at = NaiveDateTime.utc_now() role = role diff --git a/lib/epochtalk_server/models/thread.ex b/lib/epochtalk_server/models/thread.ex index 8bd1fb56..a200de75 100644 --- a/lib/epochtalk_server/models/thread.ex +++ b/lib/epochtalk_server/models/thread.ex @@ -52,9 +52,9 @@ defmodule EpochtalkServer.Models.Thread do field :slug, :string field :moderated, :boolean field :post_count, :integer - field :created_at, :naive_datetime - field :imported_at, :naive_datetime - field :updated_at, :naive_datetime + field :created_at, :naive_datetime_usec + field :imported_at, :naive_datetime_usec + field :updated_at, :naive_datetime_usec has_many :posts, Post field :poster_ids, {:array, :integer}, virtual: true field :user_id, :integer, virtual: true @@ -96,7 +96,7 @@ defmodule EpochtalkServer.Models.Thread do now_override :: NaiveDateTime.t() | nil ) :: Ecto.Changeset.t() def create_changeset(thread, attrs, now_override \\ nil) do - now = now_override || NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + now = NaiveDateTime.utc_now() # set default values and timestamps thread = diff --git a/lib/epochtalk_server/models/trust_feedback.ex b/lib/epochtalk_server/models/trust_feedback.ex index 60c46c58..48ef92f7 100644 --- a/lib/epochtalk_server/models/trust_feedback.ex +++ b/lib/epochtalk_server/models/trust_feedback.ex @@ -39,7 +39,7 @@ defmodule EpochtalkServer.Models.TrustFeedback do field :scammer, :boolean field :reference, :string field :comments, :string - field :created_at, :naive_datetime + field :created_at, :naive_datetime_usec end ## === Changesets Functions === diff --git a/lib/epochtalk_server/models/user.ex b/lib/epochtalk_server/models/user.ex index 5c11d3fe..8f11b35d 100644 --- a/lib/epochtalk_server/models/user.ex +++ b/lib/epochtalk_server/models/user.ex @@ -61,9 +61,9 @@ defmodule EpochtalkServer.Models.User do field :confirmation_token, :string field :reset_token, :string field :reset_expiration, :string - field :created_at, :naive_datetime - field :imported_at, :naive_datetime - field :updated_at, :naive_datetime + field :created_at, :naive_datetime_usec + field :imported_at, :naive_datetime_usec + field :updated_at, :naive_datetime_usec field :deleted, :boolean, default: false field :malicious_score, :decimal field :smf_member, :map, virtual: true @@ -84,7 +84,7 @@ defmodule EpochtalkServer.Models.User do """ @spec registration_changeset(user :: t(), attrs :: map() | nil) :: Ecto.Changeset.t() def registration_changeset(user, attrs) do - now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + now = NaiveDateTime.utc_now() # set timestamps user = diff --git a/lib/epochtalk_server/models/user_activity.ex b/lib/epochtalk_server/models/user_activity.ex index 744497f9..d56e97c1 100644 --- a/lib/epochtalk_server/models/user_activity.ex +++ b/lib/epochtalk_server/models/user_activity.ex @@ -37,8 +37,8 @@ defmodule EpochtalkServer.Models.UserActivity do @primary_key false schema "user_activity" do belongs_to :user, User - field :current_period_start, :naive_datetime - field :current_period_offset, :naive_datetime + field :current_period_start, :naive_datetime_usec + field :current_period_offset, :naive_datetime_usec field :remaining_period_activity, :integer, default: 14 field :total_activity, :integer, default: 0 end @@ -114,7 +114,7 @@ defmodule EpochtalkServer.Models.UserActivity do period_start_unix = to_unix(info.current_period_start) period_end_naive = from_unix(period_start_unix + @period_length_ms) - now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + now = NaiveDateTime.utc_now() # update info if period has ended period_ended = NaiveDateTime.compare(now, period_end_naive) == :gt diff --git a/lib/epochtalk_server/models/user_ignored.ex b/lib/epochtalk_server/models/user_ignored.ex index aae1a21d..a85c07c0 100644 --- a/lib/epochtalk_server/models/user_ignored.ex +++ b/lib/epochtalk_server/models/user_ignored.ex @@ -25,7 +25,7 @@ defmodule EpochtalkServer.Models.UserIgnored do schema "ignored" do belongs_to :user, User belongs_to :ignored_user, User - field :created_at, :naive_datetime + field :created_at, :naive_datetime_usec end ## === Database Functions === diff --git a/lib/epochtalk_server/models/user_ip.ex b/lib/epochtalk_server/models/user_ip.ex index 6b6a74b4..5b6685b7 100644 --- a/lib/epochtalk_server/models/user_ip.ex +++ b/lib/epochtalk_server/models/user_ip.ex @@ -23,7 +23,7 @@ defmodule EpochtalkServer.Models.UserIp do schema "ips" do belongs_to :user, User field :user_ip, :string - field :created_at, :naive_datetime + field :created_at, :naive_datetime_usec end ## === Database Functions === @@ -40,7 +40,7 @@ defmodule EpochtalkServer.Models.UserIp do %UserIp{ user_id: user_id, user_ip: user_ip, - created_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + created_at: NaiveDateTime.utc_now() }, on_conflict: :nothing, conflict_target: [:user_id, :user_ip] diff --git a/lib/epochtalk_server/models/user_thread_view.ex b/lib/epochtalk_server/models/user_thread_view.ex index 13f540ae..b498bad0 100644 --- a/lib/epochtalk_server/models/user_thread_view.ex +++ b/lib/epochtalk_server/models/user_thread_view.ex @@ -24,7 +24,7 @@ defmodule EpochtalkServer.Models.UserThreadView do schema "thread_views" do belongs_to :user, User belongs_to :thread, Thread - field :time, :naive_datetime + field :time, :naive_datetime_usec end ## === Database Functions === @@ -36,7 +36,7 @@ defmodule EpochtalkServer.Models.UserThreadView do @spec upsert(user_id :: non_neg_integer, thread_id :: non_neg_integer) :: {:ok, t()} | {:error, Ecto.Changeset.t()} def upsert(user_id, thread_id) when is_integer(user_id) and is_integer(thread_id) do - now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) + now = NaiveDateTime.utc_now() Repo.insert( %UserThreadView{user_id: user_id, thread_id: thread_id, time: now}, diff --git a/lib/epochtalk_server_web/json/poll_json.ex b/lib/epochtalk_server_web/json/poll_json.ex index 94c63484..4294a19d 100644 --- a/lib/epochtalk_server_web/json/poll_json.ex +++ b/lib/epochtalk_server_web/json/poll_json.ex @@ -49,7 +49,7 @@ defmodule EpochtalkServerWeb.Controllers.PollJSON do ) # hide votes if poll is not expired and display mode is set to display votes when expired - now = NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + now = NaiveDateTime.utc_now() hide_votes = (poll.display_mode === :voted && !has_voted) || diff --git a/priv/repo/seed_roles.exs b/priv/repo/seed_roles.exs index ee886035..91976aa2 100644 --- a/priv/repo/seed_roles.exs +++ b/priv/repo/seed_roles.exs @@ -9,8 +9,8 @@ roles = [ priority: 0, highlight_color: "#FF7442", permissions: %{}, - created_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second), - updated_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + created_at: NaiveDateTime.utc_now(), + updated_at: NaiveDateTime.utc_now() }, %{ id: 2, @@ -20,8 +20,8 @@ roles = [ priority: 1, highlight_color: "#FF4C4C", permissions: %{}, - created_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second), - updated_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + created_at: NaiveDateTime.utc_now(), + updated_at: NaiveDateTime.utc_now() }, %{ id: 3, @@ -31,8 +31,8 @@ roles = [ priority: 2, highlight_color: "#32A56E", permissions: %{}, - created_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second), - updated_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + created_at: NaiveDateTime.utc_now(), + updated_at: NaiveDateTime.utc_now() }, %{ id: 4, @@ -42,8 +42,8 @@ roles = [ priority: 3, highlight_color: "#508DD0", permissions: %{}, - created_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second), - updated_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + created_at: NaiveDateTime.utc_now(), + updated_at: NaiveDateTime.utc_now() }, %{ id: 5, @@ -52,8 +52,8 @@ roles = [ description: "Standard account with access to create threads and post", priority: 4, permissions: %{}, - created_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second), - updated_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + created_at: NaiveDateTime.utc_now(), + updated_at: NaiveDateTime.utc_now() }, %{ id: 6, @@ -62,8 +62,8 @@ roles = [ description: "Moderates Newbies only, otherwise mirrors User role unless modified", priority: 5, permissions: %{}, - created_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second), - updated_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + created_at: NaiveDateTime.utc_now(), + updated_at: NaiveDateTime.utc_now() }, %{ id: 7, @@ -72,8 +72,8 @@ roles = [ description: "Brand new users", priority: 6, permissions: %{}, - created_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second), - updated_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + created_at: NaiveDateTime.utc_now(), + updated_at: NaiveDateTime.utc_now() }, %{ id: 8, @@ -83,8 +83,8 @@ roles = [ priority: 7, priority_restrictions: [0, 1, 2, 3], permissions: %{}, - created_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second), - updated_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + created_at: NaiveDateTime.utc_now(), + updated_at: NaiveDateTime.utc_now() }, %{ id: 9, @@ -93,8 +93,8 @@ roles = [ description: "Read only access", priority: 8, permissions: %{}, - created_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second), - updated_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + created_at: NaiveDateTime.utc_now(), + updated_at: NaiveDateTime.utc_now() }, %{ id: 10, @@ -103,8 +103,8 @@ roles = [ description: "Role assigned to unauthorized users when public forum is disabled", priority: 9, permissions: %{}, - created_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second), - updated_at: NaiveDateTime.utc_now() |> NaiveDateTime.truncate(:second) + created_at: NaiveDateTime.utc_now(), + updated_at: NaiveDateTime.utc_now() } ] From 8b41a6564f89778cee3ea9721c1c6b49412e852c Mon Sep 17 00:00:00 2001 From: unenglishable Date: Fri, 6 Sep 2024 13:49:21 -0700 Subject: [PATCH 09/17] test(controllers/user): remove date truncate when checking user created/updated at --- test/epochtalk_server_web/controllers/user_test.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/epochtalk_server_web/controllers/user_test.exs b/test/epochtalk_server_web/controllers/user_test.exs index f3327b06..2319200d 100644 --- a/test/epochtalk_server_web/controllers/user_test.exs +++ b/test/epochtalk_server_web/controllers/user_test.exs @@ -94,8 +94,8 @@ defmodule Test.EpochtalkServerWeb.Controllers.User do {:ok, registered_user} = User.by_username(register_attrs.username) assert response["id"] == registered_user.id - assert registered_user.created_at == mocked_date |> NaiveDateTime.truncate(:second) - assert registered_user.updated_at == mocked_date |> NaiveDateTime.truncate(:second) + assert registered_user.created_at == mocked_date + assert registered_user.updated_at == mocked_date end test "when email is already taken, errors", %{ From 560c6791854ca167c8dc470662e3e6fefe0ef602 Mon Sep 17 00:00:00 2001 From: unenglishable Date: Fri, 6 Sep 2024 13:53:45 -0700 Subject: [PATCH 10/17] test(controllers/poll): remove string split (truncate) for iso8601 dates --- test/epochtalk_server_web/controllers/poll_test.exs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/epochtalk_server_web/controllers/poll_test.exs b/test/epochtalk_server_web/controllers/poll_test.exs index 4c831742..6a4fe7b2 100644 --- a/test/epochtalk_server_web/controllers/poll_test.exs +++ b/test/epochtalk_server_web/controllers/poll_test.exs @@ -771,8 +771,7 @@ defmodule Test.EpochtalkServerWeb.Controllers.Poll do } do expiration = NaiveDateTime.utc_now() |> NaiveDateTime.add(10) - expiration_string = - NaiveDateTime.to_iso8601(expiration) |> String.split(".") |> List.first() + expiration_string = NaiveDateTime.to_iso8601(expiration) Poll.update(%{"thread_id" => thread_id, "expiration" => expiration}) @@ -958,8 +957,7 @@ defmodule Test.EpochtalkServerWeb.Controllers.Poll do } do expiration = NaiveDateTime.utc_now() |> NaiveDateTime.add(10) - expiration_string = - NaiveDateTime.to_iso8601(expiration) |> String.split(".") |> List.first() + expiration_string = NaiveDateTime.to_iso8601(expiration) Poll.update(%{"thread_id" => thread_id, "expiration" => expiration}) From d3d1e5345988c36dcb4356fa6da9d52a35ae3800 Mon Sep 17 00:00:00 2001 From: unenglishable Date: Fri, 6 Sep 2024 13:56:24 -0700 Subject: [PATCH 11/17] test(session): update max_date to microsecond precision --- test/epochtalk_server/session_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/epochtalk_server/session_test.exs b/test/epochtalk_server/session_test.exs index cae96e6c..b1aa057c 100644 --- a/test/epochtalk_server/session_test.exs +++ b/test/epochtalk_server/session_test.exs @@ -9,7 +9,7 @@ defmodule Test.EpochtalkServer.Session do @almost_one_day_in_seconds @one_day_in_seconds - 100 @four_weeks_in_seconds 4 * 7 * @one_day_in_seconds @almost_four_weeks_in_seconds @four_weeks_in_seconds - 100 - @max_date "9999-12-31 00:00:00" + @max_date "9999-12-31 00:00:00.000000" alias EpochtalkServer.Session alias EpochtalkServer.Models.Profile alias EpochtalkServer.Models.User From 62a624fca4f2016241c888cb88cc9cc172fadae9 Mon Sep 17 00:00:00 2001 From: unenglishable Date: Fri, 6 Sep 2024 15:00:49 -0700 Subject: [PATCH 12/17] test(support/factories): use original create() for thread and post updates to timestamp precision in created_at/updated_at no longer require custom timestamp to be inserted --- test/support/factories/post.ex | 5 +---- test/support/factories/thread.ex | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/test/support/factories/post.ex b/test/support/factories/post.ex index be2e98e0..c9e78af9 100644 --- a/test/support/factories/post.ex +++ b/test/support/factories/post.ex @@ -20,10 +20,7 @@ defmodule Test.Support.Factories.Post do def post_factory(%{user: user, thread: thread} = attrs) do attributes = build(:post_attributes, attrs) - timestamp = - sequence(:post_timestamp, &NaiveDateTime.add(~N[1970-01-01 00:00:00], &1 * 60 * 60)) - - Post.create_for_test(attributes, timestamp) + Post.create(attributes) end end end diff --git a/test/support/factories/thread.ex b/test/support/factories/thread.ex index fe316491..4c1998e7 100644 --- a/test/support/factories/thread.ex +++ b/test/support/factories/thread.ex @@ -23,10 +23,7 @@ defmodule Test.Support.Factories.Thread do def thread_factory(%{board: board, user: user} = attrs) do attributes = build(:thread_attributes, attrs) - timestamp = - sequence(:post_timestamp, &NaiveDateTime.add(~N[1970-01-01 00:00:00], &1 * 60 * 60)) - - Thread.create(attributes, user, timestamp) + Thread.create(attributes, user) |> case do {:ok, thread} -> thread_id = thread.post.thread.id From 624a0bcf6db37173d0a05680cb7188b2ed7048bb Mon Sep 17 00:00:00 2001 From: unenglishable Date: Mon, 9 Sep 2024 10:01:08 -0700 Subject: [PATCH 13/17] test(controllers/thread): refactor data creation move data for "move" test into the test update comments to make them more descriptive --- .../controllers/thread_test.exs | 52 +++++++++++-------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/test/epochtalk_server_web/controllers/thread_test.exs b/test/epochtalk_server_web/controllers/thread_test.exs index c45c0fd9..63f311d6 100644 --- a/test/epochtalk_server_web/controllers/thread_test.exs +++ b/test/epochtalk_server_web/controllers/thread_test.exs @@ -11,7 +11,6 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do setup %{ users: %{ user: user, - mod_user: mod_user, admin_user: admin_user, super_admin_user: super_admin_user } @@ -37,29 +36,19 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do admin_board_thread = build(:thread, board: admin_board, user: admin_user) super_admin_board_thread = build(:thread, board: super_admin_board, user: super_admin_user) - # create thread and replies in move_board to compare last post info in tests below - move_board_thread = build(:thread, board: move_board, user: user) - - # create posts in thread created above, this is to get a specific number of thread replies - [_, {:ok, move_board_last_post}] = - build_list(2, :post, user: mod_user, thread: move_board_thread.post.thread) - + # create a thread for posting on + thread = build(:thread, board: board, user: user) + # create a specific number of posts (thread replies) num_thread_replies = 3 + build_list(num_thread_replies, :post, user: user, thread: thread.post.thread) + # the thread's total post count includes + # the original post made when creating the thread thread_post_count = num_thread_replies + 1 - thread = build(:thread, board: board, user: user) - - # create posts in thread created above, this is to get a specific number of thread replies - [_, _, {:ok, board_last_post}] = - build_list(num_thread_replies, :post, user: user, thread: thread.post.thread) - # NOTE: building additional posts or threads within "thread" or "move_board_thread" - # will break move thread tests which tests last post info { :ok, board: board, move_board: move_board, - board_last_post: board_last_post, - move_board_last_post: move_board_last_post, admin_board: admin_board, super_admin_board: super_admin_board, factory_threads: factory_threads, @@ -953,12 +942,31 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do @tag authenticated: :global_mod test "after moving thread, updates last post info of each board", %{ conn: conn, - board: %{id: old_board_id}, - move_board: %{id: new_board_id}, - board_last_post: old_board_last_post, - admin_priority_thread: old_board_second_to_last_thread, - move_board_last_post: new_board_last_post + board: %{ + id: old_board_id + }, + move_board: move_board, + users: %{ + user: user, + mod_user: mod_user + }, + thread: thread, + admin_priority_thread: old_board_second_to_last_thread } do + %{id: new_board_id} = move_board + # create thread and replies in move_board to compare last post info in tests below + move_board_thread = build(:thread, board: move_board, user: user) + + # create posts in move board thread + # and get last post for comparison + move_board_factory_posts = build_list(2, :post, user: mod_user, thread: move_board_thread.post.thread) + [_, {:ok, new_board_last_post}] = move_board_factory_posts + + # create a post on old board that's newer than last post on old board + # (this is to test that last post gets updated on the new board) + # add post to thread under original post + {:ok, old_board_last_post} = build(:post, user: user, thread: thread.post.thread) + all_boards = BoardMapping.all() [old_board_before_move] = Enum.filter(all_boards, fn bm -> bm.board_id == old_board_id end) [new_board_before_move] = Enum.filter(all_boards, fn bm -> bm.board_id == new_board_id end) From ca322707094c337b8139a315c8a2a87d2c9c73f1 Mon Sep 17 00:00:00 2001 From: unenglishable Date: Mon, 9 Sep 2024 10:18:30 -0700 Subject: [PATCH 14/17] test(controllers/thread): mix format --- test/epochtalk_server_web/controllers/thread_test.exs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/epochtalk_server_web/controllers/thread_test.exs b/test/epochtalk_server_web/controllers/thread_test.exs index 63f311d6..2fe43a75 100644 --- a/test/epochtalk_server_web/controllers/thread_test.exs +++ b/test/epochtalk_server_web/controllers/thread_test.exs @@ -959,7 +959,9 @@ defmodule Test.EpochtalkServerWeb.Controllers.Thread do # create posts in move board thread # and get last post for comparison - move_board_factory_posts = build_list(2, :post, user: mod_user, thread: move_board_thread.post.thread) + move_board_factory_posts = + build_list(2, :post, user: mod_user, thread: move_board_thread.post.thread) + [_, {:ok, new_board_last_post}] = move_board_factory_posts # create a post on old board that's newer than last post on old board From 33aaa02cf27bdc4a700e8b46a6de52cc1317db47 Mon Sep 17 00:00:00 2001 From: unenglishable Date: Mon, 9 Sep 2024 10:24:33 -0700 Subject: [PATCH 15/17] revert(models/thread): reset changes for specifying created_at --- lib/epochtalk_server/models/thread.ex | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/lib/epochtalk_server/models/thread.ex b/lib/epochtalk_server/models/thread.ex index a200de75..dafa37b3 100644 --- a/lib/epochtalk_server/models/thread.ex +++ b/lib/epochtalk_server/models/thread.ex @@ -90,12 +90,8 @@ defmodule EpochtalkServer.Models.Thread do @doc """ Create changeset for creation of `Thread` model """ - @spec create_changeset( - thread :: t(), - attrs :: map() | nil, - now_override :: NaiveDateTime.t() | nil - ) :: Ecto.Changeset.t() - def create_changeset(thread, attrs, now_override \\ nil) do + @spec create_changeset(thread :: t(), attrs :: map() | nil) :: Ecto.Changeset.t() + def create_changeset(thread, attrs) do now = NaiveDateTime.utc_now() # set default values and timestamps @@ -129,9 +125,9 @@ defmodule EpochtalkServer.Models.Thread do @doc """ Creates a new `Thread` in the database """ - @spec create(thread_attrs :: map(), user :: map(), timestamp :: NaiveDateTime.t() | nil) :: + @spec create(thread_attrs :: map(), user :: map()) :: {:ok, thread :: t()} | {:error, Ecto.Changeset.t()} - def create(thread_attrs, user, timestamp \\ nil) do + def create(thread_attrs, user) do thread_cs = create_changeset(%Thread{}, thread_attrs) case Repo.transaction(fn -> @@ -147,7 +143,7 @@ defmodule EpochtalkServer.Models.Thread do # create poll, if necessary db_poll = handle_create_poll(db_thread.id, thread_attrs["poll"], user) # create post - db_post = handle_create_post(db_thread.id, thread_attrs, user, timestamp) + db_post = handle_create_post(db_thread.id, thread_attrs, user) # return post (preloaded thread) and poll data %{post: db_post, poll: db_poll} end) do @@ -894,7 +890,7 @@ defmodule EpochtalkServer.Models.Thread do end end - defp handle_create_post(thread_id, thread_attrs, user, timestamp) do + defp handle_create_post(thread_id, thread_attrs, user) do post_attrs = %{ thread_id: thread_id, user_id: user.id, @@ -905,12 +901,7 @@ defmodule EpochtalkServer.Models.Thread do } } - if is_nil(timestamp) do - Post.create(post_attrs) - else - Post.create_for_test(post_attrs, timestamp) - end - |> case do + case Post.create(post_attrs) do {:ok, post} -> post {:error, cs} -> Repo.rollback(cs) end From f402c55f279b50e92d4dee73b4dc57f426cbd91f Mon Sep 17 00:00:00 2001 From: unenglishable Date: Mon, 9 Sep 2024 10:28:41 -0700 Subject: [PATCH 16/17] revert(models/post): reset changes for specifying created_at --- lib/epochtalk_server/models/post.ex | 66 ++++++++++------------------- 1 file changed, 22 insertions(+), 44 deletions(-) diff --git a/lib/epochtalk_server/models/post.ex b/lib/epochtalk_server/models/post.ex index 03b44672..b32e383e 100644 --- a/lib/epochtalk_server/models/post.ex +++ b/lib/epochtalk_server/models/post.ex @@ -60,13 +60,8 @@ defmodule EpochtalkServer.Models.Post do @doc """ Create changeset for `Post` model """ - @spec create_changeset( - post :: t(), - attrs :: map() | nil, - now_override :: NaiveDateTime.t() | nil - ) :: Ecto.Changeset.t() - # credo:disable-for-next-line - def create_changeset(post, attrs, now_override \\ nil) do + @spec create_changeset(post :: t(), attrs :: map() | nil) :: Ecto.Changeset.t() + def create_changeset(post, attrs) do now = NaiveDateTime.utc_now() # set default values and timestamps @@ -170,20 +165,28 @@ defmodule EpochtalkServer.Models.Post do Repo.transaction(fn -> post_cs = create_changeset(%Post{}, post_attrs) - create_post_shared(post_cs) - end) - end + case Repo.insert(post_cs) do + # changeset valid, insert success, update metadata threads and return thread + {:ok, db_post} -> + # Increment user post count + Profile.increment_post_count(db_post.user_id) - @doc """ - Creates a new `Post` in the database, used during testing. Allows modification of created_at - """ - @spec create_for_test(post_attrs :: map(), timestamp :: NaiveDateTime.t()) :: - {:ok, post :: t()} | {:error, Ecto.Changeset.t()} - def create_for_test(post_attrs, timestamp) do - Repo.transaction(fn -> - post_cs = create_changeset(%Post{}, post_attrs, timestamp) + # Set thread created_at and updated_at + Thread.set_timestamps(db_post.thread_id) + + # Set post position + Post.set_position_using_thread(db_post.id, db_post.thread_id) + + # Increment thread post ocunt + Thread.increment_post_count(db_post.thread_id) + + # Requery post with position and thread slug info + Repo.one(from p in Post, where: p.id == ^db_post.id, preload: [:thread]) - create_post_shared(post_cs) + # changeset error + {:error, cs} -> + Repo.rollback(cs) + end end) end @@ -494,29 +497,4 @@ defmodule EpochtalkServer.Models.Post do |> Map.delete("user_id") |> Map.delete("title") end - - defp create_post_shared(post_cs) do - case Repo.insert(post_cs) do - # changeset valid, insert success, update metadata threads and return thread - {:ok, db_post} -> - # Increment user post count - Profile.increment_post_count(db_post.user_id) - - # Set thread created_at and updated_at - Thread.set_timestamps(db_post.thread_id) - - # Set post position - Post.set_position_using_thread(db_post.id, db_post.thread_id) - - # Increment thread post ocunt - Thread.increment_post_count(db_post.thread_id) - - # Requery post with position and thread slug info - Repo.one(from p in Post, where: p.id == ^db_post.id, preload: [:thread]) - - # changeset error - {:error, cs} -> - Repo.rollback(cs) - end - end end From 27c46c86e1150c43ddde4d909e1a4190fc2517bc Mon Sep 17 00:00:00 2001 From: unenglishable Date: Tue, 10 Sep 2024 13:10:43 -0700 Subject: [PATCH 17/17] refactor(models/post): remove redundant code --- lib/epochtalk_server/models/post.ex | 2 -- 1 file changed, 2 deletions(-) diff --git a/lib/epochtalk_server/models/post.ex b/lib/epochtalk_server/models/post.ex index b32e383e..f4f29038 100644 --- a/lib/epochtalk_server/models/post.ex +++ b/lib/epochtalk_server/models/post.ex @@ -479,8 +479,6 @@ defmodule EpochtalkServer.Models.Post do # update updated_at field if outside of 10 min grace period, # or if a moderator is editing a user's post - now = now - attrs = if (attrs.metadata != nil && Map.keys(attrs.metadata) != []) || outside_edit_window, do: Map.put(attrs, :updated_at, now),