From: Egor Kislitsyn Date: Thu, 25 Apr 2019 06:41:10 +0000 (+0700) Subject: Merge branch 'develop' into feature/disable-account X-Git-Url: http://git.squeep.com/?a=commitdiff_plain;h=c157e27a000a12dc8f660c056744a6611beb01b1;hp=-c;p=akkoma Merge branch 'develop' into feature/disable-account --- c157e27a000a12dc8f660c056744a6611beb01b1 diff --combined config/config.exs index 9dc9387c8,b11e4c680..80f0c3f25 --- a/config/config.exs +++ b/config/config.exs @@@ -230,7 -230,8 +230,8 @@@ config :pleroma, :instance welcome_user_nickname: nil, welcome_message: nil, max_report_comment_size: 1000, - safe_dm_mentions: false + safe_dm_mentions: false, + healthcheck: false config :pleroma, :markup, # XXX - unfortunately, inline images must be enabled by default right now, because @@@ -413,8 -414,7 +414,8 @@@ config :pleroma_job_queue, :queues web_push: 50, mailer: 10, transmogrifier: 20, - scheduled_activities: 10 + scheduled_activities: 10, + user: 10 config :pleroma, :fetch_initial_posts, enabled: false, diff --combined docs/api/pleroma_api.md index b9622f586,190846de9..dd0b6ca73 --- a/docs/api/pleroma_api.md +++ b/docs/api/pleroma_api.md @@@ -61,15 -61,6 +61,15 @@@ Request parameters can be passed via [q * Response: JSON. Returns `{"status": "success"}` if the deletion was successful, `{"error": "[error message]"}` otherwise * Example response: `{"error": "Invalid password."}` +## `/api/pleroma/disable_account` +### Disable an account +* Method `POST` +* Authentication: required +* Params: + * `password`: user's password +* Response: JSON. Returns `{"status": "success"}` if the account was successfully disabled, `{"error": "[error message]"}` otherwise +* Example response: `{"error": "Invalid password."}` + ## `/api/account/register` ### Register a new user * Method `POST` @@@ -86,7 -77,7 +86,7 @@@ * `token`: invite token required when the registrations aren't public. * Response: JSON. Returns a user object on success, otherwise returns `{"error": "error_msg"}` * Example response: - ``` + ```json { "background_image": null, "cover_photo": "https://pleroma.soykaf.com/images/banner.png", @@@ -196,6 -187,62 +196,62 @@@ See [Admin-API](Admin-API.md } ``` + ## `/api/v1/pleroma/accounts/:id/favourites` + ### Returns favorites timeline of any user + * Method `GET` + * Authentication: not required + * Params: + * `id`: the id of the account for whom to return results + * `limit`: optional, the number of records to retrieve + * `since_id`: optional, returns results that are more recent than the specified id + * `max_id`: optional, returns results that are older than the specified id + * Response: JSON, returns a list of Mastodon Status entities on success, otherwise returns `{"error": "error_msg"}` + * Example response: + ```json + [ + { + "account": { + "id": "9hptFmUF3ztxYh3Svg", + "url": "https://pleroma.example.org/users/nick2", + "username": "nick2", + ... + }, + "application": {"name": "Web", "website": null}, + "bookmarked": false, + "card": null, + "content": "This is :moominmamma: note 0", + "created_at": "2019-04-15T15:42:15.000Z", + "emojis": [], + "favourited": false, + "favourites_count": 1, + "id": "9hptFmVJ02khbzYJaS", + "in_reply_to_account_id": null, + "in_reply_to_id": null, + "language": null, + "media_attachments": [], + "mentions": [], + "muted": false, + "pinned": false, + "pleroma": { + "content": {"text/plain": "This is :moominmamma: note 0"}, + "conversation_id": 13679, + "local": true, + "spoiler_text": {"text/plain": "2hu"} + }, + "reblog": null, + "reblogged": false, + "reblogs_count": 0, + "replies_count": 0, + "sensitive": false, + "spoiler_text": "2hu", + "tags": [{"name": "2hu", "url": "/tag/2hu"}], + "uri": "https://pleroma.example.org/objects/198ed2a1-7912-4482-b559-244a0369e984", + "url": "https://pleroma.example.org/notice/9hptFmVJ02khbzYJaS", + "visibility": "public" + } + ] + ``` + ## `/api/pleroma/notification_settings` ### Updates user notification settings * Method `PUT` @@@ -206,3 -253,20 +262,20 @@@ * `remote`: BOOLEAN field, receives notifications from people on remote instances * `local`: BOOLEAN field, receives notifications from people on the local instance * Response: JSON. Returns `{"status": "success"}` if the update was successful, otherwise returns `{"error": "error_msg"}` + + ## `/api/pleroma/healthcheck` + ### Healthcheck endpoint with additional system data. + * Method `GET` + * Authentication: not required + * Params: none + * Response: JSON, statuses (200 - healthy, 503 unhealthy). + * Example response: + ```json + { + "pool_size": 0, # database connection pool + "active": 0, # active processes + "idle": 0, # idle processes + "memory_used": 0.00, # Memory used + "healthy": true # Instance state + } + ``` diff --combined lib/pleroma/notification.ex index 585157efe,dd274cf6b..844264307 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@@ -33,13 -33,6 +33,13 @@@ defmodule Pleroma.Notification d def for_user_query(user) do Notification |> where(user_id: ^user.id) + |> where( + [n, a], + fragment( + "? not in (SELECT ap_id FROM users WHERE info->'deactivated' @> 'true')", + a.actor + ) + ) |> join(:inner, [n], activity in assoc(n, :activity)) |> join(:left, [n, a], object in Object, on: @@@ -203,7 -196,7 +203,7 @@@ def skip?(:follows, activity, %{info: %{notification_settings: %{"follows" => false}}} = user) do actor = activity.data["actor"] - followed = User.get_by_ap_id(actor) + followed = User.get_cached_by_ap_id(actor) User.following?(user, followed) end diff --combined lib/pleroma/user.ex index 6aaa3244f,f1feab279..d103cd809 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@@ -107,8 -107,10 +107,8 @@@ defmodule Pleroma.User d def ap_followers(%User{} = user), do: "#{ap_id(user)}/followers" def user_info(%User{} = user) do - oneself = if user.local, do: 1, else: 0 - %{ - following_count: length(user.following) - oneself, + following_count: following_count(user), note_count: user.info.note_count, follower_count: user.info.follower_count, locked: user.info.locked, @@@ -117,23 -119,6 +117,23 @@@ } end + defp restrict_deactivated(query) do + from(u in query, + where: not fragment("? \\? 'deactivated' AND ?->'deactivated' @> 'true'", u.info, u.info) + ) + end + + def following_count(%User{following: []}), do: 0 + + def following_count(%User{following: following, id: id}) do + from(u in User, + where: u.follower_address in ^following, + where: u.id != ^id + ) + |> restrict_deactivated() + |> Repo.aggregate(:count, :id) + end + def remote_user_creation(params) do params = params @@@ -284,6 -269,7 +284,7 @@@ def register(%Ecto.Changeset{} = changeset) do with {:ok, user} <- Repo.insert(changeset), {:ok, user} <- autofollow_users(user), + {:ok, user} <- set_cache(user), {:ok, _} <- Pleroma.User.WelcomeMessage.post_welcome_message_to_user(user), {:ok, _} <- try_send_confirmation_email(user) do {:ok, user} @@@ -468,10 -454,13 +469,13 @@@ name = List.last(String.split(ap_id, "/")) nickname = "#{name}@#{domain}" - get_by_nickname(nickname) + get_cached_by_nickname(nickname) end - def set_cache(user) do + def set_cache({:ok, user}), do: set_cache(user) + def set_cache({:error, err}), do: {:error, err} + + def set_cache(%User{} = user) do Cachex.put(:user_cache, "ap_id:#{user.ap_id}", user) Cachex.put(:user_cache, "nickname:#{user.nickname}", user) Cachex.put(:user_cache, "user_info:#{user.id}", user_info(user)) @@@ -559,6 -548,7 +563,7 @@@ with [_nick, _domain] <- String.split(nickname, "@"), {:ok, user} <- fetch_by_nickname(nickname) do if Pleroma.Config.get([:fetch_initial_posts, :enabled]) do + # TODO turn into job {:ok, _} = Task.start(__MODULE__, :fetch_initial_posts, [user]) end @@@ -586,7 -576,6 +591,7 @@@ where: fragment("? <@ ?", ^[follower_address], u.following), where: u.id != ^id ) + |> restrict_deactivated() end def get_followers_query(user, page) do @@@ -614,7 -603,6 +619,7 @@@ where: u.follower_address in ^following, where: u.id != ^id ) + |> restrict_deactivated() end def get_friends_query(user, page) do @@@ -726,10 -714,11 +731,10 @@@ info_cng = User.Info.set_note_count(user.info, note_count) - cng = - change(user) - |> put_embed(:info, info_cng) - - update_and_set_cache(cng) + user + |> change() + |> put_embed(:info, info_cng) + |> update_and_set_cache() end def update_follower_count(%User{} = user) do @@@ -738,7 -727,6 +743,7 @@@ |> where([u], ^user.follower_address in u.following) |> where([u], u.id != ^user.id) |> select([u], %{count: count(u.id)}) + |> restrict_deactivated() User |> where(id: ^user.id) @@@ -889,7 -877,6 +894,7 @@@ ^processed_query ) ) + |> restrict_deactivated() end defp trigram_search_subquery(term) do @@@ -908,7 -895,6 +913,7 @@@ }, where: fragment("trim(? || ' ' || coalesce(?, '')) % ?", u.nickname, u.name, ^term) ) + |> restrict_deactivated() end def blocks_import(%User{} = blocker, blocked_identifiers) when is_list(blocked_identifiers) do @@@ -1021,7 -1007,7 +1026,7 @@@ # helper to handle the block given only an actor's AP id def block(blocker, %{ap_id: ap_id}) do - block(blocker, User.get_by_ap_id(ap_id)) + block(blocker, get_cached_by_ap_id(ap_id)) end def unblock(blocker, %{ap_id: ap_id}) do @@@ -1051,7 -1037,7 +1056,7 @@@ end def subscribed_to?(user, %{ap_id: ap_id}) do - with %User{} = target <- User.get_by_ap_id(ap_id) do + with %User{} = target <- get_cached_by_ap_id(ap_id) do Enum.member?(target.info.subscribers, user.ap_id) end end @@@ -1152,27 -1138,14 +1157,27 @@@ ) end + def deactivate_async(user, status \\ true) do + PleromaJobQueue.enqueue(:user, __MODULE__, [:deactivate_async, user, status]) + end + + def perform(:deactivate_async, user, status), do: deactivate(user, status) + def deactivate(%User{} = user, status \\ true) do info_cng = User.Info.set_activation_status(user.info, status) - cng = - change(user) - |> put_embed(:info, info_cng) + with {:ok, friends} <- User.get_friends(user), + {:ok, followers} <- User.get_followers(user), + {:ok, user} <- + user + |> change() + |> put_embed(:info, info_cng) + |> update_and_set_cache() do + Enum.each(followers, &invalidate_cache(&1)) + Enum.each(friends, &update_follower_count(&1)) - update_and_set_cache(cng) + {:ok, user} + end end def update_notification_settings(%User{} = user, settings \\ %{}) do @@@ -1239,7 -1212,7 +1244,7 @@@ end def get_or_fetch_by_ap_id(ap_id) do - user = get_by_ap_id(ap_id) + user = get_cached_by_ap_id(ap_id) if !is_nil(user) and !User.needs_update?(user) do user @@@ -1262,7 -1235,7 +1267,7 @@@ def get_or_create_instance_user do relay_uri = "#{Pleroma.Web.Endpoint.url()}/relay" - if user = get_by_ap_id(relay_uri) do + if user = get_cached_by_ap_id(relay_uri) do user else changes = @@@ -1309,13 -1282,11 +1314,11 @@@ defp blank?(n), do: n def insert_or_update_user(data) do - data = - data - |> Map.put(:name, blank?(data[:name]) || data[:nickname]) - - cs = User.remote_user_creation(data) - - Repo.insert(cs, on_conflict: :replace_all, conflict_target: :nickname) + data + |> Map.put(:name, blank?(data[:name]) || data[:nickname]) + |> remote_user_creation() + |> Repo.insert(on_conflict: :replace_all, conflict_target: :nickname) + |> set_cache() end def ap_enabled?(%User{local: true}), do: true @@@ -1331,8 -1302,8 +1334,8 @@@ # this is because we have synchronous follow APIs and need to simulate them # with an async handshake def wait_and_refresh(_, %User{local: true} = a, %User{local: true} = b) do - with %User{} = a <- User.get_by_id(a.id), - %User{} = b <- User.get_by_id(b.id) do + with %User{} = a <- User.get_cached_by_id(a.id), + %User{} = b <- User.get_cached_by_id(b.id) do {:ok, a, b} else _e -> @@@ -1342,8 -1313,8 +1345,8 @@@ def wait_and_refresh(timeout, %User{} = a, %User{} = b) do with :ok <- :timer.sleep(timeout), - %User{} = a <- User.get_by_id(a.id), - %User{} = b <- User.get_by_id(b.id) do + %User{} = a <- User.get_cached_by_id(a.id), + %User{} = b <- User.get_cached_by_id(b.id) do {:ok, a, b} else _e -> @@@ -1382,7 -1353,7 +1385,7 @@@ end def tag(nickname, tags) when is_binary(nickname), - do: tag(User.get_by_nickname(nickname), tags) + do: tag(get_by_nickname(nickname), tags) def tag(%User{} = user, tags), do: update_tags(user, Enum.uniq((user.tags || []) ++ normalize_tags(tags))) @@@ -1394,7 -1365,7 +1397,7 @@@ end def untag(nickname, tags) when is_binary(nickname), - do: untag(User.get_by_nickname(nickname), tags) + do: untag(get_by_nickname(nickname), tags) def untag(%User{} = user, tags), do: update_tags(user, (user.tags || []) -- normalize_tags(tags)) diff --combined lib/pleroma/web/activity_pub/activity_pub.ex index a345372e2,604ffae7b..6bf54d1cc --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@@ -168,7 -168,7 +168,7 @@@ defmodule Pleroma.Web.ActivityPub.Activ public = "https://www.w3.org/ns/activitystreams#Public" if activity.data["type"] in ["Create", "Announce", "Delete"] do - object = Object.normalize(activity.data["object"]) + object = Object.normalize(activity) Pleroma.Web.Streamer.stream("user", activity) Pleroma.Web.Streamer.stream("list", activity) @@@ -197,7 -197,7 +197,7 @@@ if !Enum.member?(activity.data["cc"] || [], public) && !Enum.member?( activity.data["to"], - User.get_by_ap_id(activity.data["actor"]).follower_address + User.get_cached_by_ap_id(activity.data["actor"]).follower_address ), do: Pleroma.Web.Streamer.stream("direct", activity) end @@@ -805,7 -805,6 +805,7 @@@ |> restrict_reblogs(opts) |> restrict_pinned(opts) |> restrict_muted_reblogs(opts) + |> Activity.restrict_deactivated_users() end def fetch_activities(recipients, opts \\ %{}) do @@@ -890,7 -889,7 +890,7 @@@ end def make_user_from_ap_id(ap_id) do - if _user = User.get_by_ap_id(ap_id) do + if _user = User.get_cached_by_ap_id(ap_id) do Transmogrifier.upgrade_user_from_ap_id(ap_id) else with {:ok, data} <- fetch_and_prepare_user_from_ap_id(ap_id) do diff --combined lib/pleroma/web/router.ex index f475de639,ff4f08af5..5f7617ece --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@@ -135,6 -135,7 +135,7 @@@ defmodule Pleroma.Web.Router d post("/password_reset", UtilController, :password_reset) get("/emoji", UtilController, :emoji) get("/captcha", UtilController, :captcha) + get("/healthcheck", UtilController, :healthcheck) end scope "/api/pleroma", Pleroma.Web do @@@ -196,7 -197,6 +197,7 @@@ post("/change_password", UtilController, :change_password) post("/delete_account", UtilController, :delete_account) put("/notification_settings", UtilController, :update_notificaton_settings) + post("/disable_account", UtilController, :disable_account) end scope [] do @@@ -395,6 -395,8 +396,8 @@@ get("/accounts/:id", MastodonAPIController, :user) get("/search", MastodonAPIController, :search) + + get("/pleroma/accounts/:id/favourites", MastodonAPIController, :user_favourites) end end diff --combined lib/pleroma/web/twitter_api/controllers/util_controller.ex index 9b0cf2b07,1122e6c5d..6c8c2fe24 --- a/lib/pleroma/web/twitter_api/controllers/util_controller.ex +++ b/lib/pleroma/web/twitter_api/controllers/util_controller.ex @@@ -22,7 -22,7 +22,7 @@@ defmodule Pleroma.Web.TwitterAPI.UtilCo def show_password_reset(conn, %{"token" => token}) do with %{used: false} = token <- Repo.get_by(PasswordResetToken, %{token: token}), - %User{} = user <- User.get_by_id(token.user_id) do + %User{} = user <- User.get_cached_by_id(token.user_id) do render(conn, "password_reset.html", %{ token: token, user: user @@@ -113,13 -113,13 +113,13 @@@ def do_remote_follow(conn, %{ "authorization" => %{"name" => username, "password" => password, "id" => id} }) do - followee = User.get_by_id(id) + followee = User.get_cached_by_id(id) avatar = User.avatar_url(followee) name = followee.nickname with %User{} = user <- User.get_cached_by_nickname(username), true <- Pbkdf2.checkpw(password, user.password_hash), - %User{} = _followed <- User.get_by_id(id), + %User{} = _followed <- User.get_cached_by_id(id), {:ok, follower} <- User.follow(user, followee), {:ok, _activity} <- ActivityPub.follow(follower, followee) do conn @@@ -141,7 -141,7 +141,7 @@@ end def do_remote_follow(%{assigns: %{user: user}} = conn, %{"user" => %{"id" => id}}) do - with %User{} = followee <- User.get_by_id(id), + with %User{} = followee <- User.get_cached_by_id(id), {:ok, follower} <- User.follow(user, followee), {:ok, _activity} <- ActivityPub.follow(follower, followee) do conn @@@ -360,18 -360,25 +360,36 @@@ end end + def disable_account(%{assigns: %{user: user}} = conn, params) do + case CommonAPI.Utils.confirm_current_password(user, params["password"]) do + {:ok, user} -> + User.deactivate_async(user) + json(conn, %{status: "success"}) + + {:error, msg} -> + json(conn, %{error: msg}) + end + end + def captcha(conn, _params) do json(conn, Pleroma.Captcha.new()) end + + def healthcheck(conn, _params) do + info = + if Pleroma.Config.get([:instance, :healthcheck]) do + Pleroma.Healthcheck.system_info() + else + %{} + end + + conn = + if info[:healthy] do + conn + else + Plug.Conn.put_status(conn, :service_unavailable) + end + + json(conn, info) + end end diff --combined lib/pleroma/web/twitter_api/twitter_api.ex index c3f769c00,adeac6f3c..2353a95a8 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@@ -231,19 -231,16 +231,19 @@@ defmodule Pleroma.Web.TwitterAPI.Twitte def get_user(user \\ nil, params) do case params do %{"user_id" => user_id} -> - case target = User.get_cached_by_nickname_or_id(user_id) do + case User.get_cached_by_nickname_or_id(user_id) do nil -> {:error, "No user with such user_id"} - _ -> - {:ok, target} + %User{info: %{deactivated: true}} -> + {:error, "User has been disabled"} + + user -> + {:ok, user} end %{"screen_name" => nickname} -> - case User.get_by_nickname(nickname) do + case User.get_cached_by_nickname(nickname) do nil -> {:error, "No user with such screen_name"} target -> {:ok, target} end diff --combined test/user_test.exs index a5f931853,42d570c50..2966d1f88 --- a/test/user_test.exs +++ b/test/user_test.exs @@@ -8,7 -8,6 +8,7 @@@ defmodule Pleroma.UserTest d alias Pleroma.Object alias Pleroma.Repo alias Pleroma.User + alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.CommonAPI use Pleroma.DataCase @@@ -124,9 -123,9 +124,9 @@@ {:ok, user} = User.follow(user, followed) - user = User.get_by_id(user.id) + user = User.get_cached_by_id(user.id) - followed = User.get_by_ap_id(followed.ap_id) + followed = User.get_cached_by_ap_id(followed.ap_id) assert followed.info.follower_count == 1 assert User.ap_followers(followed) in user.following @@@ -189,7 -188,7 +189,7 @@@ {:ok, user, _activity} = User.unfollow(user, followed) - user = User.get_by_id(user.id) + user = User.get_cached_by_id(user.id) assert user.following == [] end @@@ -199,7 -198,7 +199,7 @@@ {:error, _} = User.unfollow(user, user) - user = User.get_by_id(user.id) + user = User.get_cached_by_id(user.id) assert user.following == [user.ap_id] end @@@ -214,8 -213,8 +214,8 @@@ test "fetches correct profile for nickname beginning with number" do # Use old-style integer ID to try to reproduce the problem user = insert(:user, %{id: 1080}) - userwithnumbers = insert(:user, %{nickname: "#{user.id}garbage"}) - assert userwithnumbers == User.get_cached_by_nickname_or_id(userwithnumbers.nickname) + user_with_numbers = insert(:user, %{nickname: "#{user.id}garbage"}) + assert user_with_numbers == User.get_cached_by_nickname_or_id(user_with_numbers.nickname) end describe "user registration" do @@@ -557,8 -556,8 +557,8 @@@ {:ok, res} = User.get_friends(user) - followed_one = User.get_by_ap_id(followed_one.ap_id) - followed_two = User.get_by_ap_id(followed_two.ap_id) + followed_one = User.get_cached_by_ap_id(followed_one.ap_id) + followed_two = User.get_cached_by_ap_id(followed_two.ap_id) assert Enum.member?(res, followed_one) assert Enum.member?(res, followed_two) refute Enum.member?(res, not_followed) @@@ -569,7 -568,7 +569,7 @@@ test "it sets the info->note_count property" do note = insert(:note) - user = User.get_by_ap_id(note.data["actor"]) + user = User.get_cached_by_ap_id(note.data["actor"]) assert user.info.note_count == 0 @@@ -580,7 -579,7 +580,7 @@@ test "it increases the info->note_count property" do note = insert(:note) - user = User.get_by_ap_id(note.data["actor"]) + user = User.get_cached_by_ap_id(note.data["actor"]) assert user.info.note_count == 0 @@@ -595,7 -594,7 +595,7 @@@ test "it decreases the info->note_count property" do note = insert(:note) - user = User.get_by_ap_id(note.data["actor"]) + user = User.get_cached_by_ap_id(note.data["actor"]) assert user.info.note_count == 0 @@@ -697,7 -696,7 +697,7 @@@ assert User.following?(blocked, blocker) {:ok, blocker} = User.block(blocker, blocked) - blocked = User.get_by_id(blocked.id) + blocked = User.get_cached_by_id(blocked.id) assert User.blocks?(blocker, blocked) @@@ -715,7 -714,7 +715,7 @@@ refute User.following?(blocked, blocker) {:ok, blocker} = User.block(blocker, blocked) - blocked = User.get_by_id(blocked.id) + blocked = User.get_cached_by_id(blocked.id) assert User.blocks?(blocker, blocked) @@@ -733,7 -732,7 +733,7 @@@ assert User.following?(blocked, blocker) {:ok, blocker} = User.block(blocker, blocked) - blocked = User.get_by_id(blocked.id) + blocked = User.get_cached_by_id(blocked.id) assert User.blocks?(blocker, blocked) @@@ -817,71 -816,13 +817,71 @@@ assert addressed in recipients end - test ".deactivate can de-activate then re-activate a user" do - user = insert(:user) - assert false == user.info.deactivated - {:ok, user} = User.deactivate(user) - assert true == user.info.deactivated - {:ok, user} = User.deactivate(user, false) - assert false == user.info.deactivated + describe ".deactivate" do + test "can de-activate then re-activate a user" do + user = insert(:user) + assert false == user.info.deactivated + {:ok, user} = User.deactivate(user) + assert true == user.info.deactivated + {:ok, user} = User.deactivate(user, false) + assert false == user.info.deactivated + end + + test "hide a user from followers " do + user = insert(:user) + user2 = insert(:user) + + {:ok, user} = User.follow(user, user2) + {:ok, _user} = User.deactivate(user) + + info = User.get_cached_user_info(user2) + + assert info.follower_count == 0 + assert {:ok, []} = User.get_followers(user2) + end + + test "hide a user from friends" do + user = insert(:user) + user2 = insert(:user) + + {:ok, user2} = User.follow(user2, user) + assert User.following_count(user2) == 1 + + {:ok, _user} = User.deactivate(user) + + info = User.get_cached_user_info(user2) + + assert info.following_count == 0 + assert User.following_count(user2) == 0 + assert {:ok, []} = User.get_friends(user2) + end + + test "hide a user's statuses from timelines and notifications" do + user = insert(:user) + user2 = insert(:user) + + {:ok, user2} = User.follow(user2, user) + + {:ok, activity} = CommonAPI.post(user, %{"status" => "hey @#{user2.nickname}"}) + + [notification] = Pleroma.Notification.for_user(user2) + assert notification.activity.id == activity.id + + assert [activity] == ActivityPub.fetch_public_activities(%{}) + + assert [activity] == + ActivityPub.fetch_activities([user2.ap_id | user2.following], %{"user" => user2}) + |> ActivityPub.contain_timeline(user2) + + {:ok, _user} = User.deactivate(user) + + assert [] == ActivityPub.fetch_public_activities(%{}) + assert [] == Pleroma.Notification.for_user(user2) + + assert [] == + ActivityPub.fetch_activities([user2.ap_id | user2.following], %{"user" => user2}) + |> ActivityPub.contain_timeline(user2) + end end test ".delete_user_activities deletes all create activities" do @@@ -911,9 -852,9 +911,9 @@@ {:ok, _} = User.delete(user) - followed = User.get_by_id(followed.id) - follower = User.get_by_id(follower.id) - user = User.get_by_id(user.id) + followed = User.get_cached_by_id(followed.id) + follower = User.get_cached_by_id(follower.id) + user = User.get_cached_by_id(user.id) assert user.info.deactivated @@@ -1067,7 -1008,7 +1067,7 @@@ results = User.search("http://mastodon.example.org/users/admin", resolve: true) result = results |> List.first() - user = User.get_by_ap_id("http://mastodon.example.org/users/admin") + user = User.get_cached_by_ap_id("http://mastodon.example.org/users/admin") assert length(results) == 1 assert user == result |> Map.put(:search_rank, nil) |> Map.put(:search_type, nil) diff --combined test/web/twitter_api/util_controller_test.exs index 0288e24d1,56474447b..14a8225f0 --- a/test/web/twitter_api/util_controller_test.exs +++ b/test/web/twitter_api/util_controller_test.exs @@@ -246,21 -246,9 +246,27 @@@ defmodule Pleroma.Web.TwitterAPI.UtilCo end end + test "GET /api/pleroma/healthcheck", %{conn: conn} do + conn = get(conn, "/api/pleroma/healthcheck") + + assert conn.status in [200, 503] + end ++ + describe "POST /api/pleroma/disable_account" do + test "it returns HTTP 200", %{conn: conn} do + user = insert(:user) + + response = + conn + |> assign(:user, user) + |> post("/api/pleroma/disable_account", %{"password" => "test"}) + |> json_response(:ok) + + assert response == %{"status" => "success"} + + user = User.get_cached_by_id(user.id) + + assert user.info.deactivated == true + end + end end