From: Egor Kislitsyn Date: Thu, 11 Apr 2019 08:51:52 +0000 (+0700) Subject: Merge remote-tracking branch 'pleroma/develop' into feature/disable-account X-Git-Url: https://git.squeep.com/?a=commitdiff_plain;h=0f2f7d2cec8297b1b5645643d7584cde561ce628;p=akkoma Merge remote-tracking branch 'pleroma/develop' into feature/disable-account --- 0f2f7d2cec8297b1b5645643d7584cde561ce628 diff --cc config/config.exs index d9ed43dda,3462a37f7..d42b136b7 --- a/config/config.exs +++ b/config/config.exs @@@ -340,11 -364,17 +364,18 @@@ config :pleroma, Pleroma.Web.Federator. initial_timeout: 30, max_retries: 5 - config :pleroma, Pleroma.Jobs, - federator_incoming: [max_jobs: 50], - federator_outgoing: [max_jobs: 50], - mailer: [max_jobs: 10], - user: [max_jobs: 10] + config :pleroma_job_queue, :queues, + federator_incoming: 50, + federator_outgoing: 50, + web_push: 50, + mailer: 10, + transmogrifier: 20, - scheduled_activities: 10 ++ scheduled_activities: 10, ++ user: 10 + + config :pleroma, :fetch_initial_posts, + enabled: false, + pages: 5 config :auto_linker, opts: [ diff --cc lib/pleroma/activity.ex index c466bff7f,ab8861b27..c8c7f0d04 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@@ -41,13 -79,44 +79,47 @@@ defmodule Pleroma.Activity d ) end + def get_by_ap_id_with_object(ap_id) do + Repo.one( + from( + activity in Activity, + where: fragment("(?)->>'id' = ?", activity.data, ^to_string(ap_id)), + left_join: o in Object, + on: + fragment( + "(?->>'id') = COALESCE(?->'object'->>'id', ?->>'object')", + o.data, + activity.data, + activity.data + ), + preload: [object: o] + ) + ) + end + def get_by_id(id) do - Repo.get(Activity, id) + Activity + |> where([a], a.id == ^id) + |> restrict_disabled_users() + |> Repo.one() end + def get_by_id_with_object(id) do + from(activity in Activity, + where: activity.id == ^id, + inner_join: o in Object, + on: + fragment( + "(?->>'id') = COALESCE(?->'object'->>'id', ?->>'object')", + o.data, + activity.data, + activity.data + ), + preload: [object: o] + ) + |> Repo.one() + end + def by_object_ap_id(ap_id) do from( activity in Activity, @@@ -128,13 -246,49 +250,59 @@@ |> Repo.all() end + def increase_replies_count(id) do + Activity + |> where(id: ^id) + |> update([a], + set: [ + data: + fragment( + """ + jsonb_set(?, '{object, repliesCount}', + (coalesce((?->'object'->>'repliesCount')::int, 0) + 1)::varchar::jsonb, true) + """, + a.data, + a.data + ) + ] + ) + |> Repo.update_all([]) + |> case do + {1, [activity]} -> activity + _ -> {:error, "Not found"} + end + end + + def decrease_replies_count(id) do + Activity + |> where(id: ^id) + |> update([a], + set: [ + data: + fragment( + """ + jsonb_set(?, '{object, repliesCount}', + (greatest(0, (?->'object'->>'repliesCount')::int - 1))::varchar::jsonb, true) + """, + a.data, + a.data + ) + ] + ) + |> Repo.update_all([]) + |> case do + {1, [activity]} -> activity + _ -> {:error, "Not found"} + end + end ++ + def restrict_disabled_users(query) do + from(activity in query, + where: + fragment( + "? not in (SELECT ap_id FROM users WHERE info->'disabled' @> 'true')", + activity.actor + ) + ) + end end diff --cc lib/pleroma/notification.ex index 0f9f74b1e,15789907a..7de2d4c18 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@@ -22,36 -25,30 +25,37 @@@ defmodule Pleroma.Notification d timestamps() end - # TODO: Make generic and unify (see activity_pub.ex) - defp restrict_max(query, %{"max_id" => max_id}) do - from(activity in query, where: activity.id < ^max_id) - end - - defp restrict_max(query, _), do: query - - defp restrict_since(query, %{"since_id" => since_id}) do - from(activity in query, where: activity.id > ^since_id) + def changeset(%Notification{} = notification, attrs) do + notification + |> cast(attrs, [:seen]) end - defp restrict_since(query, _), do: query - - def for_user(user, opts \\ %{}) do - from( - n in Notification, - where: n.user_id == ^user.id, - order_by: [desc: n.id], - join: activity in assoc(n, :activity), - preload: [activity: activity], - limit: 20, - where: + 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->'disabled' @> 'true')", ++ a.actor ++ ) ++ ) + |> join(:inner, [n], activity in assoc(n, :activity)) + |> join(:left, [n, a], object in Object, + on: fragment( - "? not in (SELECT ap_id FROM users WHERE info->'disabled' @> 'true')", - activity.actor + "(?->>'id') = COALESCE((? -> 'object'::text) ->> 'id'::text)", + object.data, + a.data ) ) - |> restrict_since(opts) - |> restrict_max(opts) - |> Repo.all() + |> preload([n, a, o], activity: {a, object: o}) + end + + def for_user(user, opts \\ %{}) do + user + |> for_user_query() + |> Pagination.fetch_paginated(opts) end def set_read_up_to(%{id: user_id} = _user, id) do diff --cc lib/pleroma/user.ex index f02051174,6e2269aff..1f2aca235 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@@ -103,13 -103,14 +103,12 @@@ defmodule Pleroma.User d "#{Web.base_url()}/users/#{nickname}" end - def ap_followers(%User{} = user) do - "#{ap_id(user)}/followers" - end + def ap_followers(%User{follower_address: fa}) when is_binary(fa), do: fa + 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, @@@ -894,36 -888,8 +906,9 @@@ }, where: fragment("trim(? || ' ' || coalesce(?, '')) % ?", u.nickname, u.name, ^term) ) + |> restrict_disabled() end - defp boost_search_results(results, nil), do: results - - defp boost_search_results(results, for_user) do - friends_ids = get_friends_ids(for_user) - followers_ids = get_followers_ids(for_user) - - Enum.map( - results, - fn u -> - search_rank_coef = - cond do - u.id in friends_ids -> - 1.2 - - u.id in followers_ids -> - 1.1 - - true -> - 1 - end - - Map.put(u, :search_rank, u.search_rank * search_rank_coef) - end - ) - |> Enum.sort_by(&(-&1.search_rank)) - end - def blocks_import(%User{} = blocker, blocked_identifiers) when is_list(blocked_identifiers) do Enum.map( blocked_identifiers, @@@ -1081,12 -1134,21 +1153,20 @@@ 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) - - update_and_set_cache(cng) + user + |> change() + |> put_embed(:info, info_cng) + |> update_and_set_cache() end + def update_notification_settings(%User{} = user, settings \\ %{}) do + info_changeset = User.Info.update_notification_settings(user.info, settings) + + change(user) + |> put_embed(:info, info_changeset) + |> update_and_set_cache() + end + def delete(%User{} = user) do {:ok, user} = User.deactivate(user) @@@ -1118,26 -1181,6 +1199,26 @@@ {:ok, user} end + def disable_async(user, status \\ true) do - Pleroma.Jobs.enqueue(:user, __MODULE__, [:disable_async, user, status]) ++ PleromaJobQueue.enqueue(:user, __MODULE__, [:disable_async, user, status]) + end + + def disable(%User{} = user, status \\ true) do + with {:ok, user} <- User.deactivate(user, status), + info_cng <- User.Info.set_disabled_status(user.info, status), + {:ok, user} <- + user + |> change() + |> put_embed(:info, info_cng) + |> update_and_set_cache(), + {:ok, friends} <- User.get_friends(user) do + Enum.each(friends, &update_follower_count(&1)) + {:ok, user} + end + end + + def perform(:disable_async, user, status), do: disable(user, status) + def html_filter_policy(%User{info: %{no_rich_text: true}}) do Pleroma.HTML.Scrubber.TwitterText end diff --cc lib/pleroma/user/info.ex index 1ec356ba9,5afa7988c..07825a1c4 --- a/lib/pleroma/user/info.ex +++ b/lib/pleroma/user/info.ex @@@ -36,8 -40,11 +40,12 @@@ defmodule Pleroma.User.Info d field(:hide_follows, :boolean, default: false) field(:pinned_activities, {:array, :string}, default: []) field(:flavour, :string, default: nil) + field(:disabled, :boolean, default: false) + field(:notification_settings, :map, + default: %{"remote" => true, "local" => true, "followers" => true, "follows" => true} + ) + # Found in the wild # ap_id -> Where is this used? # bio -> Where is this used? @@@ -55,14 -62,19 +63,27 @@@ |> validate_required([:deactivated]) end + def update_notification_settings(info, settings) do + notification_settings = + info.notification_settings + |> Map.merge(settings) + |> Map.take(["remote", "local", "followers", "follows"]) + + params = %{notification_settings: notification_settings} + + info + |> cast(params, [:notification_settings]) + |> validate_required([:notification_settings]) + end + + def set_disabled_status(info, disabled) do + params = %{disabled: disabled} + + info + |> cast(params, [:disabled]) + |> validate_required([:disabled]) + end + def add_to_note_count(info, number) do set_note_count(info, info.note_count + number) end diff --cc lib/pleroma/web/activity_pub/activity_pub.ex index aa20990f3,f217e7bac..dd51d63c8 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@@ -703,7 -803,7 +803,8 @@@ defmodule Pleroma.Web.ActivityPub.Activ |> restrict_replies(opts) |> restrict_reblogs(opts) |> restrict_pinned(opts) + |> restrict_muted_reblogs(opts) + |> Activity.restrict_disabled_users() end def fetch_activities(recipients, opts \\ %{}) do diff --cc lib/pleroma/web/admin_api/admin_api_controller.ex index 1b94f0609,70a5b5c5d..fb43d0b01 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@@ -44,16 -66,15 +66,25 @@@ defmodule Pleroma.Web.AdminAPI.AdminAPI |> json(user.nickname) end + def user_show(conn, %{"nickname" => nickname}) do + with %User{} = user <- User.get_by_nickname(nickname) do + conn + |> json(AccountView.render("show.json", %{user: user})) + else + _ -> {:error, :not_found} + end + end + + def user_toggle_disabled(conn, %{"nickname" => nickname}) do + user = User.get_by_nickname(nickname) + + {:ok, updated_user} = User.disable(user, !user.info.disabled) + + conn + |> put_view(AccountView) + |> render("show.json", %{user: updated_user}) + end + def user_toggle_activation(conn, %{"nickname" => nickname}) do user = User.get_by_nickname(nickname) diff --cc lib/pleroma/web/router.ex index 5033b5446,172f337db..dd23d7fd5 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@@ -139,11 -145,14 +145,15 @@@ defmodule Pleroma.Web.Router d scope "/api/pleroma/admin", Pleroma.Web.AdminAPI do pipe_through([:admin_api, :oauth_write]) + post("/user/follow", AdminAPIController, :user_follow) + post("/user/unfollow", AdminAPIController, :user_unfollow) + get("/users", AdminAPIController, :list_users) - get("/users/search", AdminAPIController, :search_users) + get("/users/:nickname", AdminAPIController, :user_show) + delete("/user", AdminAPIController, :user_delete) patch("/users/:nickname/toggle_activation", AdminAPIController, :user_toggle_activation) + patch("/users/:nickname/toggle_disabled", AdminAPIController, :user_toggle_disabled) post("/user", AdminAPIController, :user_create) put("/users/tag", AdminAPIController, :tag_users) delete("/users/tag", AdminAPIController, :untag_users) @@@ -184,7 -195,7 +196,8 @@@ 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