From 10ff01acd95d42314b4eb923e5b7a7191356b73e Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Wed, 16 Oct 2019 21:59:21 +0300 Subject: [PATCH 01/28] [#1304] Moved all non-mutes / non-blocks fields from User.Info to User. WIP. --- CHANGELOG.md | 1 + lib/mix/tasks/pleroma/user.ex | 18 +- lib/pleroma/daemons/digest_email_daemon.ex | 2 +- lib/pleroma/emails/user_email.ex | 2 +- lib/pleroma/formatter.ex | 2 +- lib/pleroma/notification.ex | 10 +- .../plugs/admin_secret_authentication_plug.ex | 2 +- lib/pleroma/plugs/oauth_plug.ex | 2 +- lib/pleroma/plugs/user_enabled_plug.ex | 2 +- lib/pleroma/plugs/user_is_admin_plug.ex | 2 +- lib/pleroma/stats.ex | 7 +- lib/pleroma/user.ex | 554 ++++++++++++++++----- lib/pleroma/user/info.ex | 371 -------------- lib/pleroma/user/query.ex | 21 +- lib/pleroma/web/activity_pub/activity_pub.ex | 20 +- .../web/activity_pub/activity_pub_controller.ex | 6 +- .../web/activity_pub/mrf/anti_link_spam_policy.ex | 2 +- lib/pleroma/web/activity_pub/publisher.ex | 8 +- lib/pleroma/web/activity_pub/transmogrifier.ex | 12 +- lib/pleroma/web/activity_pub/views/user_view.ex | 28 +- lib/pleroma/web/admin_api/admin_api_controller.ex | 22 +- lib/pleroma/web/admin_api/views/account_view.ex | 5 +- lib/pleroma/web/common_api/common_api.ex | 12 +- lib/pleroma/web/masto_fe_controller.ex | 2 +- .../mastodon_api/controllers/account_controller.ex | 64 ++- lib/pleroma/web/mastodon_api/views/account_view.ex | 68 ++- lib/pleroma/web/mastodon_api/views/status_view.ex | 2 +- lib/pleroma/web/oauth/oauth_controller.ex | 4 +- lib/pleroma/web/ostatus/handlers/follow_handler.ex | 2 +- lib/pleroma/web/ostatus/ostatus.ex | 9 +- .../pleroma_api/controllers/account_controller.ex | 16 +- .../pleroma_api/controllers/mascot_controller.ex | 4 +- lib/pleroma/web/salmon/salmon.ex | 8 +- lib/pleroma/web/streamer/worker.ex | 2 +- .../web/twitter_api/twitter_api_controller.ex | 9 +- lib/pleroma/web/views/masto_fe_view.ex | 8 +- lib/pleroma/web/websub/websub.ex | 4 +- ...5158_add_following_address_from_source_data.exs | 6 +- ...711042024_copy_muted_to_muted_notifications.exs | 1 - ...91009154608_copy_users_info_fields_to_users.exs | 54 ++ test/daemons/digest_email_daemon_test.exs | 2 +- test/emails/user_email_test.exs | 2 +- test/formatter_test.exs | 6 +- test/moderation_log_test.exs | 4 +- test/notification_test.exs | 8 +- .../admin_secret_authentication_plug_test.exs | 2 +- test/plugs/user_enabled_plug_test.exs | 2 +- test/plugs/user_is_admin_plug_test.exs | 2 +- test/signature_test.exs | 4 +- test/tasks/count_statuses_test.exs | 16 +- test/tasks/database_test.exs | 11 +- test/tasks/user_test.exs | 38 +- test/user_info_test.exs | 24 - test/user_test.exs | 160 +++--- .../activity_pub/activity_pub_controller_test.exs | 12 +- test/web/activity_pub/activity_pub_test.exs | 24 +- .../mrf/anti_link_spam_policy_test.exs | 22 +- test/web/activity_pub/publisher_test.exs | 50 +- .../transmogrifier/follow_handling_test.exs | 2 +- test/web/activity_pub/transmogrifier_test.exs | 36 +- test/web/activity_pub/utils_test.exs | 4 +- test/web/activity_pub/views/user_view_test.exs | 20 +- test/web/admin_api/admin_api_controller_test.exs | 130 ++--- test/web/admin_api/search_test.exs | 12 +- test/web/admin_api/views/report_view_test.exs | 2 + test/web/common_api/common_api_test.exs | 12 +- test/web/federator_test.exs | 10 +- test/web/masto_fe_controller_test.exs | 2 +- .../account_controller/update_credentials_test.exs | 2 +- .../controllers/account_controller_test.exs | 16 +- .../controllers/conversation_controller_test.exs | 12 +- .../controllers/follow_request_controller_test.exs | 6 +- .../controllers/instance_controller_test.exs | 9 +- .../controllers/status_controller_test.exs | 4 +- test/web/mastodon_api/mastodon_api_test.exs | 6 +- test/web/mastodon_api/views/account_view_test.exs | 57 +-- test/web/node_info_test.exs | 4 +- test/web/oauth/oauth_controller_test.exs | 8 +- test/web/ostatus/ostatus_controller_test.exs | 5 +- test/web/ostatus/ostatus_test.exs | 62 ++- .../controllers/account_controller_test.exs | 21 +- .../controllers/emoji_api_controller_test.exs | 12 +- test/web/salmon/salmon_test.exs | 4 +- test/web/streamer/streamer_test.exs | 2 +- test/web/twitter_api/password_controller_test.exs | 4 +- test/web/twitter_api/twitter_api_test.exs | 2 +- test/web/twitter_api/util_controller_test.exs | 8 +- test/web/websub/websub_test.exs | 2 +- 88 files changed, 1069 insertions(+), 1170 deletions(-) create mode 100644 priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs delete mode 100644 test/user_info_test.exs diff --git a/CHANGELOG.md b/CHANGELOG.md index bd06ec866..4ce9fa4b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - MRF (Simple Policy): Also use `:accept`/`:reject` on the actors rather than only their activities - OStatus: Extract RSS functionality - Mastodon API: Add `pleroma.direct_conversation_id` to the status endpoint (`GET /api/v1/statuses/:id`) +- Deprecated `User.Info` embedded schema (fields moved to `User`) ### Fixed - Mastodon API: Fix private and direct statuses not being filtered out from the public timeline for an authenticated user (`GET /api/v1/timelines/public`) diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex index 134b5bccc..265c5f1a7 100644 --- a/lib/mix/tasks/pleroma/user.ex +++ b/lib/mix/tasks/pleroma/user.ex @@ -109,10 +109,10 @@ defmodule Mix.Tasks.Pleroma.User do start_pleroma() with %User{} = user <- User.get_cached_by_nickname(nickname) do - {:ok, user} = User.deactivate(user, !user.info.deactivated) + {:ok, user} = User.deactivate(user, !user.deactivated) shell_info( - "Activation status of #{nickname}: #{if(user.info.deactivated, do: "de", else: "")}activated" + "Activation status of #{nickname}: #{if(user.deactivated, do: "de", else: "")}activated" ) else _ -> @@ -340,7 +340,7 @@ defmodule Mix.Tasks.Pleroma.User do with %User{} = user <- User.get_cached_by_nickname(nickname) do {:ok, user} = User.toggle_confirmation(user) - message = if user.info.confirmation_pending, do: "needs", else: "doesn't need" + message = if user.confirmation_pending, do: "needs", else: "doesn't need" shell_info("#{nickname} #{message} confirmation.") else @@ -364,23 +364,23 @@ defmodule Mix.Tasks.Pleroma.User do end defp set_moderator(user, value) do - {:ok, user} = User.update_info(user, &User.Info.admin_api_update(&1, %{is_moderator: value})) + {:ok, user} = User.update_and_set_cache(user, %{is_moderator: value}) - shell_info("Moderator status of #{user.nickname}: #{user.info.is_moderator}") + shell_info("Moderator status of #{user.nickname}: #{user.is_moderator}") user end defp set_admin(user, value) do - {:ok, user} = User.update_info(user, &User.Info.admin_api_update(&1, %{is_admin: value})) + {:ok, user} = User.update_and_set_cache(user, %{is_admin: value}) - shell_info("Admin status of #{user.nickname}: #{user.info.is_admin}") + shell_info("Admin status of #{user.nickname}: #{user.is_admin}") user end defp set_locked(user, value) do - {:ok, user} = User.update_info(user, &User.Info.user_upgrade(&1, %{locked: value})) + {:ok, user} = User.update_and_set_cache(user, %{locked: value}) - shell_info("Locked status of #{user.nickname}: #{user.info.locked}") + shell_info("Locked status of #{user.nickname}: #{user.locked}") user end end diff --git a/lib/pleroma/daemons/digest_email_daemon.ex b/lib/pleroma/daemons/digest_email_daemon.ex index 462ad2c55..b4c8eaad9 100644 --- a/lib/pleroma/daemons/digest_email_daemon.ex +++ b/lib/pleroma/daemons/digest_email_daemon.ex @@ -17,7 +17,7 @@ defmodule Pleroma.Daemons.DigestEmailDaemon do now = NaiveDateTime.truncate(NaiveDateTime.utc_now(), :second) from(u in inactive_users_query, - where: fragment(~s(? #> '{"email_notifications","digest"}' @> 'true'), u.info), + where: fragment(~s(? ->'digest' @> 'true'), u.email_notifications), where: u.last_digest_emailed_at < datetime_add(^now, ^negative_interval, "day"), select: u ) diff --git a/lib/pleroma/emails/user_email.ex b/lib/pleroma/emails/user_email.ex index 40b67ff56..a10f88f93 100644 --- a/lib/pleroma/emails/user_email.ex +++ b/lib/pleroma/emails/user_email.ex @@ -72,7 +72,7 @@ defmodule Pleroma.Emails.UserEmail do Endpoint, :confirm_email, user.id, - to_string(user.info.confirmation_token) + to_string(user.confirmation_token) ) html_body = """ diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex index 931b9af2b..19b9af46c 100644 --- a/lib/pleroma/formatter.ex +++ b/lib/pleroma/formatter.ex @@ -127,7 +127,7 @@ defmodule Pleroma.Formatter do end end - defp get_ap_id(%User{info: %{source_data: %{"url" => url}}}) when is_binary(url), do: url + defp get_ap_id(%User{source_data: %{"url" => url}}) when is_binary(url), do: url defp get_ap_id(%User{ap_id: ap_id}), do: ap_id defp get_nickname_text(nickname, %{mentions_format: :full}), do: User.full_nickname(nickname) diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index d94ae5971..19d22370f 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -40,7 +40,7 @@ defmodule Pleroma.Notification do |> where( [n, a], fragment( - "? not in (SELECT ap_id FROM users WHERE info->'deactivated' @> 'true')", + "? not in (SELECT ap_id FROM users WHERE deactivated = 'true')", a.actor ) ) @@ -259,7 +259,7 @@ defmodule Pleroma.Notification do def skip?( :followers, activity, - %{info: %{notification_settings: %{"followers" => false}}} = user + %{notification_settings: %{"followers" => false}} = user ) do actor = activity.data["actor"] follower = User.get_cached_by_ap_id(actor) @@ -269,14 +269,14 @@ defmodule Pleroma.Notification do def skip?( :non_followers, activity, - %{info: %{notification_settings: %{"non_followers" => false}}} = user + %{notification_settings: %{"non_followers" => false}} = user ) do actor = activity.data["actor"] follower = User.get_cached_by_ap_id(actor) !User.following?(follower, user) end - def skip?(:follows, activity, %{info: %{notification_settings: %{"follows" => false}}} = user) do + def skip?(:follows, activity, %{notification_settings: %{"follows" => false}} = user) do actor = activity.data["actor"] followed = User.get_cached_by_ap_id(actor) User.following?(user, followed) @@ -285,7 +285,7 @@ defmodule Pleroma.Notification do def skip?( :non_follows, activity, - %{info: %{notification_settings: %{"non_follows" => false}}} = user + %{notification_settings: %{"non_follows" => false}} = user ) do actor = activity.data["actor"] followed = User.get_cached_by_ap_id(actor) diff --git a/lib/pleroma/plugs/admin_secret_authentication_plug.ex b/lib/pleroma/plugs/admin_secret_authentication_plug.ex index 5baf8a691..fdadd476e 100644 --- a/lib/pleroma/plugs/admin_secret_authentication_plug.ex +++ b/lib/pleroma/plugs/admin_secret_authentication_plug.ex @@ -19,7 +19,7 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlug do def call(%{params: %{"admin_token" => admin_token}} = conn, _) do if secret_token() && admin_token == secret_token() do conn - |> assign(:user, %User{info: %{is_admin: true}}) + |> assign(:user, %User{is_admin: true}) else conn end diff --git a/lib/pleroma/plugs/oauth_plug.ex b/lib/pleroma/plugs/oauth_plug.ex index 86bc4aa3a..fd004fcd2 100644 --- a/lib/pleroma/plugs/oauth_plug.ex +++ b/lib/pleroma/plugs/oauth_plug.ex @@ -71,7 +71,7 @@ defmodule Pleroma.Plugs.OAuthPlug do ) # credo:disable-for-next-line Credo.Check.Readability.MaxLineLength - with %Token{user: %{info: %{deactivated: false} = _} = user} = token_record <- Repo.one(query) do + with %Token{user: %{deactivated: false} = user} = token_record <- Repo.one(query) do {:ok, user, token_record} end end diff --git a/lib/pleroma/plugs/user_enabled_plug.ex b/lib/pleroma/plugs/user_enabled_plug.ex index da892c28b..fbb4bf115 100644 --- a/lib/pleroma/plugs/user_enabled_plug.ex +++ b/lib/pleroma/plugs/user_enabled_plug.ex @@ -10,7 +10,7 @@ defmodule Pleroma.Plugs.UserEnabledPlug do options end - def call(%{assigns: %{user: %User{info: %{deactivated: true}}}} = conn, _) do + def call(%{assigns: %{user: %User{deactivated: true}}} = conn, _) do conn |> assign(:user, nil) end diff --git a/lib/pleroma/plugs/user_is_admin_plug.ex b/lib/pleroma/plugs/user_is_admin_plug.ex index 4c4b3d610..ee808f31f 100644 --- a/lib/pleroma/plugs/user_is_admin_plug.ex +++ b/lib/pleroma/plugs/user_is_admin_plug.ex @@ -11,7 +11,7 @@ defmodule Pleroma.Plugs.UserIsAdminPlug do options end - def call(%{assigns: %{user: %User{info: %{is_admin: true}}}} = conn, _) do + def call(%{assigns: %{user: %User{is_admin: true}}} = conn, _) do conn end diff --git a/lib/pleroma/stats.ex b/lib/pleroma/stats.ex index df80fbaa4..8154a09b7 100644 --- a/lib/pleroma/stats.ex +++ b/lib/pleroma/stats.ex @@ -68,12 +68,7 @@ defmodule Pleroma.Stats do domain_count = Enum.count(peers) - status_query = - from(u in User.Query.build(%{local: true}), - select: fragment("sum((?->>'note_count')::int)", u.info) - ) - - status_count = Repo.one(status_query) + status_count = Repo.aggregate(User.Query.build(%{local: true}), :sum, :note_count) user_count = Repo.aggregate(User.Query.build(%{local: true, active: true}), :count, :id) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 2cfb13a8c..165342011 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -63,6 +63,62 @@ defmodule Pleroma.User do field(:tags, {:array, :string}, default: []) field(:last_refreshed_at, :naive_datetime_usec) field(:last_digest_emailed_at, :naive_datetime) + + field(:banner, :map, default: %{}) + field(:background, :map, default: %{}) + field(:source_data, :map, default: %{}) + field(:note_count, :integer, default: 0) + field(:follower_count, :integer, default: 0) + # Should be filled in only for remote users + field(:following_count, :integer, default: nil) + field(:locked, :boolean, default: false) + field(:confirmation_pending, :boolean, default: false) + field(:password_reset_pending, :boolean, default: false) + field(:confirmation_token, :string, default: nil) + field(:default_scope, :string, default: "public") + field(:blocks, {:array, :string}, default: []) + field(:domain_blocks, {:array, :string}, default: []) + field(:mutes, {:array, :string}, default: []) + field(:muted_reblogs, {:array, :string}, default: []) + field(:muted_notifications, {:array, :string}, default: []) + field(:subscribers, {:array, :string}, default: []) + field(:deactivated, :boolean, default: false) + field(:no_rich_text, :boolean, default: false) + field(:ap_enabled, :boolean, default: false) + field(:is_moderator, :boolean, default: false) + field(:is_admin, :boolean, default: false) + field(:show_role, :boolean, default: true) + field(:settings, :map, default: nil) + field(:magic_key, :string, default: nil) + field(:uri, :string, default: nil) + field(:topic, :string, default: nil) + field(:hub, :string, default: nil) + field(:salmon, :string, default: nil) + field(:hide_followers_count, :boolean, default: false) + field(:hide_follows_count, :boolean, default: false) + field(:hide_followers, :boolean, default: false) + field(:hide_follows, :boolean, default: false) + field(:hide_favorites, :boolean, default: true) + field(:unread_conversation_count, :integer, default: 0) + field(:pinned_activities, {:array, :string}, default: []) + field(:email_notifications, :map, default: %{"digest" => false}) + field(:mascot, :map, default: nil) + field(:emoji, {:array, :map}, default: []) + field(:pleroma_settings_store, :map, default: %{}) + field(:fields, {:array, :map}, default: nil) + field(:raw_fields, {:array, :map}, default: []) + field(:discoverable, :boolean, default: false) + field(:skip_thread_containment, :boolean, default: false) + + field(:notification_settings, :map, + default: %{ + "followers" => true, + "follows" => true, + "non_follows" => true, + "non_followers" => true + } + ) + has_many(:notifications, Notification) has_many(:registrations, Registration) has_many(:deliveries, Delivery) @@ -71,7 +127,7 @@ defmodule Pleroma.User do timestamps() end - def auth_active?(%User{info: %User.Info{confirmation_pending: true}}), + def auth_active?(%User{confirmation_pending: true}), do: !Pleroma.Config.get([:instance, :account_activation_required]) def auth_active?(%User{}), do: true @@ -86,8 +142,8 @@ defmodule Pleroma.User do def visible_for?(_, _), do: false - def superuser?(%User{local: true, info: %User.Info{is_admin: true}}), do: true - def superuser?(%User{local: true, info: %User.Info{is_moderator: true}}), do: true + def superuser?(%User{local: true, is_admin: true}), do: true + def superuser?(%User{local: true, is_moderator: true}), do: true def superuser?(_), do: false def avatar_url(user, options \\ []) do @@ -98,13 +154,13 @@ defmodule Pleroma.User do end def banner_url(user, options \\ []) do - case user.info.banner do + case user.banner do %{"url" => [%{"href" => href} | _]} -> href _ -> !options[:no_default] && "#{Web.base_url()}/images/banner.png" end end - def profile_url(%User{info: %{source_data: %{"url" => url}}}), do: url + def profile_url(%User{source_data: %{"url" => url}}), do: url def profile_url(%User{ap_id: ap_id}), do: ap_id def profile_url(_), do: nil @@ -119,15 +175,15 @@ defmodule Pleroma.User do def user_info(%User{} = user, args \\ %{}) do following_count = - Map.get(args, :following_count, user.info.following_count || following_count(user)) + Map.get(args, :following_count, user.following_count || following_count(user)) - follower_count = Map.get(args, :follower_count, user.info.follower_count) + follower_count = Map.get(args, :follower_count, user.follower_count) %{ - note_count: user.info.note_count, - locked: user.info.locked, - confirmation_pending: user.info.confirmation_pending, - default_scope: user.info.default_scope + note_count: user.note_count, + locked: user.locked, + confirmation_pending: user.confirmation_pending, + default_scope: user.default_scope } |> Map.put(:following_count, following_count) |> Map.put(:follower_count, follower_count) @@ -157,9 +213,7 @@ defmodule Pleroma.User do @spec restrict_deactivated(Ecto.Query.t()) :: Ecto.Query.t() def restrict_deactivated(query) do - from(u in query, - where: not fragment("? \\? 'deactivated' AND ?->'deactivated' @> 'true'", u.info, u.info) - ) + from(u in query, where: u.deactivated != ^true) end def following_count(%User{following: []}), do: 0 @@ -170,6 +224,64 @@ defmodule Pleroma.User do |> Repo.aggregate(:count, :id) end + @info_fields [ + :banner, + :background, + :source_data, + :note_count, + :follower_count, + :following_count, + :locked, + :confirmation_pending, + :password_reset_pending, + :confirmation_token, + :default_scope, + :blocks, + :domain_blocks, + :mutes, + :muted_reblogs, + :muted_notifications, + :subscribers, + :deactivated, + :no_rich_text, + :ap_enabled, + :is_moderator, + :is_admin, + :show_role, + :settings, + :magic_key, + :uri, + :topic, + :hub, + :salmon, + :hide_followers_count, + :hide_follows_count, + :hide_followers, + :hide_follows, + :hide_favorites, + :unread_conversation_count, + :pinned_activities, + :email_notifications, + :mascot, + :emoji, + :pleroma_settings_store, + :fields, + :raw_fields, + :discoverable, + :skip_thread_containment, + :notification_settings + ] + + def info_fields, do: @info_fields + + defp truncate_fields_param(params) do + if Map.has_key?(params, :fields) do + Map.put(params, :fields, Enum.map(params[:fields], &truncate_field/1)) + else + params + end + end + defp truncate_if_exists(params, key, max_length) do if Map.has_key?(params, key) and is_binary(params[key]) do {value, _chopped} = String.split_at(params[key], max_length) @@ -188,18 +300,20 @@ defmodule Pleroma.User do |> Map.put(:info, params[:info] || %{}) |> truncate_if_exists(:name, name_limit) |> truncate_if_exists(:bio, bio_limit) + |> truncate_fields_param() changeset = %User{local: false} - |> cast(params, [:bio, :name, :ap_id, :nickname, :avatar]) + |> cast(params, [:bio, :name, :ap_id, :nickname, :avatar] ++ @info_fields) |> validate_required([:name, :ap_id]) |> unique_constraint(:nickname) |> validate_format(:nickname, @email_regex) |> validate_length(:bio, max: bio_limit) |> validate_length(:name, max: name_limit) - |> change_info(&User.Info.remote_user_creation(&1, params[:info])) + |> validate_fields(true) + |> change_info(& &1) - case params[:info][:source_data] do + case params[:source_data] do %{"followers" => followers, "following" => following} -> changeset |> put_change(:follower_address, followers) @@ -216,11 +330,12 @@ defmodule Pleroma.User do name_limit = Pleroma.Config.get([:instance, :user_name_length], 100) struct - |> cast(params, [:bio, :name, :avatar, :following]) + |> cast(params, [:bio, :name, :avatar, :following] ++ @info_fields) |> unique_constraint(:nickname) |> validate_format(:nickname, local_nickname_regex()) |> validate_length(:bio, max: bio_limit) |> validate_length(:name, min: 1, max: name_limit) + |> validate_fields(false) end def upgrade_changeset(struct, params \\ %{}, remote? \\ false) do @@ -229,20 +344,26 @@ defmodule Pleroma.User do params = Map.put(params, :last_refreshed_at, NaiveDateTime.utc_now()) + params = if remote?, do: truncate_fields_param(params), else: params + struct - |> cast(params, [ - :bio, - :name, - :follower_address, - :following_address, - :avatar, - :last_refreshed_at - ]) + |> cast( + params, + [ + :bio, + :name, + :follower_address, + :following_address, + :avatar, + :last_refreshed_at + ] ++ @info_fields + ) |> unique_constraint(:nickname) |> validate_format(:nickname, local_nickname_regex()) |> validate_length(:bio, max: bio_limit) |> validate_length(:name, max: name_limit) - |> change_info(&User.Info.user_upgrade(&1, params[:info], remote?)) + |> validate_fields(remote?) + |> change_info(& &1) end def password_update_changeset(struct, params) do @@ -250,8 +371,8 @@ defmodule Pleroma.User do |> cast(params, [:password, :password_confirmation]) |> validate_required([:password, :password_confirmation]) |> validate_confirmation(:password) - |> put_password_hash - |> put_embed(:info, User.Info.set_password_reset_pending(struct.info, false)) + |> put_password_hash() + |> put_change(:password_reset_pending, false) end @spec reset_password(User.t(), map) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()} @@ -268,19 +389,19 @@ defmodule Pleroma.User do end end + def update_password_reset_pending(user, value) do + user + |> change() + |> put_change(:password_reset_pending, value) + |> update_and_set_cache() + end + def force_password_reset_async(user) do BackgroundWorker.enqueue("force_password_reset", %{"user_id" => user.id}) end @spec force_password_reset(User.t()) :: {:ok, User.t()} | {:error, Ecto.Changeset.t()} - def force_password_reset(user) do - info_cng = User.Info.set_password_reset_pending(user.info, true) - - user - |> change() - |> put_embed(:info, info_cng) - |> update_and_set_cache() - end + def force_password_reset(user), do: update_password_reset_pending(user, true) def register_changeset(struct, params \\ %{}, opts \\ []) do bio_limit = Pleroma.Config.get([:instance, :user_bio_length], 5000) @@ -294,6 +415,7 @@ defmodule Pleroma.User do end struct + |> confirmation_changeset(need_confirmation: need_confirmation?) |> cast(params, [:bio, :email, :name, :nickname, :password, :password_confirmation]) |> validate_required([:name, :nickname, :password, :password_confirmation]) |> validate_confirmation(:password) @@ -304,7 +426,7 @@ defmodule Pleroma.User do |> validate_format(:email, @email_regex) |> validate_length(:bio, max: bio_limit) |> validate_length(:name, min: 1, max: name_limit) - |> change_info(&User.Info.confirmation_changeset(&1, need_confirmation: need_confirmation?)) + |> change_info(& &1) |> maybe_validate_required_email(opts[:external]) |> put_password_hash |> put_ap_id() @@ -355,7 +477,7 @@ defmodule Pleroma.User do end def try_send_confirmation_email(%User{} = user) do - if user.info.confirmation_pending && + if user.confirmation_pending && Pleroma.Config.get([:instance, :account_activation_required]) do user |> Pleroma.Emails.UserEmail.account_confirmation_email() @@ -378,7 +500,7 @@ defmodule Pleroma.User do def needs_update?(_), do: true @spec maybe_direct_follow(User.t(), User.t()) :: {:ok, User.t()} | {:error, String.t()} - def maybe_direct_follow(%User{} = follower, %User{local: true, info: %{locked: true}}) do + def maybe_direct_follow(%User{} = follower, %User{local: true, locked: true}) do {:ok, follower} end @@ -425,13 +547,13 @@ defmodule Pleroma.User do set_cache(follower) end - def follow(%User{} = follower, %User{info: info} = followed) do + def follow(%User{} = follower, %User{} = followed) do deny_follow_blocked = Pleroma.Config.get([:user, :deny_follow_blocked]) ap_followers = followed.follower_address cond do - info.deactivated -> - {:error, "Could not follow user: You are deactivated."} + followed.deactivated -> + {:error, "Could not follow user: #{followed.nickname} is deactivated."} deny_follow_blocked and blocks?(followed, follower) -> {:error, "Could not follow user: #{followed.nickname} blocked you."} @@ -489,7 +611,7 @@ defmodule Pleroma.User do end def locked?(%User{} = user) do - user.info.locked || false + user.locked || false end def get_by_id(id) do @@ -532,6 +654,12 @@ defmodule Pleroma.User do {:ok, user} end + def update_and_set_cache(struct, params) do + struct + |> update_changeset(params) + |> update_and_set_cache() + end + def update_and_set_cache(changeset) do with {:ok, user} <- Repo.update(changeset, stale_error_field: :id) do set_cache(user) @@ -721,16 +849,7 @@ defmodule Pleroma.User do def increase_note_count(%User{} = user) do User |> where(id: ^user.id) - |> update([u], - set: [ - info: - fragment( - "jsonb_set(?, '{note_count}', ((?->>'note_count')::int + 1)::varchar::jsonb, true)", - u.info, - u.info - ) - ] - ) + |> update([u], inc: [note_count: 1]) |> select([u], u) |> Repo.update_all([]) |> case do @@ -744,12 +863,7 @@ defmodule Pleroma.User do |> where(id: ^user.id) |> update([u], set: [ - info: - fragment( - "jsonb_set(?, '{note_count}', (greatest(0, (?->>'note_count')::int - 1))::varchar::jsonb, true)", - u.info, - u.info - ) + note_count: fragment("greatest(0, note_count - 1)") ] ) |> select([u], u) @@ -760,29 +874,17 @@ defmodule Pleroma.User do end end - def update_note_count(%User{} = user) do + def update_note_count(%User{} = user, note_count \\ nil) do note_count = - from( - a in Object, - where: fragment("?->>'actor' = ? and ?->>'type' = 'Note'", a.data, ^user.ap_id, a.data), - select: count(a.id) - ) - |> Repo.one() + note_count || + from( + a in Object, + where: fragment("?->>'actor' = ? and ?->>'type' = 'Note'", a.data, ^user.ap_id, a.data), + select: count(a.id) + ) + |> Repo.one() - update_info(user, &User.Info.set_note_count(&1, note_count)) - end - - def update_mascot(user, url) do - info_changeset = - User.Info.mascot_update( - user.info, - url - ) - - user - |> change() - |> put_embed(:info, info_changeset) - |> update_and_set_cache() + update_and_set_cache(user, %{note_count: note_count}) end @spec maybe_fetch_follow_information(User.t()) :: User.t() @@ -799,10 +901,24 @@ defmodule Pleroma.User do def fetch_follow_information(user) do with {:ok, info} <- ActivityPub.fetch_follow_information_for_user(user) do - update_info(user, &User.Info.follow_information_update(&1, info)) + user + |> follow_information_changeset(info) + |> update_and_set_cache() end end + defp follow_information_changeset(user, params) do + user + |> cast(params, [ + :hide_followers, + :hide_follows, + :follower_count, + :following_count, + :hide_followers_count, + :hide_follows_count + ]) + end + def update_follower_count(%User{} = user) do if user.local or !Pleroma.Config.get([:instance, :external_user_synchronization]) do follower_count_query = @@ -813,14 +929,7 @@ defmodule Pleroma.User do |> where(id: ^user.id) |> join(:inner, [u], s in subquery(follower_count_query)) |> update([u, s], - set: [ - info: - fragment( - "jsonb_set(?, '{follower_count}', ?::varchar::jsonb, true)", - u.info, - s.count - ) - ] + set: [follower_count: s.count] ) |> select([u], u) |> Repo.update_all([]) @@ -850,14 +959,7 @@ defmodule Pleroma.User do User |> join(:inner, [u], p in subquery(unread_query)) |> update([u, p], - set: [ - info: - fragment( - "jsonb_set(?, '{unread_conversation_count}', ?::varchar::jsonb, true)", - u.info, - p.count - ) - ] + set: [unread_conversation_count: p.count] ) |> where([u], u.id == ^user.id) |> select([u], u) @@ -878,14 +980,7 @@ defmodule Pleroma.User do User |> join(:inner, [u], p in subquery(unread_query)) |> update([u, p], - set: [ - info: - fragment( - "jsonb_set(?, '{unread_conversation_count}', (coalesce((?->>'unread_conversation_count')::int, 0) + 1)::varchar::jsonb, true)", - u.info, - u.info - ) - ] + inc: [unread_conversation_count: 1] ) |> where([u], u.id == ^user.id) |> where([u, p], p.count == 0) @@ -942,14 +1037,14 @@ defmodule Pleroma.User do if blocks?(subscribed, subscriber) and deny_follow_blocked do {:error, "Could not subscribe: #{subscribed.nickname} is blocking you"} else - update_info(subscribed, &User.Info.add_to_subscribers(&1, subscriber.ap_id)) + User.add_to_subscribers(subscribed, subscriber.ap_id) end end end def unsubscribe(unsubscriber, %{ap_id: ap_id}) do with %User{} = user <- get_cached_by_ap_id(ap_id) do - update_info(user, &User.Info.remove_from_subscribers(&1, unsubscriber.ap_id)) + User.remove_from_subscribers(user, unsubscriber.ap_id) end end @@ -1025,7 +1120,7 @@ defmodule Pleroma.User do def subscribed_to?(user, %{ap_id: ap_id}) do with %User{} = target <- get_cached_by_ap_id(ap_id) do - Enum.member?(target.info.subscribers, user.ap_id) + Enum.member?(target.subscribers, user.ap_id) end end @@ -1043,7 +1138,7 @@ defmodule Pleroma.User do @spec subscribers(User.t()) :: [User.t()] def subscribers(user) do - User.Query.build(%{ap_id: user.info.subscribers, deactivated: false}) + User.Query.build(%{ap_id: user.subscribers, deactivated: false}) |> Repo.all() end @@ -1060,7 +1155,7 @@ defmodule Pleroma.User do end def deactivate(%User{} = user, status \\ true) do - with {:ok, user} <- update_info(user, &User.Info.set_activation_status(&1, status)) do + with {:ok, user} <- set_activation_status(user, status) do Enum.each(get_followers(user), &invalidate_cache/1) Enum.each(get_friends(user), &update_follower_count/1) @@ -1068,8 +1163,23 @@ defmodule Pleroma.User do end end - def update_notification_settings(%User{} = user, settings \\ %{}) do - update_info(user, &User.Info.update_notification_settings(&1, settings)) + def update_notification_settings(%User{} = user, settings) do + settings = + settings + |> Enum.map(fn {k, v} -> {k, v in [true, "true", "True", "1"]} end) + |> Map.new() + + notification_settings = + user.notification_settings + |> Map.merge(settings) + |> Map.take(["followers", "follows", "non_follows", "non_followers"]) + + params = %{notification_settings: notification_settings} + + user + |> cast(params, [:notification_settings]) + |> validate_required([:notification_settings]) + |> update_and_set_cache() end def delete(%User{} = user) do @@ -1107,7 +1217,7 @@ defmodule Pleroma.User do pages = Pleroma.Config.get!([:fetch_initial_posts, :pages]) # Insert all the posts in reverse order, so they're in the right order on the timeline - user.info.source_data["outbox"] + user.source_data["outbox"] |> Utils.fetch_ordered_collection(pages) |> Enum.reverse() |> Enum.each(&Pleroma.Web.Federator.incoming_ap_doc/1) @@ -1228,7 +1338,7 @@ defmodule Pleroma.User do defp delete_activity(_activity), do: "Doing nothing" - def html_filter_policy(%User{info: %{no_rich_text: true}}) do + def html_filter_policy(%User{no_rich_text: true}) do Pleroma.HTML.Scrubber.TwitterText end @@ -1288,9 +1398,7 @@ defmodule Pleroma.User do end # AP style - def public_key_from_info(%{ - source_data: %{"publicKey" => %{"publicKeyPem" => public_key_pem}} - }) do + def public_key(%{source_data: %{"publicKey" => %{"publicKeyPem" => public_key_pem}}}) do key = public_key_pem |> :public_key.pem_decode() @@ -1301,15 +1409,15 @@ defmodule Pleroma.User do end # OStatus Magic Key - def public_key_from_info(%{magic_key: magic_key}) when not is_nil(magic_key) do + def public_key(%{magic_key: magic_key}) when not is_nil(magic_key) do {:ok, Pleroma.Web.Salmon.decode_key(magic_key)} end - def public_key_from_info(_), do: {:error, "not found key"} + def public_key(_), do: {:error, "not found key"} def get_public_key_for_ap_id(ap_id) do with {:ok, %User{} = user} <- get_or_fetch_by_ap_id(ap_id), - {:ok, public_key} <- public_key_from_info(user.info) do + {:ok, public_key} <- public_key(user) do {:ok, public_key} else _ -> :error @@ -1328,7 +1436,7 @@ defmodule Pleroma.User do end def ap_enabled?(%User{local: true}), do: true - def ap_enabled?(%User{info: info}), do: info.ap_enabled + def ap_enabled?(%User{ap_enabled: ap_enabled}), do: ap_enabled def ap_enabled?(_), do: false @doc "Gets or fetch a user by uri or nickname." @@ -1486,7 +1594,7 @@ defmodule Pleroma.User do left_join: a in Pleroma.Activity, on: u.ap_id == a.actor, where: not is_nil(u.nickname), - where: fragment("not (?->'deactivated' @> 'true')", u.info), + where: u.deactivated != ^true, where: u.id not in ^has_read_notifications, group_by: u.id, having: @@ -1500,16 +1608,16 @@ defmodule Pleroma.User do ## Examples - iex> Pleroma.User.switch_email_notifications(Pleroma.User{info: %{email_notifications: %{"digest" => false}}}, "digest", true) - Pleroma.User{info: %{email_notifications: %{"digest" => true}}} + iex> Pleroma.User.switch_email_notifications(Pleroma.User{email_notifications: %{"digest" => false}}, "digest", true) + Pleroma.User{email_notifications: %{"digest" => true}} - iex> Pleroma.User.switch_email_notifications(Pleroma.User{info: %{email_notifications: %{"digest" => true}}}, "digest", false) - Pleroma.User{info: %{email_notifications: %{"digest" => false}}} + iex> Pleroma.User.switch_email_notifications(Pleroma.User{email_notifications: %{"digest" => true}}, "digest", false) + Pleroma.User{email_notifications: %{"digest" => false}} """ @spec switch_email_notifications(t(), String.t(), boolean()) :: {:ok, t()} | {:error, Ecto.Changeset.t()} def switch_email_notifications(user, type, status) do - update_info(user, &User.Info.update_email_notifications(&1, %{type => status})) + User.update_email_notifications(user, %{type => status}) end @doc """ @@ -1529,17 +1637,16 @@ defmodule Pleroma.User do @spec toggle_confirmation(User.t()) :: {:ok, User.t()} | {:error, Changeset.t()} def toggle_confirmation(%User{} = user) do - need_confirmation? = !user.info.confirmation_pending - user - |> update_info(&User.Info.confirmation_changeset(&1, need_confirmation: need_confirmation?)) + |> confirmation_changeset(need_confirmation: !user.confirmation_pending) + |> update_and_set_cache() end - def get_mascot(%{info: %{mascot: %{} = mascot}}) when not is_nil(mascot) do + def get_mascot(%{mascot: %{} = mascot}) when not is_nil(mascot) do mascot end - def get_mascot(%{info: %{mascot: mascot}}) when is_nil(mascot) do + def get_mascot(%{mascot: mascot}) when is_nil(mascot) do # use instance-default config = Pleroma.Config.get([:assets, :mascots]) default_mascot = Pleroma.Config.get([:assets, :default_mascot]) @@ -1609,6 +1716,31 @@ defmodule Pleroma.User do |> update_and_set_cache() end + # Internal function; public one is `deactivate/2` + defp set_activation_status(user, deactivated) do + user + |> cast(%{deactivated: deactivated}, [:deactivated]) + |> update_and_set_cache() + end + + def update_banner(user, banner) do + user + |> cast(%{banner: banner}, [:banner]) + |> update_and_set_cache() + end + + def update_background(user, background) do + user + |> cast(%{background: background}, [:background]) + |> update_and_set_cache() + end + + def update_source_data(user, source_data) do + user + |> cast(%{source_data: source_data}, [:source_data]) + |> update_and_set_cache() + end + @doc """ Changes `user.info` and returns the user changeset. @@ -1630,4 +1762,160 @@ defmodule Pleroma.User do |> change_info(fun) |> update_and_set_cache() end + + def roles(%{is_moderator: is_moderator, is_admin: is_admin}) do + %{ + admin: is_admin, + moderator: is_moderator + } + end + + # ``fields`` is an array of mastodon profile field, containing ``{"name": "…", "value": "…"}``. + # For example: [{"name": "Pronoun", "value": "she/her"}, …] + def fields(%{fields: nil, source_data: %{"attachment" => attachment}}) do + limit = Pleroma.Config.get([:instance, :max_remote_account_fields], 0) + + attachment + |> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end) + |> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end) + |> Enum.take(limit) + end + + def fields(%{fields: nil}), do: [] + + def fields(%{fields: fields}), do: fields + + def validate_fields(changeset, remote? \\ false) do + limit_name = if remote?, do: :max_remote_account_fields, else: :max_account_fields + limit = Pleroma.Config.get([:instance, limit_name], 0) + + changeset + |> validate_length(:fields, max: limit) + |> validate_change(:fields, fn :fields, fields -> + if Enum.all?(fields, &valid_field?/1) do + [] + else + [fields: "invalid"] + end + end) + end + + defp valid_field?(%{"name" => name, "value" => value}) do + name_limit = Pleroma.Config.get([:instance, :account_field_name_length], 255) + value_limit = Pleroma.Config.get([:instance, :account_field_value_length], 255) + + is_binary(name) && is_binary(value) && String.length(name) <= name_limit && + String.length(value) <= value_limit + end + + defp valid_field?(_), do: false + + defp truncate_field(%{"name" => name, "value" => value}) do + {name, _chopped} = + String.split_at(name, Pleroma.Config.get([:instance, :account_field_name_length], 255)) + + {value, _chopped} = + String.split_at(value, Pleroma.Config.get([:instance, :account_field_value_length], 255)) + + %{"name" => name, "value" => value} + end + + def admin_api_update(user, params) do + user + |> cast(params, [ + :is_moderator, + :is_admin, + :show_role + ]) + |> update_and_set_cache() + end + + def mascot_update(user, url) do + user + |> cast(%{mascot: url}, [:mascot]) + |> validate_required([:mascot]) + |> update_and_set_cache() + end + + def mastodon_settings_update(user, settings) do + user + |> cast(%{settings: settings}, [:settings]) + |> validate_required([:settings]) + |> update_and_set_cache() + end + + @spec confirmation_changeset(User.t(), keyword()) :: Changeset.t() + def confirmation_changeset(user, need_confirmation: need_confirmation?) do + params = + if need_confirmation? do + %{ + confirmation_pending: true, + confirmation_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64() + } + else + %{ + confirmation_pending: false, + confirmation_token: nil + } + end + + cast(user, params, [:confirmation_pending, :confirmation_token]) + end + + def add_pinnned_activity(user, %Pleroma.Activity{id: id}) do + if id not in user.pinned_activities do + max_pinned_statuses = Pleroma.Config.get([:instance, :max_pinned_statuses], 0) + params = %{pinned_activities: user.pinned_activities ++ [id]} + + user + |> cast(params, [:pinned_activities]) + |> validate_length(:pinned_activities, + max: max_pinned_statuses, + message: "You have already pinned the maximum number of statuses" + ) + else + change(user) + end + |> update_and_set_cache() + end + + def remove_pinnned_activity(user, %Pleroma.Activity{id: id}) do + params = %{pinned_activities: List.delete(user.pinned_activities, id)} + + user + |> cast(params, [:pinned_activities]) + |> update_and_set_cache() + end + + def update_email_notifications(user, settings) do + email_notifications = + user.email_notifications + |> Map.merge(settings) + |> Map.take(["digest"]) + + params = %{email_notifications: email_notifications} + fields = [:email_notifications] + + user + |> cast(params, fields) + |> validate_required(fields) + |> update_and_set_cache() + end + + defp set_subscribers(user, subscribers) do + params = %{subscribers: subscribers} + + user + |> cast(params, [:subscribers]) + |> validate_required([:subscribers]) + |> update_and_set_cache() + end + + def add_to_subscribers(user, subscribed) do + set_subscribers(user, Enum.uniq([subscribed | user.subscribers])) + end + + def remove_from_subscribers(user, subscribed) do + set_subscribers(user, List.delete(user.subscribers, subscribed)) + end end diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex index 4b5b43d7f..fe59ddeab 100644 --- a/lib/pleroma/user/info.ex +++ b/lib/pleroma/user/info.ex @@ -11,62 +11,11 @@ defmodule Pleroma.User.Info do @type t :: %__MODULE__{} embedded_schema do - field(:banner, :map, default: %{}) - field(:background, :map, default: %{}) - field(:source_data, :map, default: %{}) - field(:note_count, :integer, default: 0) - field(:follower_count, :integer, default: 0) - # Should be filled in only for remote users - field(:following_count, :integer, default: nil) - field(:locked, :boolean, default: false) - field(:confirmation_pending, :boolean, default: false) - field(:password_reset_pending, :boolean, default: false) - field(:confirmation_token, :string, default: nil) - field(:default_scope, :string, default: "public") field(:blocks, {:array, :string}, default: []) field(:domain_blocks, {:array, :string}, default: []) field(:mutes, {:array, :string}, default: []) field(:muted_reblogs, {:array, :string}, default: []) field(:muted_notifications, {:array, :string}, default: []) - field(:subscribers, {:array, :string}, default: []) - field(:deactivated, :boolean, default: false) - field(:no_rich_text, :boolean, default: false) - field(:ap_enabled, :boolean, default: false) - field(:is_moderator, :boolean, default: false) - field(:is_admin, :boolean, default: false) - field(:show_role, :boolean, default: true) - field(:keys, :string, default: nil) - field(:settings, :map, default: nil) - field(:magic_key, :string, default: nil) - field(:uri, :string, default: nil) - field(:topic, :string, default: nil) - field(:hub, :string, default: nil) - field(:salmon, :string, default: nil) - field(:hide_followers_count, :boolean, default: false) - field(:hide_follows_count, :boolean, default: false) - field(:hide_followers, :boolean, default: false) - field(:hide_follows, :boolean, default: false) - field(:hide_favorites, :boolean, default: true) - field(:unread_conversation_count, :integer, default: 0) - field(:pinned_activities, {:array, :string}, default: []) - field(:email_notifications, :map, default: %{"digest" => false}) - field(:mascot, :map, default: nil) - field(:emoji, {:array, :map}, default: []) - field(:pleroma_settings_store, :map, default: %{}) - field(:fields, {:array, :map}, default: nil) - field(:raw_fields, {:array, :map}, default: []) - field(:discoverable, :boolean, default: false) - - field(:notification_settings, :map, - default: %{ - "followers" => true, - "follows" => true, - "non_follows" => true, - "non_followers" => true - } - ) - - field(:skip_thread_containment, :boolean, default: false) # Found in the wild # ap_id -> Where is this used? @@ -77,84 +26,6 @@ defmodule Pleroma.User.Info do # subject _> Where is this used? end - def set_activation_status(info, deactivated) do - params = %{deactivated: deactivated} - - info - |> cast(params, [:deactivated]) - |> validate_required([:deactivated]) - end - - def set_password_reset_pending(info, pending) do - params = %{password_reset_pending: pending} - - info - |> cast(params, [:password_reset_pending]) - |> validate_required([:password_reset_pending]) - end - - def update_notification_settings(info, settings) do - settings = - settings - |> Enum.map(fn {k, v} -> {k, v in [true, "true", "True", "1"]} end) - |> Map.new() - - notification_settings = - info.notification_settings - |> Map.merge(settings) - |> Map.take(["followers", "follows", "non_follows", "non_followers"]) - - params = %{notification_settings: notification_settings} - - info - |> cast(params, [:notification_settings]) - |> validate_required([:notification_settings]) - end - - @doc """ - Update email notifications in the given User.Info struct. - - Examples: - - iex> update_email_notifications(%Pleroma.User.Info{email_notifications: %{"digest" => false}}, %{"digest" => true}) - %Pleroma.User.Info{email_notifications: %{"digest" => true}} - - """ - @spec update_email_notifications(t(), map()) :: Ecto.Changeset.t() - def update_email_notifications(info, settings) do - email_notifications = - info.email_notifications - |> Map.merge(settings) - |> Map.take(["digest"]) - - params = %{email_notifications: email_notifications} - fields = [:email_notifications] - - info - |> cast(params, fields) - |> validate_required(fields) - end - - def add_to_note_count(info, number) do - set_note_count(info, info.note_count + number) - end - - def set_note_count(info, number) do - params = %{note_count: Enum.max([0, number])} - - info - |> cast(params, [:note_count]) - |> validate_required([:note_count]) - end - - def set_follower_count(info, number) do - params = %{follower_count: Enum.max([0, number])} - - info - |> cast(params, [:follower_count]) - |> validate_required([:follower_count]) - end - def set_mutes(info, mutes) do params = %{mutes: mutes} @@ -181,14 +52,6 @@ defmodule Pleroma.User.Info do |> validate_required([:blocks]) end - def set_subscribers(info, subscribers) do - params = %{subscribers: subscribers} - - info - |> cast(params, [:subscribers]) - |> validate_required([:subscribers]) - end - @spec add_to_mutes(Info.t(), String.t(), boolean()) :: Changeset.t() def add_to_mutes(info, muted, notifications?) do info @@ -214,14 +77,6 @@ defmodule Pleroma.User.Info do set_blocks(info, List.delete(info.blocks, blocked)) end - def add_to_subscribers(info, subscribed) do - set_subscribers(info, Enum.uniq([subscribed | info.subscribers])) - end - - def remove_from_subscribers(info, subscribed) do - set_subscribers(info, List.delete(info.subscribers, subscribed)) - end - def set_domain_blocks(info, domain_blocks) do params = %{domain_blocks: domain_blocks} @@ -238,205 +93,6 @@ defmodule Pleroma.User.Info do set_domain_blocks(info, List.delete(info.domain_blocks, domain_blocked)) end - def set_keys(info, keys) do - params = %{keys: keys} - - info - |> cast(params, [:keys]) - |> validate_required([:keys]) - end - - def remote_user_creation(info, params) do - params = - if Map.has_key?(params, :fields) do - Map.put(params, :fields, Enum.map(params[:fields], &truncate_field/1)) - else - params - end - - info - |> cast(params, [ - :ap_enabled, - :source_data, - :banner, - :locked, - :magic_key, - :uri, - :hub, - :topic, - :salmon, - :hide_followers, - :hide_follows, - :hide_followers_count, - :hide_follows_count, - :follower_count, - :fields, - :following_count, - :discoverable - ]) - |> validate_fields(true) - end - - def user_upgrade(info, params, remote? \\ false) do - info - |> cast(params, [ - :ap_enabled, - :source_data, - :banner, - :locked, - :magic_key, - :follower_count, - :following_count, - :hide_follows, - :fields, - :hide_followers, - :discoverable, - :hide_followers_count, - :hide_follows_count - ]) - |> validate_fields(remote?) - end - - def profile_update(info, params) do - info - |> cast(params, [ - :locked, - :no_rich_text, - :default_scope, - :banner, - :hide_follows, - :hide_followers, - :hide_followers_count, - :hide_follows_count, - :hide_favorites, - :background, - :show_role, - :skip_thread_containment, - :fields, - :raw_fields, - :pleroma_settings_store, - :discoverable - ]) - |> validate_fields() - end - - def validate_fields(changeset, remote? \\ false) do - limit_name = if remote?, do: :max_remote_account_fields, else: :max_account_fields - limit = Pleroma.Config.get([:instance, limit_name], 0) - - changeset - |> validate_length(:fields, max: limit) - |> validate_change(:fields, fn :fields, fields -> - if Enum.all?(fields, &valid_field?/1) do - [] - else - [fields: "invalid"] - end - end) - end - - defp valid_field?(%{"name" => name, "value" => value}) do - name_limit = Pleroma.Config.get([:instance, :account_field_name_length], 255) - value_limit = Pleroma.Config.get([:instance, :account_field_value_length], 255) - - is_binary(name) && is_binary(value) && String.length(name) <= name_limit && - String.length(value) <= value_limit - end - - defp valid_field?(_), do: false - - defp truncate_field(%{"name" => name, "value" => value}) do - {name, _chopped} = - String.split_at(name, Pleroma.Config.get([:instance, :account_field_name_length], 255)) - - {value, _chopped} = - String.split_at(value, Pleroma.Config.get([:instance, :account_field_value_length], 255)) - - %{"name" => name, "value" => value} - end - - @spec confirmation_changeset(Info.t(), keyword()) :: Changeset.t() - def confirmation_changeset(info, opts) do - need_confirmation? = Keyword.get(opts, :need_confirmation) - - params = - if need_confirmation? do - %{ - confirmation_pending: true, - confirmation_token: :crypto.strong_rand_bytes(32) |> Base.url_encode64() - } - else - %{ - confirmation_pending: false, - confirmation_token: nil - } - end - - cast(info, params, [:confirmation_pending, :confirmation_token]) - end - - def mastodon_settings_update(info, settings) do - params = %{settings: settings} - - info - |> cast(params, [:settings]) - |> validate_required([:settings]) - end - - def mascot_update(info, url) do - params = %{mascot: url} - - info - |> cast(params, [:mascot]) - |> validate_required([:mascot]) - end - - def set_source_data(info, source_data) do - params = %{source_data: source_data} - - info - |> cast(params, [:source_data]) - |> validate_required([:source_data]) - end - - def admin_api_update(info, params) do - info - |> cast(params, [ - :is_moderator, - :is_admin, - :show_role - ]) - end - - def add_pinnned_activity(info, %Pleroma.Activity{id: id}) do - if id not in info.pinned_activities do - max_pinned_statuses = Pleroma.Config.get([:instance, :max_pinned_statuses], 0) - params = %{pinned_activities: info.pinned_activities ++ [id]} - - info - |> cast(params, [:pinned_activities]) - |> validate_length(:pinned_activities, - max: max_pinned_statuses, - message: "You have already pinned the maximum number of statuses" - ) - else - change(info) - end - end - - def remove_pinnned_activity(info, %Pleroma.Activity{id: id}) do - params = %{pinned_activities: List.delete(info.pinned_activities, id)} - - cast(info, params, [:pinned_activities]) - end - - def roles(%Info{is_moderator: is_moderator, is_admin: is_admin}) do - %{ - admin: is_admin, - moderator: is_moderator - } - end - def add_reblog_mute(info, ap_id) do params = %{muted_reblogs: info.muted_reblogs ++ [ap_id]} @@ -448,31 +104,4 @@ defmodule Pleroma.User.Info do cast(info, params, [:muted_reblogs]) end - - # ``fields`` is an array of mastodon profile field, containing ``{"name": "…", "value": "…"}``. - # For example: [{"name": "Pronoun", "value": "she/her"}, …] - def fields(%{fields: nil, source_data: %{"attachment" => attachment}}) do - limit = Pleroma.Config.get([:instance, :max_remote_account_fields], 0) - - attachment - |> Enum.filter(fn %{"type" => t} -> t == "PropertyValue" end) - |> Enum.map(fn fields -> Map.take(fields, ["name", "value"]) end) - |> Enum.take(limit) - end - - def fields(%{fields: nil}), do: [] - - def fields(%{fields: fields}), do: fields - - def follow_information_update(info, params) do - info - |> cast(params, [ - :hide_followers, - :hide_follows, - :follower_count, - :following_count, - :hide_followers_count, - :hide_follows_count - ]) - end end diff --git a/lib/pleroma/user/query.ex b/lib/pleroma/user/query.ex index 2baf016cf..7f5273c4e 100644 --- a/lib/pleroma/user/query.ex +++ b/lib/pleroma/user/query.ex @@ -56,7 +56,6 @@ defmodule Pleroma.User.Query do @ilike_criteria [:nickname, :name, :query] @equal_criteria [:email] - @role_criteria [:is_admin, :is_moderator] @contains_criteria [:ap_id, :nickname] @spec build(criteria()) :: Query.t() @@ -100,15 +99,19 @@ defmodule Pleroma.User.Query do Enum.reduce(tags, query, &prepare_tag_criteria/2) end - defp compose_query({key, _}, query) when key in @role_criteria do - where(query, [u], fragment("(?->? @> 'true')", u.info, ^to_string(key))) + defp compose_query({:is_admin, _}, query) do + where(query, [u], u.is_admin) + end + + defp compose_query({:is_moderator, _}, query) do + where(query, [u], u.is_moderator) end defp compose_query({:super_users, _}, query) do where( query, [u], - fragment("?->'is_admin' @> 'true' OR ?->'is_moderator' @> 'true'", u.info, u.info) + u.is_admin or u.is_moderator ) end @@ -117,7 +120,13 @@ defmodule Pleroma.User.Query do defp compose_query({:external, _}, query), do: location_query(query, false) defp compose_query({:active, _}, query) do - where(query, [u], fragment("not (?->'deactivated' @> 'true')", u.info)) + User.restrict_deactivated(query) + |> where([u], not is_nil(u.nickname)) + end + + defp compose_query({:legacy_active, _}, query) do + query + |> where([u], fragment("not (?->'deactivated' @> 'true')", u.info)) |> where([u], not is_nil(u.nickname)) end @@ -126,7 +135,7 @@ defmodule Pleroma.User.Query do end defp compose_query({:deactivated, true}, query) do - where(query, [u], fragment("?->'deactivated' @> 'true'", u.info)) + where(query, [u], u.deactivated == ^true) |> where([u], not is_nil(u.nickname)) end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 364452b5d..78efaae2a 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -68,7 +68,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp check_actor_is_active(actor) do if not is_nil(actor) do with user <- User.get_cached_by_ap_id(actor), - false <- user.info.deactivated do + false <- user.deactivated do true else _e -> false @@ -601,7 +601,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_thread_visibility( query, - %{"user" => %User{info: %{skip_thread_containment: true}}}, + %{"user" => %User{skip_thread_containment: true}}, _ ), do: query @@ -639,7 +639,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do |> Map.put("user", reading_user) |> Map.put("actor_id", user.ap_id) |> Map.put("whole_db", true) - |> Map.put("pinned_activity_ids", user.info.pinned_activities) + |> Map.put("pinned_activity_ids", user.pinned_activities) recipients = user_activities_recipients(%{ @@ -1049,14 +1049,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do user_data = %{ ap_id: data["id"], - info: %{ - ap_enabled: true, - source_data: data, - banner: banner, - fields: fields, - locked: locked, - discoverable: discoverable - }, + banner: banner, + discoverable: discoverable, + source_data: data, + fields: fields, + locked: locked, + ap_enabled: true, avatar: avatar, name: data["name"], follower_address: data["followers"], diff --git a/lib/pleroma/web/activity_pub/activity_pub_controller.ex b/lib/pleroma/web/activity_pub/activity_pub_controller.ex index 080030eb5..568623318 100644 --- a/lib/pleroma/web/activity_pub/activity_pub_controller.ex +++ b/lib/pleroma/web/activity_pub/activity_pub_controller.ex @@ -137,7 +137,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do with %User{} = user <- User.get_cached_by_nickname(nickname), {user, for_user} <- ensure_user_keys_present_and_maybe_refresh_for_user(user, for_user), {:show_follows, true} <- - {:show_follows, (for_user && for_user == user) || !user.info.hide_follows} do + {:show_follows, (for_user && for_user == user) || !user.hide_follows} do {page, _} = Integer.parse(page) conn @@ -174,7 +174,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do with %User{} = user <- User.get_cached_by_nickname(nickname), {user, for_user} <- ensure_user_keys_present_and_maybe_refresh_for_user(user, for_user), {:show_followers, true} <- - {:show_followers, (for_user && for_user == user) || !user.info.hide_followers} do + {:show_followers, (for_user && for_user == user) || !user.hide_followers} do {page, _} = Integer.parse(page) conn @@ -387,7 +387,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubController do def handle_user_activity(user, %{"type" => "Delete"} = params) do with %Object{} = object <- Object.normalize(params["object"]), - true <- user.info.is_moderator || user.ap_id == object.data["actor"], + true <- user.is_moderator || user.ap_id == object.data["actor"], {:ok, delete} <- ActivityPub.delete(object) do {:ok, delete} else diff --git a/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex index b90193ca0..8abe18e29 100644 --- a/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex +++ b/lib/pleroma/web/activity_pub/mrf/anti_link_spam_policy.ex @@ -11,7 +11,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicy do # has the user successfully posted before? defp old_user?(%User{} = u) do - u.info.note_count > 0 || u.info.follower_count > 0 + u.note_count > 0 || u.follower_count > 0 end # does the post contain links? diff --git a/lib/pleroma/web/activity_pub/publisher.ex b/lib/pleroma/web/activity_pub/publisher.ex index 3866dacee..ebbc1e970 100644 --- a/lib/pleroma/web/activity_pub/publisher.ex +++ b/lib/pleroma/web/activity_pub/publisher.ex @@ -140,7 +140,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do |> Enum.map(& &1.ap_id) end - defp maybe_use_sharedinbox(%User{info: %{source_data: data}}), + defp maybe_use_sharedinbox(%User{source_data: data}), do: (is_map(data["endpoints"]) && Map.get(data["endpoints"], "sharedInbox")) || data["inbox"] @doc """ @@ -156,7 +156,7 @@ defmodule Pleroma.Web.ActivityPub.Publisher do """ def determine_inbox( %Activity{data: activity_data}, - %User{info: %{source_data: data}} = user + %User{source_data: data} = user ) do to = activity_data["to"] || [] cc = activity_data["cc"] || [] @@ -190,12 +190,12 @@ defmodule Pleroma.Web.ActivityPub.Publisher do recipients |> Enum.filter(&User.ap_enabled?/1) - |> Enum.map(fn %{info: %{source_data: data}} -> data["inbox"] end) + |> Enum.map(fn %{source_data: data} -> data["inbox"] end) |> Enum.filter(fn inbox -> should_federate?(inbox, public) end) |> Instances.filter_reachable() |> Enum.each(fn {inbox, unreachable_since} -> %User{ap_id: ap_id} = - Enum.find(recipients, fn %{info: %{source_data: data}} -> data["inbox"] == inbox end) + Enum.find(recipients, fn %{source_data: data} -> data["inbox"] == inbox end) # Get all the recipients on the same host and add them to cc. Otherwise, a remote # instance would only accept a first message for the first recipient and ignore the rest. diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index b56343beb..d0ad270c2 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -600,9 +600,8 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do with %User{ap_id: ^actor_id} = actor <- User.get_cached_by_ap_id(object["id"]) do {:ok, new_user_data} = ActivityPub.user_data_from_user_object(object) - banner = new_user_data[:info][:banner] - locked = new_user_data[:info][:locked] || false - attachment = get_in(new_user_data, [:info, :source_data, "attachment"]) || [] + locked = new_user_data[:locked] || false + attachment = get_in(new_user_data, [:source_data, "attachment"]) || [] fields = attachment @@ -611,8 +610,9 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do update_data = new_user_data - |> Map.take([:name, :bio, :avatar]) - |> Map.put(:info, %{banner: banner, locked: locked, fields: fields}) + |> Map.take([:avatar, :banner, :bio, :name]) + |> Map.put(:fields, fields) + |> Map.put(:locked, locked) actor |> User.upgrade_changeset(update_data, true) @@ -979,7 +979,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do %{"type" => "Mention", "href" => ap_id, "name" => "@#{nickname}"} end - def take_emoji_tags(%User{info: %{emoji: emoji} = _user_info} = _user) do + def take_emoji_tags(%User{emoji: emoji}) do emoji |> Enum.flat_map(&Map.to_list/1) |> Enum.map(&build_emoji_tag/1) diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex index 9b39d1629..82879a486 100644 --- a/lib/pleroma/web/activity_pub/views/user_view.ex +++ b/lib/pleroma/web/activity_pub/views/user_view.ex @@ -78,8 +78,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do emoji_tags = Transmogrifier.take_emoji_tags(user) fields = - user.info - |> User.Info.fields() + user + |> User.fields() |> Enum.map(fn %{"name" => name, "value" => value} -> %{ "name" => Pleroma.HTML.strip_tags(name), @@ -99,7 +99,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do "name" => user.name, "summary" => user.bio, "url" => user.ap_id, - "manuallyApprovesFollowers" => user.info.locked, + "manuallyApprovesFollowers" => user.locked, "publicKey" => %{ "id" => "#{user.ap_id}#main-key", "owner" => user.ap_id, @@ -107,8 +107,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do }, "endpoints" => endpoints, "attachment" => fields, - "tag" => (user.info.source_data["tag"] || []) ++ emoji_tags, - "discoverable" => user.info.discoverable + "tag" => (user.source_data["tag"] || []) ++ emoji_tags, + "discoverable" => user.discoverable } |> Map.merge(maybe_make_image(&User.avatar_url/2, "icon", user)) |> Map.merge(maybe_make_image(&User.banner_url/2, "image", user)) @@ -116,8 +116,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do end def render("following.json", %{user: user, page: page} = opts) do - showing_items = (opts[:for] && opts[:for] == user) || !user.info.hide_follows - showing_count = showing_items || !user.info.hide_follows_count + showing_items = (opts[:for] && opts[:for] == user) || !user.hide_follows + showing_count = showing_items || !user.hide_follows_count query = User.get_friends_query(user) query = from(user in query, select: [:ap_id]) @@ -135,8 +135,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do end def render("following.json", %{user: user} = opts) do - showing_items = (opts[:for] && opts[:for] == user) || !user.info.hide_follows - showing_count = showing_items || !user.info.hide_follows_count + showing_items = (opts[:for] && opts[:for] == user) || !user.hide_follows + showing_count = showing_items || !user.hide_follows_count query = User.get_friends_query(user) query = from(user in query, select: [:ap_id]) @@ -155,7 +155,7 @@ defmodule Pleroma.Web.ActivityPub.UserView do "totalItems" => total, "first" => if showing_items do - collection(following, "#{user.ap_id}/following", 1, !user.info.hide_follows) + collection(following, "#{user.ap_id}/following", 1, !user.hide_follows) else "#{user.ap_id}/following?page=1" end @@ -164,8 +164,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do end def render("followers.json", %{user: user, page: page} = opts) do - showing_items = (opts[:for] && opts[:for] == user) || !user.info.hide_followers - showing_count = showing_items || !user.info.hide_followers_count + showing_items = (opts[:for] && opts[:for] == user) || !user.hide_followers + showing_count = showing_items || !user.hide_followers_count query = User.get_followers_query(user) query = from(user in query, select: [:ap_id]) @@ -183,8 +183,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do end def render("followers.json", %{user: user} = opts) do - showing_items = (opts[:for] && opts[:for] == user) || !user.info.hide_followers - showing_count = showing_items || !user.info.hide_followers_count + showing_items = (opts[:for] && opts[:for] == user) || !user.hide_followers + showing_count = showing_items || !user.hide_followers_count query = User.get_followers_query(user) query = from(user in query, select: [:ap_id]) diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex index 513bae800..3894b3742 100644 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@ -234,9 +234,9 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do def user_toggle_activation(%{assigns: %{user: admin}} = conn, %{"nickname" => nickname}) do user = User.get_cached_by_nickname(nickname) - {:ok, updated_user} = User.deactivate(user, !user.info.deactivated) + {:ok, updated_user} = User.deactivate(user, !user.deactivated) - action = if user.info.deactivated, do: "activate", else: "deactivate" + action = if user.deactivated, do: "activate", else: "deactivate" ModerationLog.insert_log(%{ actor: admin, @@ -318,12 +318,12 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do "nickname" => nickname }) when permission_group in ["moderator", "admin"] do - info = Map.put(%{}, "is_" <> permission_group, true) + fields = %{:"is_#{permission_group}" => true} {:ok, user} = nickname |> User.get_cached_by_nickname() - |> User.update_info(&User.Info.admin_api_update(&1, info)) + |> User.admin_api_update(fields) ModerationLog.insert_log(%{ action: "grant", @@ -332,7 +332,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do permission: permission_group }) - json(conn, info) + json(conn, fields) end def right_add(conn, _) do @@ -344,8 +344,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do conn |> json(%{ - is_moderator: user.info.is_moderator, - is_admin: user.info.is_admin + is_moderator: user.is_moderator, + is_admin: user.is_admin }) end @@ -361,12 +361,12 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do } ) when permission_group in ["moderator", "admin"] do - info = Map.put(%{}, "is_" <> permission_group, false) + fields = %{:"is_#{permission_group}" => false} {:ok, user} = nickname |> User.get_cached_by_nickname() - |> User.update_info(&User.Info.admin_api_update(&1, info)) + |> User.admin_api_update(fields) ModerationLog.insert_log(%{ action: "revoke", @@ -375,7 +375,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do permission: permission_group }) - json(conn, info) + json(conn, fields) end def right_delete(conn, _) do @@ -389,7 +389,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do with {:ok, status} <- Ecto.Type.cast(:boolean, status), %User{} = user <- User.get_cached_by_nickname(nickname), {:ok, _} <- User.deactivate(user, !status) do - action = if(user.info.deactivated, do: "activate", else: "deactivate") + action = if(user.deactivated, do: "activate", else: "deactivate") ModerationLog.insert_log(%{ actor: admin, diff --git a/lib/pleroma/web/admin_api/views/account_view.ex b/lib/pleroma/web/admin_api/views/account_view.ex index a96affd40..eed1b9fa7 100644 --- a/lib/pleroma/web/admin_api/views/account_view.ex +++ b/lib/pleroma/web/admin_api/views/account_view.ex @@ -7,7 +7,6 @@ defmodule Pleroma.Web.AdminAPI.AccountView do alias Pleroma.HTML alias Pleroma.User - alias Pleroma.User.Info alias Pleroma.Web.AdminAPI.AccountView alias Pleroma.Web.MediaProxy @@ -28,9 +27,9 @@ defmodule Pleroma.Web.AdminAPI.AccountView do "avatar" => avatar, "nickname" => user.nickname, "display_name" => display_name, - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "local" => user.local, - "roles" => Info.roles(user.info), + "roles" => User.roles(user), "tags" => user.tags || [] } end diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index 386408d51..ef738a870 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -263,10 +263,10 @@ defmodule Pleroma.Web.CommonAPI do # Updates the emojis for a user based on their profile def update(user) do emoji = emoji_from_profile(user) - source_data = user.info |> Map.get(:source_data, %{}) |> Map.put("tag", emoji) + source_data = Map.put(user.source_data, "tag", emoji) user = - case User.update_info(user, &User.Info.set_source_data(&1, source_data)) do + case User.update_source_data(user, source_data) do {:ok, user} -> user _ -> user end @@ -287,20 +287,20 @@ defmodule Pleroma.Web.CommonAPI do object: %Object{data: %{"type" => "Note"}} } = activity <- get_by_id_or_ap_id(id_or_ap_id), true <- Visibility.is_public?(activity), - {:ok, _user} <- User.update_info(user, &User.Info.add_pinnned_activity(&1, activity)) do + {:ok, _user} <- User.add_pinnned_activity(user, activity) do {:ok, activity} else - {:error, %{changes: %{info: %{errors: [pinned_activities: {err, _}]}}}} -> {:error, err} + {:error, %{errors: [pinned_activities: {err, _}]}} -> {:error, err} _ -> {:error, dgettext("errors", "Could not pin")} end end def unpin(id_or_ap_id, user) do with %Activity{} = activity <- get_by_id_or_ap_id(id_or_ap_id), - {:ok, _user} <- User.update_info(user, &User.Info.remove_pinnned_activity(&1, activity)) do + {:ok, _user} <- User.remove_pinnned_activity(user, activity) do {:ok, activity} else - %{errors: [pinned_activities: {err, _}]} -> {:error, err} + {:error, %{errors: [pinned_activities: {err, _}]}} -> {:error, err} _ -> {:error, dgettext("errors", "Could not unpin")} end end diff --git a/lib/pleroma/web/masto_fe_controller.ex b/lib/pleroma/web/masto_fe_controller.ex index 87860f1d5..cf0fe91ce 100644 --- a/lib/pleroma/web/masto_fe_controller.ex +++ b/lib/pleroma/web/masto_fe_controller.ex @@ -36,7 +36,7 @@ defmodule Pleroma.Web.MastoFEController do @doc "PUT /api/web/settings" def put_settings(%{assigns: %{user: user}} = conn, %{"data" => settings} = _params) do - with {:ok, _} <- User.update_info(user, &User.Info.mastodon_settings_update(&1, settings)) do + with {:ok, _} <- User.mastodon_settings_update(user, settings) do json(conn, %{}) else e -> diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index 9ef7fd48d..7ba2f9ff1 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -130,25 +130,6 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do def update_credentials(%{assigns: %{user: original_user}} = conn, params) do user = original_user - user_params = - %{} - |> add_if_present(params, "display_name", :name) - |> add_if_present(params, "note", :bio, fn value -> {:ok, User.parse_bio(value, user)} end) - |> add_if_present(params, "avatar", :avatar, fn value -> - with %Plug.Upload{} <- value, - {:ok, object} <- ActivityPub.upload(value, type: :avatar) do - {:ok, object.data} - end - end) - - emojis_text = (user_params["display_name"] || "") <> (user_params["note"] || "") - - user_info_emojis = - user.info - |> Map.get(:emoji, []) - |> Enum.concat(Emoji.Formatter.get_emoji_map(emojis_text)) - |> Enum.dedup() - params = if Map.has_key?(params, "fields_attributes") do Map.update!(params, "fields_attributes", fn fields -> @@ -160,7 +141,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do params end - info_params = + user_params = [ :no_rich_text, :locked, @@ -176,15 +157,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do |> Enum.reduce(%{}, fn key, acc -> add_if_present(acc, params, to_string(key), key, &{:ok, truthy_param?(&1)}) end) - |> add_if_present(params, "default_scope", :default_scope) - |> add_if_present(params, "fields_attributes", :fields, fn fields -> - fields = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end) - - {:ok, fields} - end) - |> add_if_present(params, "fields_attributes", :raw_fields) - |> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value -> - {:ok, Map.merge(user.info.pleroma_settings_store, value)} + |> add_if_present(params, "display_name", :name) + |> add_if_present(params, "note", :bio, fn value -> {:ok, User.parse_bio(value, user)} end) + |> add_if_present(params, "avatar", :avatar, fn value -> + with %Plug.Upload{} <- value, + {:ok, object} <- ActivityPub.upload(value, type: :avatar) do + {:ok, object.data} + end end) |> add_if_present(params, "header", :banner, fn value -> with %Plug.Upload{} <- value, @@ -198,12 +177,31 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do {:ok, object.data} end end) - |> Map.put(:emoji, user_info_emojis) + |> add_if_present(params, "fields_attributes", :fields, fn fields -> + fields = Enum.map(fields, fn f -> Map.update!(f, "value", &AutoLinker.link(&1)) end) + + {:ok, fields} + end) + |> add_if_present(params, "fields_attributes", :raw_fields) + |> add_if_present(params, "pleroma_settings_store", :pleroma_settings_store, fn value -> + {:ok, Map.merge(user.pleroma_settings_store, value)} + end) + |> add_if_present(params, "default_scope", :default_scope) + + emojis_text = (user_params["display_name"] || "") <> (user_params["note"] || "") + + user_emojis = + user + |> Map.get(:emoji, []) + |> Enum.concat(Emoji.Formatter.get_emoji_map(emojis_text)) + |> Enum.dedup() + + user_params = Map.put(user_params, :emoji, user_emojis) changeset = user |> User.update_changeset(user_params) - |> User.change_info(&User.Info.profile_update(&1, info_params)) + |> User.change_info(& &1) with {:ok, user} <- User.update_and_set_cache(changeset) do if original_user != user, do: CommonAPI.update(user) @@ -269,7 +267,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do followers = cond do for_user && user.id == for_user.id -> MastodonAPI.get_followers(user, params) - user.info.hide_followers -> [] + user.hide_followers -> [] true -> MastodonAPI.get_followers(user, params) end @@ -283,7 +281,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do followers = cond do for_user && user.id == for_user.id -> MastodonAPI.get_friends(user, params) - user.info.hide_follows -> [] + user.hide_follows -> [] true -> MastodonAPI.get_friends(user, params) end diff --git a/lib/pleroma/web/mastodon_api/views/account_view.ex b/lib/pleroma/web/mastodon_api/views/account_view.ex index 2d4976891..e30fed610 100644 --- a/lib/pleroma/web/mastodon_api/views/account_view.ex +++ b/lib/pleroma/web/mastodon_api/views/account_view.ex @@ -74,23 +74,23 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do user_info = User.get_cached_user_info(user) following_count = - if !user.info.hide_follows_count or !user.info.hide_follows or opts[:for] == user do + if !user.hide_follows_count or !user.hide_follows or opts[:for] == user do user_info.following_count else 0 end followers_count = - if !user.info.hide_followers_count or !user.info.hide_followers or opts[:for] == user do + if !user.hide_followers_count or !user.hide_followers or opts[:for] == user do user_info.follower_count else 0 end - bot = (user.info.source_data["type"] || "Person") in ["Application", "Service"] + bot = (user.source_data["type"] || "Person") in ["Application", "Service"] emojis = - (user.info.source_data["tag"] || []) + (user.source_data["tag"] || []) |> Enum.filter(fn %{"type" => t} -> t == "Emoji" end) |> Enum.map(fn %{"icon" => %{"url" => url}, "name" => name} -> %{ @@ -102,8 +102,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do end) fields = - user.info - |> User.Info.fields() + user + |> User.fields() |> Enum.map(fn %{"name" => name, "value" => value} -> %{ "name" => Pleroma.HTML.strip_tags(name), @@ -111,23 +111,19 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do } end) - raw_fields = Map.get(user.info, :raw_fields, []) - bio = HTML.filter_tags(user.bio, User.html_filter_policy(opts[:for])) relationship = render("relationship.json", %{user: opts[:for], target: user}) - discoverable = user.info.discoverable - %{ id: to_string(user.id), username: username_from_nickname(user.nickname), acct: user.nickname, display_name: display_name, - locked: user_info.locked, + locked: user.locked, created_at: Utils.to_masto_date(user.inserted_at), followers_count: followers_count, following_count: following_count, - statuses_count: user_info.note_count, + statuses_count: user.note_count, note: bio || "", url: User.profile_url(user), avatar: image, @@ -140,9 +136,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do source: %{ note: HTML.strip_tags((user.bio || "") |> String.replace("
", "\n")), sensitive: false, - fields: raw_fields, + fields: user.raw_fields, pleroma: %{ - discoverable: discoverable + discoverable: user.discoverable } }, @@ -150,14 +146,14 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do pleroma: %{ confirmation_pending: user_info.confirmation_pending, tags: user.tags, - hide_followers_count: user.info.hide_followers_count, - hide_follows_count: user.info.hide_follows_count, - hide_followers: user.info.hide_followers, - hide_follows: user.info.hide_follows, - hide_favorites: user.info.hide_favorites, + hide_followers_count: user.hide_followers_count, + hide_follows_count: user.hide_follows_count, + hide_followers: user.hide_followers, + hide_follows: user.hide_follows, + hide_favorites: user.hide_favorites, relationship: relationship, - skip_thread_containment: user.info.skip_thread_containment, - background_image: image_url(user.info.background) |> MediaProxy.url() + skip_thread_containment: user.skip_thread_containment, + background_image: image_url(user.background) |> MediaProxy.url() } } |> maybe_put_role(user, opts[:for]) @@ -195,21 +191,21 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do data, %User{id: user_id} = user, %User{id: user_id}, - user_info + _user_info ) do data - |> Kernel.put_in([:source, :privacy], user_info.default_scope) - |> Kernel.put_in([:source, :pleroma, :show_role], user.info.show_role) - |> Kernel.put_in([:source, :pleroma, :no_rich_text], user.info.no_rich_text) + |> Kernel.put_in([:source, :privacy], user.default_scope) + |> Kernel.put_in([:source, :pleroma, :show_role], user.show_role) + |> Kernel.put_in([:source, :pleroma, :no_rich_text], user.no_rich_text) end defp maybe_put_settings(data, _, _, _), do: data - defp maybe_put_settings_store(data, %User{info: info, id: id}, %User{id: id}, %{ + defp maybe_put_settings_store(data, %User{} = user, %User{}, %{ with_pleroma_settings: true }) do data - |> Kernel.put_in([:pleroma, :settings_store], info.pleroma_settings_store) + |> Kernel.put_in([:pleroma, :settings_store], user.pleroma_settings_store) end defp maybe_put_settings_store(data, _, _, _), do: data @@ -223,28 +219,28 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do defp maybe_put_chat_token(data, _, _, _), do: data - defp maybe_put_role(data, %User{info: %{show_role: true}} = user, _) do + defp maybe_put_role(data, %User{show_role: true} = user, _) do data - |> Kernel.put_in([:pleroma, :is_admin], user.info.is_admin) - |> Kernel.put_in([:pleroma, :is_moderator], user.info.is_moderator) + |> Kernel.put_in([:pleroma, :is_admin], user.is_admin) + |> Kernel.put_in([:pleroma, :is_moderator], user.is_moderator) end defp maybe_put_role(data, %User{id: user_id} = user, %User{id: user_id}) do data - |> Kernel.put_in([:pleroma, :is_admin], user.info.is_admin) - |> Kernel.put_in([:pleroma, :is_moderator], user.info.is_moderator) + |> Kernel.put_in([:pleroma, :is_admin], user.is_admin) + |> Kernel.put_in([:pleroma, :is_moderator], user.is_moderator) end defp maybe_put_role(data, _, _), do: data defp maybe_put_notification_settings(data, %User{id: user_id} = user, %User{id: user_id}) do - Kernel.put_in(data, [:pleroma, :notification_settings], user.info.notification_settings) + Kernel.put_in(data, [:pleroma, :notification_settings], user.notification_settings) end defp maybe_put_notification_settings(data, _, _), do: data - defp maybe_put_activation_status(data, user, %User{info: %{is_admin: true}}) do - Kernel.put_in(data, [:pleroma, :deactivated], user.info.deactivated) + defp maybe_put_activation_status(data, user, %User{is_admin: true}) do + Kernel.put_in(data, [:pleroma, :deactivated], user.deactivated) end defp maybe_put_activation_status(data, _, _), do: data @@ -253,7 +249,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountView do data |> Kernel.put_in( [:pleroma, :unread_conversation_count], - user.info.unread_conversation_count + user.unread_conversation_count ) end diff --git a/lib/pleroma/web/mastodon_api/views/status_view.ex b/lib/pleroma/web/mastodon_api/views/status_view.ex index 9b8dd3086..b785ca9d4 100644 --- a/lib/pleroma/web/mastodon_api/views/status_view.ex +++ b/lib/pleroma/web/mastodon_api/views/status_view.ex @@ -498,6 +498,6 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do defp present?(false), do: false defp present?(_), do: true - defp pinned?(%Activity{id: id}, %User{info: %{pinned_activities: pinned_activities}}), + defp pinned?(%Activity{id: id}, %User{pinned_activities: pinned_activities}), do: id in pinned_activities end diff --git a/lib/pleroma/web/oauth/oauth_controller.ex b/lib/pleroma/web/oauth/oauth_controller.ex index 03c9a5027..fe71aca8c 100644 --- a/lib/pleroma/web/oauth/oauth_controller.ex +++ b/lib/pleroma/web/oauth/oauth_controller.ex @@ -202,9 +202,9 @@ defmodule Pleroma.Web.OAuth.OAuthController do with {:ok, %User{} = user} <- Authenticator.get_user(conn), {:ok, app} <- Token.Utils.fetch_app(conn), {:auth_active, true} <- {:auth_active, User.auth_active?(user)}, - {:user_active, true} <- {:user_active, !user.info.deactivated}, + {:user_active, true} <- {:user_active, !user.deactivated}, {:password_reset_pending, false} <- - {:password_reset_pending, user.info.password_reset_pending}, + {:password_reset_pending, user.password_reset_pending}, {:ok, scopes} <- validate_scopes(app, params), {:ok, auth} <- Authorization.create_authorization(app, user, scopes), {:ok, token} <- Token.exchange_token(app, auth) do diff --git a/lib/pleroma/web/ostatus/handlers/follow_handler.ex b/lib/pleroma/web/ostatus/handlers/follow_handler.ex index 24513972e..483099d34 100644 --- a/lib/pleroma/web/ostatus/handlers/follow_handler.ex +++ b/lib/pleroma/web/ostatus/handlers/follow_handler.ex @@ -14,7 +14,7 @@ defmodule Pleroma.Web.OStatus.FollowHandler do followed_uri when not is_nil(followed_uri) <- XML.string_from_xpath("/entry/activity:object/id", entry), {:ok, followed} <- OStatus.find_or_make_user(followed_uri), - {:locked, false} <- {:locked, followed.info.locked}, + {:locked, false} <- {:locked, followed.locked}, {:ok, activity} <- ActivityPub.follow(actor, followed, id, false) do User.follow(actor, followed) {:ok, activity} diff --git a/lib/pleroma/web/ostatus/ostatus.ex b/lib/pleroma/web/ostatus/ostatus.ex index 5de1ceef3..a11cacacc 100644 --- a/lib/pleroma/web/ostatus/ostatus.ex +++ b/lib/pleroma/web/ostatus/ostatus.ex @@ -287,14 +287,19 @@ defmodule Pleroma.Web.OStatus do end defp build_user_data(info) do - %{ + info_fields = Enum.map(User.info_fields(), &to_string/1) + + info + |> Map.take(info_fields) + |> Map.new(fn {k, v} -> {String.to_atom(k), v} end) + |> Map.merge(%{ name: info["name"], nickname: info["nickname"] <> "@" <> info["host"], ap_id: info["uri"], info: info, avatar: info["avatar"], bio: info["bio"] - } + }) end # TODO: Just takes the first one for now. diff --git a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex index 9012e2175..ee40bbf33 100644 --- a/lib/pleroma/web/pleroma_api/controllers/account_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/account_controller.ex @@ -80,9 +80,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do @doc "PATCH /api/v1/pleroma/accounts/update_banner" def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) do - new_info = %{"banner" => %{}} - - with {:ok, user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do + with {:ok, user} <- User.update_banner(user, %{}) do CommonAPI.update(user) json(conn, %{url: nil}) end @@ -90,8 +88,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do def update_banner(%{assigns: %{user: user}} = conn, params) do with {:ok, object} <- ActivityPub.upload(%{"img" => params["banner"]}, type: :banner), - new_info <- %{"banner" => object.data}, - {:ok, user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do + {:ok, user} <- User.update_banner(user, object.data) do CommonAPI.update(user) %{"url" => [%{"href" => href} | _]} = object.data @@ -101,17 +98,14 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do @doc "PATCH /api/v1/pleroma/accounts/update_background" def update_background(%{assigns: %{user: user}} = conn, %{"img" => ""}) do - new_info = %{"background" => %{}} - - with {:ok, _user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do + with {:ok, _user} <- User.update_background(user, %{}) do json(conn, %{url: nil}) end end def update_background(%{assigns: %{user: user}} = conn, params) do with {:ok, object} <- ActivityPub.upload(params, type: :background), - new_info <- %{"background" => object.data}, - {:ok, _user} <- User.update_info(user, &User.Info.profile_update(&1, new_info)) do + {:ok, _user} <- User.update_background(user, object.data) do %{"url" => [%{"href" => href} | _]} = object.data json(conn, %{url: href}) @@ -119,7 +113,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountController do end @doc "GET /api/v1/pleroma/accounts/:id/favourites" - def favourites(%{assigns: %{account: %{info: %{hide_favorites: true}}}} = conn, _params) do + def favourites(%{assigns: %{account: %{hide_favorites: true}}} = conn, _params) do render_error(conn, :forbidden, "Can't get favorites") end diff --git a/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex b/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex index d71d72dd5..8cf552b7e 100644 --- a/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex +++ b/lib/pleroma/web/pleroma_api/controllers/mascot_controller.ex @@ -24,9 +24,7 @@ defmodule Pleroma.Web.PleromaAPI.MascotController do with {:ok, object} <- ActivityPub.upload(file, actor: User.ap_id(user)), # Reject if not an image %{type: "image"} = attachment <- render_attachment(object) do - # Sure! - # Save to the user's info - {:ok, _user} = User.update_info(user, &User.Info.mascot_update(&1, attachment)) + {:ok, _user} = User.mascot_update(user, attachment) json(conn, attachment) else diff --git a/lib/pleroma/web/salmon/salmon.ex b/lib/pleroma/web/salmon/salmon.ex index 0ffe903cd..0361c18da 100644 --- a/lib/pleroma/web/salmon/salmon.ex +++ b/lib/pleroma/web/salmon/salmon.ex @@ -147,7 +147,7 @@ defmodule Pleroma.Web.Salmon do end @doc "Pushes an activity to remote account." - def publish_one(%{recipient: %{info: %{salmon: salmon}}} = params), + def publish_one(%{recipient: %{salmon: salmon}} = params), do: publish_one(Map.put(params, :recipient, salmon)) def publish_one(%{recipient: url, feed: feed} = params) when is_binary(url) do @@ -217,19 +217,19 @@ defmodule Pleroma.Web.Salmon do remote_users = remote_users(user, activity) - salmon_urls = Enum.map(remote_users, & &1.info.salmon) + salmon_urls = Enum.map(remote_users, & &1.salmon) reachable_urls_metadata = Instances.filter_reachable(salmon_urls) reachable_urls = Map.keys(reachable_urls_metadata) remote_users - |> Enum.filter(&(&1.info.salmon in reachable_urls)) + |> Enum.filter(&(&1.salmon in reachable_urls)) |> Enum.each(fn remote_user -> Logger.debug(fn -> "Sending Salmon to #{remote_user.ap_id}" end) Publisher.enqueue_one(__MODULE__, %{ recipient_id: remote_user.id, feed: feed, - unreachable_since: reachable_urls_metadata[remote_user.info.salmon] + unreachable_since: reachable_urls_metadata[remote_user.salmon] }) end) end diff --git a/lib/pleroma/web/streamer/worker.ex b/lib/pleroma/web/streamer/worker.ex index 0ea224874..9910c3484 100644 --- a/lib/pleroma/web/streamer/worker.ex +++ b/lib/pleroma/web/streamer/worker.ex @@ -212,7 +212,7 @@ defmodule Pleroma.Web.Streamer.Worker do end @spec thread_containment(Activity.t(), User.t()) :: boolean() - defp thread_containment(_activity, %User{info: %{skip_thread_containment: true}}), do: true + defp thread_containment(_activity, %User{skip_thread_containment: true}), do: true defp thread_containment(activity, user) do if Config.get([:instance, :skip_thread_containment]) do diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index bf5a6ae42..5eafc01de 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -20,11 +20,10 @@ defmodule Pleroma.Web.TwitterAPI.Controller do action_fallback(:errors) def confirm_email(conn, %{"user_id" => uid, "token" => token}) do - new_info = [need_confirmation: false] - - with %User{info: info} = user <- User.get_cached_by_id(uid), - true <- user.local and info.confirmation_pending and info.confirmation_token == token, - {:ok, _} <- User.update_info(user, &User.Info.confirmation_changeset(&1, new_info)) do + with %User{} = user <- User.get_cached_by_id(uid), + true <- user.local and user.confirmation_pending and user.confirmation_token == token, + {:ok, _} <- + User.update_and_set_cache(User.confirmation_changeset(user, need_confirmation: false)) do redirect(conn, to: "/") end end diff --git a/lib/pleroma/web/views/masto_fe_view.ex b/lib/pleroma/web/views/masto_fe_view.ex index 21b086d4c..10cba9b3b 100644 --- a/lib/pleroma/web/views/masto_fe_view.ex +++ b/lib/pleroma/web/views/masto_fe_view.ex @@ -61,12 +61,12 @@ defmodule Pleroma.Web.MastoFEView do }, poll_limits: Config.get([:instance, :poll_limits]), rights: %{ - delete_others_notice: present?(user.info.is_moderator), - admin: present?(user.info.is_admin) + delete_others_notice: present?(user.is_moderator), + admin: present?(user.is_admin) }, compose: %{ me: "#{user.id}", - default_privacy: user.info.default_scope, + default_privacy: user.default_scope, default_sensitive: false, allow_content_types: Config.get([:instance, :allowed_post_formats]) }, @@ -86,7 +86,7 @@ defmodule Pleroma.Web.MastoFEView do "video\/mp4" ] }, - settings: user.info.settings || @default_settings, + settings: user.settings || @default_settings, push_subscription: nil, accounts: %{user.id => render(AccountView, "show.json", user: user, for: user)}, custom_emojis: render(CustomEmojiView, "index.json", custom_emojis: custom_emojis), diff --git a/lib/pleroma/web/websub/websub.ex b/lib/pleroma/web/websub/websub.ex index b61f388b8..0f98ec4fd 100644 --- a/lib/pleroma/web/websub/websub.ex +++ b/lib/pleroma/web/websub/websub.ex @@ -181,7 +181,7 @@ defmodule Pleroma.Web.Websub do end def subscribe(subscriber, subscribed, requester \\ &request_subscription/1) do - topic = subscribed.info.topic + topic = subscribed.topic # FIXME: Race condition, use transactions {:ok, subscription} = with subscription when not is_nil(subscription) <- @@ -193,7 +193,7 @@ defmodule Pleroma.Web.Websub do _e -> subscription = %WebsubClientSubscription{ topic: topic, - hub: subscribed.info.hub, + hub: subscribed.hub, subscribers: [subscriber.ap_id], state: "requested", secret: :crypto.strong_rand_bytes(8) |> Base.url_encode64(), diff --git a/priv/repo/migrations/20190710125158_add_following_address_from_source_data.exs b/priv/repo/migrations/20190710125158_add_following_address_from_source_data.exs index 779aa382e..a5170d521 100644 --- a/priv/repo/migrations/20190710125158_add_following_address_from_source_data.exs +++ b/priv/repo/migrations/20190710125158_add_following_address_from_source_data.exs @@ -5,7 +5,11 @@ defmodule Pleroma.Repo.Migrations.AddFollowingAddressFromSourceData do def change do query = - User.external_users_query() + User.Query.build(%{ + external: true, + legacy_active: true, + order_by: :id + }) |> select([u], struct(u, [:id, :ap_id, :info])) Pleroma.Repo.stream(query) diff --git a/priv/repo/migrations/20190711042024_copy_muted_to_muted_notifications.exs b/priv/repo/migrations/20190711042024_copy_muted_to_muted_notifications.exs index bc4e828cc..dbddac516 100644 --- a/priv/repo/migrations/20190711042024_copy_muted_to_muted_notifications.exs +++ b/priv/repo/migrations/20190711042024_copy_muted_to_muted_notifications.exs @@ -1,6 +1,5 @@ defmodule Pleroma.Repo.Migrations.CopyMutedToMutedNotifications do use Ecto.Migration - alias Pleroma.User def change do execute( diff --git a/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs b/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs new file mode 100644 index 000000000..b26b122eb --- /dev/null +++ b/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs @@ -0,0 +1,54 @@ +defmodule Pleroma.Repo.Migrations.CopyUsersInfoaddsToUsers do + use Ecto.Migration + + def change do + alter table(:users) do + add(:banner, :map, default: %{}) + add(:background, :map, default: %{}) + add(:source_data, :map, default: %{}) + add(:note_count, :integer, default: 0) + add(:follower_count, :integer, default: 0) + # Should be filled in only for remote users + add(:following_count, :integer, default: nil) + add(:locked, :boolean, default: false) + add(:confirmation_pending, :boolean, default: false) + add(:password_reset_pending, :boolean, default: false) + add(:confirmation_token, :text, default: nil) + add(:default_scope, :string, default: "public") + add(:blocks, {:array, :text}, default: []) + add(:domain_blocks, {:array, :text}, default: []) + add(:mutes, {:array, :text}, default: []) + add(:muted_reblogs, {:array, :text}, default: []) + add(:muted_notifications, {:array, :text}, default: []) + add(:subscribers, {:array, :text}, default: []) + add(:deactivated, :boolean, default: false, null: false) + add(:no_rich_text, :boolean, default: false, null: false) + add(:ap_enabled, :boolean, default: false, null: false) + add(:is_moderator, :boolean, default: false, null: false) + add(:is_admin, :boolean, default: false, null: false) + add(:show_role, :boolean, default: true, null: false) + add(:settings, :map, default: nil) + add(:magic_key, :text, default: nil) + add(:uri, :text, default: nil) + add(:topic, :text, default: nil) + add(:hub, :text, default: nil) + add(:salmon, :text, default: nil) + add(:hide_followers_count, :boolean, default: false, null: false) + add(:hide_follows_count, :boolean, default: false, null: false) + add(:hide_followers, :boolean, default: false, null: false) + add(:hide_follows, :boolean, default: false, null: false) + add(:hide_favorites, :boolean, default: true, null: false) + add(:unread_conversation_count, :integer, default: 0) + add(:pinned_activities, {:array, :text}, default: []) + add(:email_notifications, :map, default: %{"digest" => false}) + add(:mascot, :map, default: nil) + add(:emoji, {:array, :map}, default: []) + add(:pleroma_settings_store, :map, default: %{}) + add(:fields, {:array, :map}, default: nil) + add(:raw_fields, {:array, :map}, default: []) + add(:discoverable, :boolean, default: false, null: false) + add(:notification_settings, :map, default: %{}) + add(:skip_thread_containment, :boolean, default: false, null: false) + end + end +end diff --git a/test/daemons/digest_email_daemon_test.exs b/test/daemons/digest_email_daemon_test.exs index 3168f3b9a..faf592d5f 100644 --- a/test/daemons/digest_email_daemon_test.exs +++ b/test/daemons/digest_email_daemon_test.exs @@ -20,7 +20,7 @@ defmodule Pleroma.DigestEmailDaemonTest do |> Timex.to_naive_datetime() user2 = insert(:user, last_digest_emailed_at: date) - User.switch_email_notifications(user2, "digest", true) + {:ok, _} = User.switch_email_notifications(user2, "digest", true) CommonAPI.post(user, %{"status" => "hey @#{user2.nickname}!"}) DigestEmailDaemon.perform() diff --git a/test/emails/user_email_test.exs b/test/emails/user_email_test.exs index 963565f7c..9e145977e 100644 --- a/test/emails/user_email_test.exs +++ b/test/emails/user_email_test.exs @@ -36,7 +36,7 @@ defmodule Pleroma.Emails.UserEmailTest do test "build account confirmation email" do config = Pleroma.Config.get(:instance) - user = insert(:user, info: %Pleroma.User.Info{confirmation_token: "conf-token"}) + user = insert(:user, confirmation_token: "conf-token") email = UserEmail.account_confirmation_email(user) assert email.from == {config[:name], config[:notify_email]} assert email.to == [{user.name, user.email}] diff --git a/test/formatter_test.exs b/test/formatter_test.exs index 3bff51527..087bdbcc2 100644 --- a/test/formatter_test.exs +++ b/test/formatter_test.exs @@ -125,10 +125,10 @@ defmodule Pleroma.FormatterTest do gsimg = insert(:user, %{nickname: "gsimg"}) archaeme = - insert(:user, %{ + insert(:user, nickname: "archa_eme_", - info: %User.Info{source_data: %{"url" => "https://archeme/@archa_eme_"}} - }) + source_data: %{"url" => "https://archeme/@archa_eme_"} + ) archaeme_remote = insert(:user, %{nickname: "archaeme@archae.me"}) diff --git a/test/moderation_log_test.exs b/test/moderation_log_test.exs index a39a00e02..6363db5aa 100644 --- a/test/moderation_log_test.exs +++ b/test/moderation_log_test.exs @@ -12,8 +12,8 @@ defmodule Pleroma.ModerationLogTest do describe "user moderation" do setup do - admin = insert(:user, info: %{is_admin: true}) - moderator = insert(:user, info: %{is_moderator: true}) + admin = insert(:user, is_admin: true) + moderator = insert(:user, is_moderator: true) subject1 = insert(:user) subject2 = insert(:user) diff --git a/test/notification_test.exs b/test/notification_test.exs index 54c0f9877..ddd7ae307 100644 --- a/test/notification_test.exs +++ b/test/notification_test.exs @@ -136,7 +136,7 @@ defmodule Pleroma.NotificationTest do test "it disables notifications from followers" do follower = insert(:user) - followed = insert(:user, info: %{notification_settings: %{"followers" => false}}) + followed = insert(:user, notification_settings: %{"followers" => false}) User.follow(follower, followed) {:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"}) refute Notification.create_notification(activity, followed) @@ -144,13 +144,13 @@ defmodule Pleroma.NotificationTest do test "it disables notifications from non-followers" do follower = insert(:user) - followed = insert(:user, info: %{notification_settings: %{"non_followers" => false}}) + followed = insert(:user, notification_settings: %{"non_followers" => false}) {:ok, activity} = CommonAPI.post(follower, %{"status" => "hey @#{followed.nickname}"}) refute Notification.create_notification(activity, followed) end test "it disables notifications from people the user follows" do - follower = insert(:user, info: %{notification_settings: %{"follows" => false}}) + follower = insert(:user, notification_settings: %{"follows" => false}) followed = insert(:user) User.follow(follower, followed) follower = Repo.get(User, follower.id) @@ -159,7 +159,7 @@ defmodule Pleroma.NotificationTest do end test "it disables notifications from people the user does not follow" do - follower = insert(:user, info: %{notification_settings: %{"non_follows" => false}}) + follower = insert(:user, notification_settings: %{"non_follows" => false}) followed = insert(:user) {:ok, activity} = CommonAPI.post(followed, %{"status" => "hey @#{follower.nickname}"}) refute Notification.create_notification(activity, follower) diff --git a/test/plugs/admin_secret_authentication_plug_test.exs b/test/plugs/admin_secret_authentication_plug_test.exs index e1d4b391f..c94a62c10 100644 --- a/test/plugs/admin_secret_authentication_plug_test.exs +++ b/test/plugs/admin_secret_authentication_plug_test.exs @@ -37,6 +37,6 @@ defmodule Pleroma.Plugs.AdminSecretAuthenticationPlugTest do %{conn | params: %{"admin_token" => "password123"}} |> AdminSecretAuthenticationPlug.call(%{}) - assert conn.assigns[:user].info.is_admin + assert conn.assigns[:user].is_admin end end diff --git a/test/plugs/user_enabled_plug_test.exs b/test/plugs/user_enabled_plug_test.exs index c0fafcab1..996a7d77b 100644 --- a/test/plugs/user_enabled_plug_test.exs +++ b/test/plugs/user_enabled_plug_test.exs @@ -17,7 +17,7 @@ defmodule Pleroma.Plugs.UserEnabledPlugTest do end test "with a user that is deactivated, it removes that user", %{conn: conn} do - user = insert(:user, info: %{deactivated: true}) + user = insert(:user, deactivated: true) conn = conn diff --git a/test/plugs/user_is_admin_plug_test.exs b/test/plugs/user_is_admin_plug_test.exs index 9e05fff18..136dcc54e 100644 --- a/test/plugs/user_is_admin_plug_test.exs +++ b/test/plugs/user_is_admin_plug_test.exs @@ -9,7 +9,7 @@ defmodule Pleroma.Plugs.UserIsAdminPlugTest do import Pleroma.Factory test "accepts a user that is admin" do - user = insert(:user, info: %{is_admin: true}) + user = insert(:user, is_admin: true) conn = build_conn() diff --git a/test/signature_test.exs b/test/signature_test.exs index 96c8ba07a..ada1b1054 100644 --- a/test/signature_test.exs +++ b/test/signature_test.exs @@ -42,7 +42,7 @@ defmodule Pleroma.SignatureTest do test "it returns key" do expected_result = {:ok, @rsa_public_key} - user = insert(:user, %{info: %{source_data: %{"publicKey" => @public_key}}}) + user = insert(:user, source_data: %{"publicKey" => @public_key}) assert Signature.fetch_public_key(make_fake_conn(user.ap_id)) == expected_result end @@ -54,7 +54,7 @@ defmodule Pleroma.SignatureTest do end test "it returns error if public key is empty" do - user = insert(:user, %{info: %{source_data: %{"publicKey" => %{}}}}) + user = insert(:user, source_data: %{"publicKey" => %{}}) assert Signature.fetch_public_key(make_fake_conn(user.ap_id)) == {:error, :error} end diff --git a/test/tasks/count_statuses_test.exs b/test/tasks/count_statuses_test.exs index 6035da3c3..bb5dc88f8 100644 --- a/test/tasks/count_statuses_test.exs +++ b/test/tasks/count_statuses_test.exs @@ -22,18 +22,18 @@ defmodule Mix.Tasks.Pleroma.CountStatusesTest do user = refresh_record(user) user2 = refresh_record(user2) - assert %{info: %{note_count: 2}} = user - assert %{info: %{note_count: 1}} = user2 + assert %{note_count: 2} = user + assert %{note_count: 1} = user2 - {:ok, user} = User.update_info(user, &User.Info.set_note_count(&1, 0)) - {:ok, user2} = User.update_info(user2, &User.Info.set_note_count(&1, 0)) + {:ok, user} = User.update_note_count(user, 0) + {:ok, user2} = User.update_note_count(user2, 0) - assert %{info: %{note_count: 0}} = user - assert %{info: %{note_count: 0}} = user2 + assert %{note_count: 0} = user + assert %{note_count: 0} = user2 assert capture_io(fn -> Mix.Tasks.Pleroma.CountStatuses.run([]) end) == "Done\n" - assert %{info: %{note_count: 2}} = refresh_record(user) - assert %{info: %{note_count: 1}} = refresh_record(user2) + assert %{note_count: 2} = refresh_record(user) + assert %{note_count: 1} = refresh_record(user2) end end diff --git a/test/tasks/database_test.exs b/test/tasks/database_test.exs index b63dcac00..b66324e5e 100644 --- a/test/tasks/database_test.exs +++ b/test/tasks/database_test.exs @@ -72,26 +72,25 @@ defmodule Mix.Tasks.Pleroma.DatabaseTest do describe "running update_users_following_followers_counts" do test "following and followers count are updated" do [user, user2] = insert_pair(:user) - {:ok, %User{following: following, info: info} = user} = User.follow(user, user2) + {:ok, %User{following: following} = user} = User.follow(user, user2) assert length(following) == 2 - assert info.follower_count == 0 + assert user.follower_count == 0 {:ok, user} = user - |> Ecto.Changeset.change(%{following: following ++ following}) - |> User.change_info(&Ecto.Changeset.change(&1, %{follower_count: 3})) + |> Ecto.Changeset.change(%{following: following ++ following, follower_count: 3}) |> Repo.update() assert length(user.following) == 4 - assert user.info.follower_count == 3 + assert user.follower_count == 3 assert :ok == Mix.Tasks.Pleroma.Database.run(["update_users_following_followers_counts"]) user = User.get_by_id(user.id) assert length(user.following) == 2 - assert user.info.follower_count == 0 + assert user.follower_count == 0 end end diff --git a/test/tasks/user_test.exs b/test/tasks/user_test.exs index cf12d9ed6..f024f92ae 100644 --- a/test/tasks/user_test.exs +++ b/test/tasks/user_test.exs @@ -58,8 +58,8 @@ defmodule Mix.Tasks.Pleroma.UserTest do assert user.name == unsaved.name assert user.email == unsaved.email assert user.bio == unsaved.bio - assert user.info.is_moderator - assert user.info.is_admin + assert user.is_moderator + assert user.is_admin end test "user is not created" do @@ -113,11 +113,11 @@ defmodule Mix.Tasks.Pleroma.UserTest do assert message =~ " deactivated" user = User.get_cached_by_nickname(user.nickname) - assert user.info.deactivated + assert user.deactivated end test "user is activated" do - user = insert(:user, info: %{deactivated: true}) + user = insert(:user, deactivated: true) Mix.Tasks.Pleroma.User.run(["toggle_activated", user.nickname]) @@ -125,7 +125,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do assert message =~ " activated" user = User.get_cached_by_nickname(user.nickname) - refute user.info.deactivated + refute user.deactivated end test "no user to toggle" do @@ -155,7 +155,7 @@ defmodule Mix.Tasks.Pleroma.UserTest do user = User.get_cached_by_nickname(user.nickname) assert Enum.empty?(user.following) - assert user.info.deactivated + assert user.deactivated end test "no user to unsubscribe" do @@ -182,13 +182,13 @@ defmodule Mix.Tasks.Pleroma.UserTest do assert message =~ ~r/Admin status .* true/ user = User.get_cached_by_nickname(user.nickname) - assert user.info.is_moderator - assert user.info.locked - assert user.info.is_admin + assert user.is_moderator + assert user.locked + assert user.is_admin end test "All statuses unset" do - user = insert(:user, info: %{is_moderator: true, locked: true, is_admin: true}) + user = insert(:user, locked: true, is_moderator: true, is_admin: true) Mix.Tasks.Pleroma.User.run([ "set", @@ -208,9 +208,9 @@ defmodule Mix.Tasks.Pleroma.UserTest do assert message =~ ~r/Admin status .* false/ user = User.get_cached_by_nickname(user.nickname) - refute user.info.is_moderator - refute user.info.locked - refute user.info.is_admin + refute user.is_moderator + refute user.locked + refute user.is_admin end test "no user to set status" do @@ -358,28 +358,28 @@ defmodule Mix.Tasks.Pleroma.UserTest do describe "running toggle_confirmed" do test "user is confirmed" do - %{id: id, nickname: nickname} = insert(:user, info: %{confirmation_pending: false}) + %{id: id, nickname: nickname} = insert(:user, confirmation_pending: false) assert :ok = Mix.Tasks.Pleroma.User.run(["toggle_confirmed", nickname]) assert_received {:mix_shell, :info, [message]} assert message == "#{nickname} needs confirmation." user = Repo.get(User, id) - assert user.info.confirmation_pending - assert user.info.confirmation_token + assert user.confirmation_pending + assert user.confirmation_token end test "user is not confirmed" do %{id: id, nickname: nickname} = - insert(:user, info: %{confirmation_pending: true, confirmation_token: "some token"}) + insert(:user, confirmation_pending: true, confirmation_token: "some token") assert :ok = Mix.Tasks.Pleroma.User.run(["toggle_confirmed", nickname]) assert_received {:mix_shell, :info, [message]} assert message == "#{nickname} doesn't need confirmation." user = Repo.get(User, id) - refute user.info.confirmation_pending - refute user.info.confirmation_token + refute user.confirmation_pending + refute user.confirmation_token end test "it prints an error message when user is not exist" do diff --git a/test/user_info_test.exs b/test/user_info_test.exs deleted file mode 100644 index 2d795594e..000000000 --- a/test/user_info_test.exs +++ /dev/null @@ -1,24 +0,0 @@ -defmodule Pleroma.UserInfoTest do - alias Pleroma.Repo - alias Pleroma.User.Info - - use Pleroma.DataCase - - import Pleroma.Factory - - describe "update_email_notifications/2" do - setup do - user = insert(:user, %{info: %{email_notifications: %{"digest" => true}}}) - - {:ok, user: user} - end - - test "Notifications are updated", %{user: user} do - true = user.info.email_notifications["digest"] - changeset = Info.update_email_notifications(user.info, %{"digest" => false}) - assert changeset.valid? - {:ok, result} = Ecto.Changeset.apply_action(changeset, :insert) - assert result.email_notifications["digest"] == false - end - end -end diff --git a/test/user_test.exs b/test/user_test.exs index 019e7b400..381d8ea27 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -68,7 +68,7 @@ defmodule Pleroma.UserTest do test "returns all pending follow requests" do unlocked = insert(:user) - locked = insert(:user, %{info: %{locked: true}}) + locked = insert(:user, locked: true) follower = insert(:user) CommonAPI.follow(follower, unlocked) @@ -81,7 +81,7 @@ defmodule Pleroma.UserTest do end test "doesn't return already accepted or duplicate follow requests" do - locked = insert(:user, %{info: %{locked: true}}) + locked = insert(:user, locked: true) pending_follower = insert(:user) accepted_follower = insert(:user) @@ -95,7 +95,7 @@ defmodule Pleroma.UserTest do end test "clears follow requests when requester is blocked" do - followed = insert(:user, %{info: %{locked: true}}) + followed = insert(:user, locked: true) follower = insert(:user) CommonAPI.follow(follower, followed) @@ -151,14 +151,14 @@ defmodule Pleroma.UserTest do user = User.get_cached_by_id(user.id) followed = User.get_cached_by_ap_id(followed.ap_id) - assert followed.info.follower_count == 1 + assert followed.follower_count == 1 assert User.ap_followers(followed) in user.following end test "can't follow a deactivated users" do user = insert(:user) - followed = insert(:user, info: %{deactivated: true}) + followed = insert(:user, %{deactivated: true}) {:error, _} = User.follow(user, followed) end @@ -182,8 +182,8 @@ defmodule Pleroma.UserTest do end test "local users do not automatically follow local locked accounts" do - follower = insert(:user, info: %{locked: true}) - followed = insert(:user, info: %{locked: true}) + follower = insert(:user, locked: true) + followed = insert(:user, locked: true) {:ok, follower} = User.maybe_direct_follow(follower, followed) @@ -400,8 +400,8 @@ defmodule Pleroma.UserTest do {:ok, user} = Repo.insert(changeset) - assert user.info.confirmation_pending - assert user.info.confirmation_token + assert user.confirmation_pending + assert user.confirmation_token end test "it creates confirmed user if :confirmed option is given" do @@ -410,8 +410,8 @@ defmodule Pleroma.UserTest do {:ok, user} = Repo.insert(changeset) - refute user.info.confirmation_pending - refute user.info.confirmation_token + refute user.confirmation_pending + refute user.confirmation_token end end @@ -505,7 +505,8 @@ defmodule Pleroma.UserTest do assert orig_user.last_refreshed_at == a_week_ago {:ok, user} = User.get_or_fetch_by_ap_id("http://mastodon.example.org/users/admin") - assert user.info.source_data["endpoints"] + + assert user.source_data["endpoints"] refute user.last_refreshed_at == orig_user.last_refreshed_at end @@ -611,63 +612,63 @@ defmodule Pleroma.UserTest do end describe "updating note and follower count" do - test "it sets the info->note_count property" do + test "it sets the note_count property" do note = insert(:note) user = User.get_cached_by_ap_id(note.data["actor"]) - assert user.info.note_count == 0 + assert user.note_count == 0 {:ok, user} = User.update_note_count(user) - assert user.info.note_count == 1 + assert user.note_count == 1 end - test "it increases the info->note_count property" do + test "it increases the note_count property" do note = insert(:note) user = User.get_cached_by_ap_id(note.data["actor"]) - assert user.info.note_count == 0 + assert user.note_count == 0 {:ok, user} = User.increase_note_count(user) - assert user.info.note_count == 1 + assert user.note_count == 1 {:ok, user} = User.increase_note_count(user) - assert user.info.note_count == 2 + assert user.note_count == 2 end - test "it decreases the info->note_count property" do + test "it decreases the note_count property" do note = insert(:note) user = User.get_cached_by_ap_id(note.data["actor"]) - assert user.info.note_count == 0 + assert user.note_count == 0 {:ok, user} = User.increase_note_count(user) - assert user.info.note_count == 1 + assert user.note_count == 1 {:ok, user} = User.decrease_note_count(user) - assert user.info.note_count == 0 + assert user.note_count == 0 {:ok, user} = User.decrease_note_count(user) - assert user.info.note_count == 0 + assert user.note_count == 0 end - test "it sets the info->follower_count property" do + test "it sets the follower_count property" do user = insert(:user) follower = insert(:user) User.follow(follower, user) - assert user.info.follower_count == 0 + assert user.follower_count == 0 {:ok, user} = User.update_follower_count(user) - assert user.info.follower_count == 1 + assert user.follower_count == 1 end end @@ -958,14 +959,14 @@ defmodule Pleroma.UserTest do describe ".deactivate" do test "can de-activate then re-activate a user" do user = insert(:user) - assert false == user.info.deactivated + assert false == user.deactivated {:ok, user} = User.deactivate(user) - assert true == user.info.deactivated + assert true == user.deactivated {:ok, user} = User.deactivate(user, false) - assert false == user.info.deactivated + assert false == user.deactivated end - test "hide a user from followers " do + test "hide a user from followers" do user = insert(:user) user2 = insert(:user) @@ -1041,7 +1042,7 @@ defmodule Pleroma.UserTest do end test "it deletes deactivated user" do - {:ok, user} = insert(:user, info: %{deactivated: true}) |> User.set_cache() + {:ok, user} = insert(:user, deactivated: true) |> User.set_cache() {:ok, job} = User.delete(user) {:ok, _user} = ObanHelpers.perform(job) @@ -1180,7 +1181,7 @@ defmodule Pleroma.UserTest do end test "html_filter_policy returns TwitterText scrubber when rich-text is disabled" do - user = insert(:user, %{info: %{no_rich_text: true}}) + user = insert(:user, no_rich_text: true) assert Pleroma.HTML.Scrubber.TwitterText == User.html_filter_policy(user) end @@ -1217,8 +1218,8 @@ defmodule Pleroma.UserTest do test "auth_active?/1 works correctly" do Pleroma.Config.put([:instance, :account_activation_required], true) - local_user = insert(:user, local: true, info: %{confirmation_pending: true}) - confirmed_user = insert(:user, local: true, info: %{confirmation_pending: false}) + local_user = insert(:user, local: true, confirmation_pending: true) + confirmed_user = insert(:user, local: true, confirmation_pending: false) remote_user = insert(:user, local: false) refute User.auth_active?(local_user) @@ -1235,20 +1236,20 @@ defmodule Pleroma.UserTest do test "returns false for remote users" do user = insert(:user, local: false) - remote_admin_user = insert(:user, local: false, info: %{is_admin: true}) + remote_admin_user = insert(:user, local: false, is_admin: true) refute User.superuser?(user) refute User.superuser?(remote_admin_user) end test "returns true for local moderators" do - user = insert(:user, local: true, info: %{is_moderator: true}) + user = insert(:user, local: true, is_moderator: true) assert User.superuser?(user) end test "returns true for local admins" do - user = insert(:user, local: true, info: %{is_admin: true}) + user = insert(:user, local: true, is_admin: true) assert User.superuser?(user) end @@ -1264,14 +1265,14 @@ defmodule Pleroma.UserTest do test "returns false when the account is unauthenticated and auth is required" do Pleroma.Config.put([:instance, :account_activation_required], true) - user = insert(:user, local: true, info: %{confirmation_pending: true}) + user = insert(:user, local: true, confirmation_pending: true) other_user = insert(:user, local: true) refute User.visible_for?(user, other_user) end test "returns true when the account is unauthenticated and auth is not required" do - user = insert(:user, local: true, info: %{confirmation_pending: true}) + user = insert(:user, local: true, confirmation_pending: true) other_user = insert(:user, local: true) assert User.visible_for?(user, other_user) @@ -1280,8 +1281,8 @@ defmodule Pleroma.UserTest do test "returns true when the account is unauthenticated and being viewed by a privileged account (auth required)" do Pleroma.Config.put([:instance, :account_activation_required], true) - user = insert(:user, local: true, info: %{confirmation_pending: true}) - other_user = insert(:user, local: true, info: %{is_admin: true}) + user = insert(:user, local: true, confirmation_pending: true) + other_user = insert(:user, local: true, is_admin: true) assert User.visible_for?(user, other_user) end @@ -1347,7 +1348,7 @@ defmodule Pleroma.UserTest do users = Enum.map(1..total, fn _ -> - insert(:user, last_digest_emailed_at: days_ago(20), info: %{deactivated: false}) + insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false) end) inactive_users_ids = @@ -1365,7 +1366,7 @@ defmodule Pleroma.UserTest do users = Enum.map(1..total, fn _ -> - insert(:user, last_digest_emailed_at: days_ago(20), info: %{deactivated: false}) + insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false) end) {inactive, active} = Enum.split(users, trunc(total / 2)) @@ -1398,7 +1399,7 @@ defmodule Pleroma.UserTest do users = Enum.map(1..total, fn _ -> - insert(:user, last_digest_emailed_at: days_ago(20), info: %{deactivated: false}) + insert(:user, last_digest_emailed_at: days_ago(20), deactivated: false) end) [sender | recipients] = users @@ -1438,19 +1439,19 @@ defmodule Pleroma.UserTest do describe "toggle_confirmation/1" do test "if user is confirmed" do - user = insert(:user, info: %{confirmation_pending: false}) + user = insert(:user, confirmation_pending: false) {:ok, user} = User.toggle_confirmation(user) - assert user.info.confirmation_pending - assert user.info.confirmation_token + assert user.confirmation_pending + assert user.confirmation_token end test "if user is unconfirmed" do - user = insert(:user, info: %{confirmation_pending: true, confirmation_token: "some token"}) + user = insert(:user, confirmation_pending: true, confirmation_token: "some token") {:ok, user} = User.toggle_confirmation(user) - refute user.info.confirmation_pending - refute user.info.confirmation_token + refute user.confirmation_pending + refute user.confirmation_token end end @@ -1486,7 +1487,7 @@ defmodule Pleroma.UserTest do user1 = insert(:user, local: false, ap_id: "http://localhost:4001/users/masto_closed") user2 = insert(:user, local: false, ap_id: "http://localhost:4001/users/fuser2") insert(:user, local: true) - insert(:user, local: false, info: %{deactivated: true}) + insert(:user, local: false, deactivated: true) {:ok, user1: user1, user2: user2} end @@ -1605,7 +1606,7 @@ defmodule Pleroma.UserTest do local: false, follower_address: "http://localhost:4001/users/masto_closed/followers", following_address: "http://localhost:4001/users/masto_closed/following", - info: %{ap_enabled: true} + ap_enabled: true ) assert User.user_info(other_user).following_count == 0 @@ -1628,7 +1629,7 @@ defmodule Pleroma.UserTest do local: false, follower_address: "http://localhost:4001/users/masto_closed/followers", following_address: "http://localhost:4001/users/masto_closed/following", - info: %{ap_enabled: true} + ap_enabled: true ) assert User.user_info(other_user).following_count == 0 @@ -1651,7 +1652,7 @@ defmodule Pleroma.UserTest do local: false, follower_address: "http://localhost:4001/users/masto_closed/followers", following_address: "http://localhost:4001/users/masto_closed/following", - info: %{ap_enabled: true} + ap_enabled: true ) assert User.user_info(other_user).following_count == 0 @@ -1691,41 +1692,6 @@ defmodule Pleroma.UserTest do end end - describe "set_password_reset_pending/2" do - setup do - [user: insert(:user)] - end - - test "sets password_reset_pending to true", %{user: user} do - %{password_reset_pending: password_reset_pending} = user.info - - refute password_reset_pending - - {:ok, %{info: %{password_reset_pending: password_reset_pending}}} = - User.force_password_reset(user) - - assert password_reset_pending - end - end - - test "change_info/2" do - user = insert(:user) - assert user.info.hide_follows == false - - changeset = User.change_info(user, &User.Info.profile_update(&1, %{hide_follows: true})) - assert changeset.changes.info.changes.hide_follows == true - end - - test "update_info/2" do - user = insert(:user) - assert user.info.hide_follows == false - - assert {:ok, _} = User.update_info(user, &User.Info.profile_update(&1, %{hide_follows: true})) - - assert %{info: %{hide_follows: true}} = Repo.get(User, user.id) - assert {:ok, %{info: %{hide_follows: true}}} = Cachex.get(:user_cache, "ap_id:#{user.ap_id}") - end - describe "get_cached_by_nickname_or_id" do setup do limit_to_local_content = Pleroma.Config.get([:instance, :limit_to_local_content]) @@ -1782,4 +1748,18 @@ defmodule Pleroma.UserTest do assert %User{} = User.get_cached_by_nickname_or_id(local_user.nickname) end end + + describe "update_email_notifications/2" do + setup do + user = insert(:user, email_notifications: %{"digest" => true}) + + {:ok, user: user} + end + + test "Notifications are updated", %{user: user} do + true = user.email_notifications["digest"] + assert {:ok, result} = User.update_email_notifications(user, %{"digest" => false}) + assert result.email_notifications["digest"] == false + end + end end diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs index 6a3e48b5e..4c666a0f2 100644 --- a/test/web/activity_pub/activity_pub_controller_test.exs +++ b/test/web/activity_pub/activity_pub_controller_test.exs @@ -683,7 +683,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do test "it returns returns a uri if the user has 'hide_followers' set", %{conn: conn} do user = insert(:user) - user_two = insert(:user, %{info: %{hide_followers: true}}) + user_two = insert(:user, hide_followers: true) User.follow(user, user_two) result = @@ -696,7 +696,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do test "it returns a 403 error on pages, if the user has 'hide_followers' set and the request is not authenticated", %{conn: conn} do - user = insert(:user, %{info: %{hide_followers: true}}) + user = insert(:user, hide_followers: true) result = conn @@ -708,7 +708,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do test "it renders the page, if the user has 'hide_followers' set and the request is authenticated with the same user", %{conn: conn} do - user = insert(:user, %{info: %{hide_followers: true}}) + user = insert(:user, hide_followers: true) other_user = insert(:user) {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user) @@ -764,7 +764,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do end test "it returns a uri if the user has 'hide_follows' set", %{conn: conn} do - user = insert(:user, %{info: %{hide_follows: true}}) + user = insert(:user, hide_follows: true) user_two = insert(:user) User.follow(user, user_two) @@ -778,7 +778,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do test "it returns a 403 error on pages, if the user has 'hide_follows' set and the request is not authenticated", %{conn: conn} do - user = insert(:user, %{info: %{hide_follows: true}}) + user = insert(:user, hide_follows: true) result = conn @@ -790,7 +790,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do test "it renders the page, if the user has 'hide_follows' set and the request is authenticated with the same user", %{conn: conn} do - user = insert(:user, %{info: %{hide_follows: true}}) + user = insert(:user, hide_follows: true) other_user = insert(:user) {:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user) diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index c9f2a92e7..44f66f40b 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -93,8 +93,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do {:ok, user} = ActivityPub.make_user_from_ap_id(user_id) assert user.ap_id == user_id assert user.nickname == "admin@mastodon.example.org" - assert user.info.source_data - assert user.info.ap_enabled + assert user.source_data + assert user.ap_enabled assert user.follower_address == "http://mastodon.example.org/users/admin/followers" end @@ -279,7 +279,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert activity.actor == user.ap_id user = User.get_cached_by_id(user.id) - assert user.info.note_count == 0 + assert user.note_count == 0 end test "can be fetched into a timeline" do @@ -342,7 +342,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do }) user = User.get_cached_by_id(user.id) - assert user.info.note_count == 2 + assert user.note_count == 2 end test "increases replies count" do @@ -1009,7 +1009,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do end test "decrements user note count only for public activities" do - user = insert(:user, info: %{note_count: 10}) + user = insert(:user, note_count: 10) {:ok, a1} = CommonAPI.post(User.get_cached_by_id(user.id), %{ @@ -1041,7 +1041,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do {:ok, _} = Object.normalize(a4) |> ActivityPub.delete() user = User.get_cached_by_id(user.id) - assert user.info.note_count == 10 + assert user.note_count == 10 end test "it creates a delete activity and checks that it is also sent to users mentioned by the deleted object" do @@ -1305,9 +1305,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do following_address: "http://localhost:4001/users/masto_closed/following" ) - {:ok, info} = ActivityPub.fetch_follow_information_for_user(user) - assert info.hide_followers == true - assert info.hide_follows == false + {:ok, follow_info} = ActivityPub.fetch_follow_information_for_user(user) + assert follow_info.hide_followers == true + assert follow_info.hide_follows == false end test "detects hidden follows" do @@ -1328,9 +1328,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do following_address: "http://localhost:4001/users/masto_closed/following" ) - {:ok, info} = ActivityPub.fetch_follow_information_for_user(user) - assert info.hide_followers == false - assert info.hide_follows == true + {:ok, follow_info} = ActivityPub.fetch_follow_information_for_user(user) + assert follow_info.hide_followers == false + assert follow_info.hide_follows == true end end end diff --git a/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs b/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs index 03dc299ec..b524fdd23 100644 --- a/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs +++ b/test/web/activity_pub/mrf/anti_link_spam_policy_test.exs @@ -35,7 +35,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do test "it allows posts without links" do user = insert(:user) - assert user.info.note_count == 0 + assert user.note_count == 0 message = @linkless_message @@ -47,7 +47,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do test "it disallows posts with links" do user = insert(:user) - assert user.info.note_count == 0 + assert user.note_count == 0 message = @linkful_message @@ -59,9 +59,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do describe "with old user" do test "it allows posts without links" do - user = insert(:user, info: %{note_count: 1}) + user = insert(:user, note_count: 1) - assert user.info.note_count == 1 + assert user.note_count == 1 message = @linkless_message @@ -71,9 +71,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do end test "it allows posts with links" do - user = insert(:user, info: %{note_count: 1}) + user = insert(:user, note_count: 1) - assert user.info.note_count == 1 + assert user.note_count == 1 message = @linkful_message @@ -85,9 +85,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do describe "with followed new user" do test "it allows posts without links" do - user = insert(:user, info: %{follower_count: 1}) + user = insert(:user, follower_count: 1) - assert user.info.follower_count == 1 + assert user.follower_count == 1 message = @linkless_message @@ -97,9 +97,9 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do end test "it allows posts with links" do - user = insert(:user, info: %{follower_count: 1}) + user = insert(:user, follower_count: 1) - assert user.info.follower_count == 1 + assert user.follower_count == 1 message = @linkful_message @@ -133,7 +133,7 @@ defmodule Pleroma.Web.ActivityPub.MRF.AntiLinkSpamPolicyTest do describe "with contentless-objects" do test "it does not reject them or error out" do - user = insert(:user, info: %{note_count: 1}) + user = insert(:user, note_count: 1) message = @response_message diff --git a/test/web/activity_pub/publisher_test.exs b/test/web/activity_pub/publisher_test.exs index df03b4008..e885e5a5a 100644 --- a/test/web/activity_pub/publisher_test.exs +++ b/test/web/activity_pub/publisher_test.exs @@ -27,7 +27,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do test "it returns sharedInbox for messages involving as:Public in to" do user = insert(:user, %{ - info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}} + source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}} }) activity = %Activity{ @@ -40,7 +40,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do test "it returns sharedInbox for messages involving as:Public in cc" do user = insert(:user, %{ - info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}} + source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}} }) activity = %Activity{ @@ -53,7 +53,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do test "it returns sharedInbox for messages involving multiple recipients in to" do user = insert(:user, %{ - info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}} + source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}} }) user_two = insert(:user) @@ -69,7 +69,7 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do test "it returns sharedInbox for messages involving multiple recipients in cc" do user = insert(:user, %{ - info: %{source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}}} + source_data: %{"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}} }) user_two = insert(:user) @@ -84,14 +84,12 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do test "it returns sharedInbox for messages involving multiple recipients in total" do user = - insert(:user, %{ - info: %{ - source_data: %{ - "inbox" => "http://example.com/personal-inbox", - "endpoints" => %{"sharedInbox" => "http://example.com/inbox"} - } + insert(:user, + source_data: %{ + "inbox" => "http://example.com/personal-inbox", + "endpoints" => %{"sharedInbox" => "http://example.com/inbox"} } - }) + ) user_two = insert(:user) @@ -104,14 +102,12 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do test "it returns inbox for messages involving single recipients in total" do user = - insert(:user, %{ - info: %{ - source_data: %{ - "inbox" => "http://example.com/personal-inbox", - "endpoints" => %{"sharedInbox" => "http://example.com/inbox"} - } + insert(:user, + source_data: %{ + "inbox" => "http://example.com/personal-inbox", + "endpoints" => %{"sharedInbox" => "http://example.com/inbox"} } - }) + ) activity = %Activity{ data: %{"to" => [user.ap_id], "cc" => []} @@ -241,10 +237,8 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do follower = insert(:user, local: false, - info: %{ - ap_enabled: true, - source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"} - } + source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"}, + ap_enabled: true ) actor = insert(:user, follower_address: follower.ap_id) @@ -278,19 +272,15 @@ defmodule Pleroma.Web.ActivityPub.PublisherTest do fetcher = insert(:user, local: false, - info: %{ - ap_enabled: true, - source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"} - } + source_data: %{"inbox" => "https://domain.com/users/nick1/inbox"}, + ap_enabled: true ) another_fetcher = insert(:user, local: false, - info: %{ - ap_enabled: true, - source_data: %{"inbox" => "https://domain2.com/users/nick1/inbox"} - } + source_data: %{"inbox" => "https://domain2.com/users/nick1/inbox"}, + ap_enabled: true ) actor = insert(:user) diff --git a/test/web/activity_pub/transmogrifier/follow_handling_test.exs b/test/web/activity_pub/transmogrifier/follow_handling_test.exs index 99ab573c5..75cfbea2e 100644 --- a/test/web/activity_pub/transmogrifier/follow_handling_test.exs +++ b/test/web/activity_pub/transmogrifier/follow_handling_test.exs @@ -58,7 +58,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier.FollowHandlingTest do end test "with locked accounts, it does not create a follow or an accept" do - user = insert(:user, info: %{locked: true}) + user = insert(:user, locked: true) data = File.read!("test/fixtures/mastodon-follow-activity.json") diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index 6c35a6f4d..0e36a18f5 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -148,7 +148,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do user = User.get_cached_by_ap_id(object_data["actor"]) - assert user.info.note_count == 1 + assert user.note_count == 1 end test "it works for incoming notices with hashtags" do @@ -585,7 +585,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do } ] - assert user.info.banner["url"] == [ + assert user.banner["url"] == [ %{ "href" => "https://cd.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png" @@ -604,7 +604,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do user = User.get_cached_by_ap_id(activity.actor) - assert User.Info.fields(user.info) == [ + assert User.fields(user) == [ %{"name" => "foo", "value" => "bar"}, %{"name" => "foo1", "value" => "bar1"} ] @@ -625,7 +625,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do user = User.get_cached_by_ap_id(user.ap_id) - assert User.Info.fields(user.info) == [ + assert User.fields(user) == [ %{"name" => "foo", "value" => "updated"}, %{"name" => "foo1", "value" => "updated"} ] @@ -643,7 +643,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do user = User.get_cached_by_ap_id(user.ap_id) - assert User.Info.fields(user.info) == [ + assert User.fields(user) == [ %{"name" => "foo", "value" => "updated"}, %{"name" => "foo1", "value" => "updated"} ] @@ -654,7 +654,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do user = User.get_cached_by_ap_id(user.ap_id) - assert User.Info.fields(user.info) == [] + assert User.fields(user) == [] end test "it works for incoming update activities which lock the account" do @@ -677,7 +677,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do {:ok, %Activity{data: data, local: false}} = Transmogrifier.handle_incoming(update_data) user = User.get_cached_by_ap_id(data["actor"]) - assert user.info.locked == true + assert user.locked == true end test "it works for incoming deletes" do @@ -918,7 +918,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do test "it works for incoming accepts which were orphaned" do follower = insert(:user) - followed = insert(:user, %{info: %User.Info{locked: true}}) + followed = insert(:user, locked: true) {:ok, follow_activity} = ActivityPub.follow(follower, followed) @@ -940,7 +940,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do test "it works for incoming accepts which are referenced by IRI only" do follower = insert(:user) - followed = insert(:user, %{info: %User.Info{locked: true}}) + followed = insert(:user, locked: true) {:ok, follow_activity} = ActivityPub.follow(follower, followed) @@ -960,7 +960,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do test "it fails for incoming accepts which cannot be correlated" do follower = insert(:user) - followed = insert(:user, %{info: %User.Info{locked: true}}) + followed = insert(:user, locked: true) accept_data = File.read!("test/fixtures/mastodon-accept-activity.json") @@ -979,7 +979,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do test "it fails for incoming rejects which cannot be correlated" do follower = insert(:user) - followed = insert(:user, %{info: %User.Info{locked: true}}) + followed = insert(:user, locked: true) accept_data = File.read!("test/fixtures/mastodon-reject-activity.json") @@ -998,7 +998,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do test "it works for incoming rejects which are orphaned" do follower = insert(:user) - followed = insert(:user, %{info: %User.Info{locked: true}}) + followed = insert(:user, locked: true) {:ok, follower} = User.follow(follower, followed) {:ok, _follow_activity} = ActivityPub.follow(follower, followed) @@ -1024,7 +1024,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do test "it works for incoming rejects which are referenced by IRI only" do follower = insert(:user) - followed = insert(:user, %{info: %User.Info{locked: true}}) + followed = insert(:user, locked: true) {:ok, follower} = User.follow(follower, followed) {:ok, follow_activity} = ActivityPub.follow(follower, followed) @@ -1326,18 +1326,18 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do assert "http://localhost:4001/users/rye@niu.moe/followers" in activity.recipients user = User.get_cached_by_id(user.id) - assert user.info.note_count == 1 + assert user.note_count == 1 {:ok, user} = Transmogrifier.upgrade_user_from_ap_id("https://niu.moe/users/rye") ObanHelpers.perform_all() - assert user.info.ap_enabled - assert user.info.note_count == 1 + assert user.ap_enabled + assert user.note_count == 1 assert user.follower_address == "https://niu.moe/users/rye/followers" assert user.following_address == "https://niu.moe/users/rye/following" user = User.get_cached_by_id(user.id) - assert user.info.note_count == 1 + assert user.note_count == 1 activity = Activity.get_by_id(activity.id) assert user.follower_address in activity.recipients @@ -1358,7 +1358,7 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do "https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png" } ] - } = user.info.banner + } = user.banner refute "..." in activity.recipients diff --git a/test/web/activity_pub/utils_test.exs b/test/web/activity_pub/utils_test.exs index c57ea7eb9..c1b000fac 100644 --- a/test/web/activity_pub/utils_test.exs +++ b/test/web/activity_pub/utils_test.exs @@ -297,7 +297,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do describe "update_follow_state_for_all/2" do test "updates the state of all Follow activities with the same actor and object" do - user = insert(:user, info: %{locked: true}) + user = insert(:user, locked: true) follower = insert(:user) {:ok, follow_activity} = ActivityPub.follow(follower, user) @@ -321,7 +321,7 @@ defmodule Pleroma.Web.ActivityPub.UtilsTest do describe "update_follow_state/2" do test "updates the state of the given follow activity" do - user = insert(:user, info: %{locked: true}) + user = insert(:user, locked: true) follower = insert(:user) {:ok, follow_activity} = ActivityPub.follow(follower, user) diff --git a/test/web/activity_pub/views/user_view_test.exs b/test/web/activity_pub/views/user_view_test.exs index 3155749aa..42918cf2f 100644 --- a/test/web/activity_pub/views/user_view_test.exs +++ b/test/web/activity_pub/views/user_view_test.exs @@ -29,7 +29,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do {:ok, user} = insert(:user) - |> User.upgrade_changeset(%{info: %{fields: fields}}) + |> User.upgrade_changeset(%{fields: fields}) |> User.update_and_set_cache() assert %{ @@ -38,7 +38,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do end test "Renders with emoji tags" do - user = insert(:user, %{info: %{emoji: [%{"bib" => "/test"}]}}) + user = insert(:user, emoji: [%{"bib" => "/test"}]) assert %{ "tag" => [ @@ -64,9 +64,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do user = insert(:user, avatar: %{"url" => [%{"href" => "https://someurl"}]}, - info: %{ - banner: %{"url" => [%{"href" => "https://somebanner"}]} - } + banner: %{"url" => [%{"href" => "https://somebanner"}]} ) {:ok, user} = User.ensure_keys_present(user) @@ -121,8 +119,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do other_user = insert(:user) {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user) assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user}) - info = Map.merge(user.info, %{hide_followers_count: true, hide_followers: true}) - user = Map.put(user, :info, info) + user = Map.merge(user, %{hide_followers_count: true, hide_followers: true}) assert %{"totalItems" => 0} = UserView.render("followers.json", %{user: user}) end @@ -131,8 +128,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do other_user = insert(:user) {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user) assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user}) - info = Map.merge(user.info, %{hide_followers_count: false, hide_followers: true}) - user = Map.put(user, :info, info) + user = Map.merge(user, %{hide_followers_count: false, hide_followers: true}) assert %{"totalItems" => 1} = UserView.render("followers.json", %{user: user}) end end @@ -143,8 +139,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do other_user = insert(:user) {:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user) assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user}) - info = Map.merge(user.info, %{hide_follows_count: true, hide_follows: true}) - user = Map.put(user, :info, info) + user = Map.merge(user, %{hide_follows_count: true, hide_follows: true}) assert %{"totalItems" => 0} = UserView.render("following.json", %{user: user}) end @@ -153,8 +148,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do other_user = insert(:user) {:ok, user, _other_user, _activity} = CommonAPI.follow(user, other_user) assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user}) - info = Map.merge(user.info, %{hide_follows_count: false, hide_follows: true}) - user = Map.put(user, :info, info) + user = Map.merge(user, %{hide_follows_count: false, hide_follows: true}) assert %{"totalItems" => 1} = UserView.render("following.json", %{user: user}) end end diff --git a/test/web/admin_api/admin_api_controller_test.exs b/test/web/admin_api/admin_api_controller_test.exs index b5c355e66..a1027e2e2 100644 --- a/test/web/admin_api/admin_api_controller_test.exs +++ b/test/web/admin_api/admin_api_controller_test.exs @@ -19,7 +19,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "/api/pleroma/admin/users" do test "Delete" do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) user = insert(:user) conn = @@ -40,7 +40,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "Create" do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) conn = build_conn() @@ -70,7 +70,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "Cannot create user with exisiting email" do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) user = insert(:user) conn = @@ -101,7 +101,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "Cannot create user with exisiting nickname" do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) user = insert(:user) conn = @@ -132,7 +132,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "Multiple user creation works in transaction" do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) user = insert(:user) conn = @@ -181,7 +181,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "/api/pleroma/admin/users/:nickname" do test "Show", %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) user = insert(:user) conn = @@ -204,7 +204,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "when the user doesn't exist", %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) user = build(:user) conn = @@ -218,7 +218,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "/api/pleroma/admin/users/follow" do test "allows to force-follow another user" do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) user = insert(:user) follower = insert(:user) @@ -244,7 +244,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "/api/pleroma/admin/users/unfollow" do test "allows to force-unfollow another user" do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) user = insert(:user) follower = insert(:user) @@ -272,7 +272,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "PUT /api/pleroma/admin/users/tag" do setup do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) user1 = insert(:user, %{tags: ["x"]}) user2 = insert(:user, %{tags: ["y"]}) user3 = insert(:user, %{tags: ["unchanged"]}) @@ -321,7 +321,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "DELETE /api/pleroma/admin/users/tag" do setup do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) user1 = insert(:user, %{tags: ["x"]}) user2 = insert(:user, %{tags: ["y", "z"]}) user3 = insert(:user, %{tags: ["unchanged"]}) @@ -370,7 +370,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "/api/pleroma/admin/users/:nickname/permission_group" do test "GET is giving user_info" do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) conn = build_conn() @@ -385,7 +385,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "/:right POST, can add to a permission group" do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) user = insert(:user) conn = @@ -405,8 +405,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "/:right DELETE, can remove from a permission group" do - admin = insert(:user, info: %{is_admin: true}) - user = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) + user = insert(:user, is_admin: true) conn = build_conn() @@ -427,7 +427,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "PUT /api/pleroma/admin/users/:nickname/activation_status" do setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) conn = conn @@ -445,7 +445,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do |> put("/api/pleroma/admin/users/#{user.nickname}/activation_status", %{status: false}) user = User.get_cached_by_id(user.id) - assert user.info.deactivated == true + assert user.deactivated == true assert json_response(conn, :no_content) log_entry = Repo.one(ModerationLog) @@ -455,14 +455,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "activates the user", %{conn: conn, admin: admin} do - user = insert(:user, info: %{deactivated: true}) + user = insert(:user, deactivated: true) conn = conn |> put("/api/pleroma/admin/users/#{user.nickname}/activation_status", %{status: true}) user = User.get_cached_by_id(user.id) - assert user.info.deactivated == false + assert user.deactivated == false assert json_response(conn, :no_content) log_entry = Repo.one(ModerationLog) @@ -485,7 +485,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "POST /api/pleroma/admin/email_invite, with valid config" do setup do - [user: insert(:user, info: %{is_admin: true})] + [user: insert(:user, is_admin: true)] end clear_config([:instance, :registrations_open]) do @@ -545,7 +545,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "POST /api/pleroma/admin/users/email_invite, with invalid config" do setup do - [user: insert(:user, info: %{is_admin: true})] + [user: insert(:user, is_admin: true)] end clear_config([:instance, :registrations_open]) @@ -577,7 +577,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "/api/pleroma/admin/users/:nickname/password_reset" do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) user = insert(:user) conn = @@ -593,7 +593,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "GET /api/pleroma/admin/users" do setup do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) conn = build_conn() @@ -609,7 +609,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do users = [ %{ - "deactivated" => admin.info.deactivated, + "deactivated" => admin.deactivated, "id" => admin.id, "nickname" => admin.nickname, "roles" => %{"admin" => true, "moderator" => false}, @@ -619,7 +619,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "display_name" => HTML.strip_tags(admin.name || admin.nickname) }, %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, @@ -660,7 +660,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 50, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, @@ -684,7 +684,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 50, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, @@ -708,7 +708,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 50, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, @@ -732,7 +732,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 50, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, @@ -756,7 +756,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 50, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, @@ -780,7 +780,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 1, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, @@ -799,7 +799,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 1, "users" => [ %{ - "deactivated" => user2.info.deactivated, + "deactivated" => user2.deactivated, "id" => user2.id, "nickname" => user2.nickname, "roles" => %{"admin" => false, "moderator" => false}, @@ -813,7 +813,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "only local users" do - admin = insert(:user, info: %{is_admin: true}, nickname: "john") + admin = insert(:user, is_admin: true, nickname: "john") user = insert(:user, nickname: "bob") insert(:user, nickname: "bobb", local: false) @@ -828,7 +828,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 50, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, @@ -842,7 +842,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "only local users with no query", %{admin: old_admin} do - admin = insert(:user, info: %{is_admin: true}, nickname: "john") + admin = insert(:user, is_admin: true, nickname: "john") user = insert(:user, nickname: "bob") insert(:user, nickname: "bobb", local: false) @@ -855,7 +855,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do users = [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, @@ -865,7 +865,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "display_name" => HTML.strip_tags(user.name || user.nickname) }, %{ - "deactivated" => admin.info.deactivated, + "deactivated" => admin.deactivated, "id" => admin.id, "nickname" => admin.nickname, "roles" => %{"admin" => true, "moderator" => false}, @@ -895,7 +895,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "load only admins", %{conn: conn, admin: admin} do - second_admin = insert(:user, info: %{is_admin: true}) + second_admin = insert(:user, is_admin: true) insert(:user) insert(:user) @@ -934,7 +934,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "load only moderators", %{conn: conn} do - moderator = insert(:user, info: %{is_moderator: true}) + moderator = insert(:user, is_moderator: true) insert(:user) insert(:user) @@ -999,11 +999,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "it works with multiple filters" do - admin = insert(:user, nickname: "john", info: %{is_admin: true}) - user = insert(:user, nickname: "bob", local: false, info: %{deactivated: true}) + admin = insert(:user, nickname: "john", is_admin: true) + user = insert(:user, nickname: "bob", local: false, deactivated: true) - insert(:user, nickname: "ken", local: true, info: %{deactivated: true}) - insert(:user, nickname: "bobb", local: false, info: %{deactivated: false}) + insert(:user, nickname: "ken", local: true, deactivated: true) + insert(:user, nickname: "bobb", local: false, deactivated: false) conn = build_conn() @@ -1015,7 +1015,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do "page_size" => 50, "users" => [ %{ - "deactivated" => user.info.deactivated, + "deactivated" => user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, @@ -1030,7 +1030,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) user = insert(:user) conn = @@ -1040,7 +1040,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do assert json_response(conn, 200) == %{ - "deactivated" => !user.info.deactivated, + "deactivated" => !user.deactivated, "id" => user.id, "nickname" => user.nickname, "roles" => %{"admin" => false, "moderator" => false}, @@ -1058,7 +1058,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "POST /api/pleroma/admin/users/invite_token" do setup do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) conn = build_conn() @@ -1122,7 +1122,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "GET /api/pleroma/admin/users/invites" do setup do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) conn = build_conn() @@ -1160,7 +1160,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "POST /api/pleroma/admin/users/revoke_invite" do test "with token" do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) {:ok, invite} = UserInviteToken.create_invite() conn = @@ -1180,7 +1180,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do end test "with invalid token" do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) conn = build_conn() @@ -1193,7 +1193,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "GET /api/pleroma/admin/reports/:id" do setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) %{conn: assign(conn, :user, admin)} end @@ -1226,7 +1226,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "PUT /api/pleroma/admin/reports/:id" do setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) [reporter, target_user] = insert_pair(:user) activity = insert(:note_activity, user: target_user) @@ -1287,7 +1287,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "GET /api/pleroma/admin/reports" do setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) %{conn: assign(conn, :user, admin)} end @@ -1407,7 +1407,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do # describe "POST /api/pleroma/admin/reports/:id/respond" do setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) %{conn: assign(conn, :user, admin), admin: admin} end @@ -1462,7 +1462,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "PUT /api/pleroma/admin/statuses/:id" do setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) activity = insert(:note_activity) %{conn: assign(conn, :user, admin), id: activity.id, admin: admin} @@ -1528,7 +1528,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "DELETE /api/pleroma/admin/statuses/:id" do setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) activity = insert(:note_activity) %{conn: assign(conn, :user, admin), id: activity.id, admin: admin} @@ -1558,7 +1558,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "GET /api/pleroma/admin/config" do setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) %{conn: assign(conn, :user, admin)} end @@ -1595,7 +1595,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "POST /api/pleroma/admin/config" do setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) temp_file = "config/test.exported_from_db.secret.exs" @@ -2163,7 +2163,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "config mix tasks run" do setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) temp_file = "config/test.exported_from_db.secret.exs" @@ -2199,7 +2199,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "GET /api/pleroma/admin/users/:nickname/statuses" do setup do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) user = insert(:user) date1 = (DateTime.to_unix(DateTime.utc_now()) + 2000) |> DateTime.from_unix!() @@ -2256,8 +2256,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "GET /api/pleroma/admin/moderation_log" do setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) - moderator = insert(:user, info: %{is_moderator: true}) + admin = insert(:user, is_admin: true) + moderator = insert(:user, is_moderator: true) %{conn: assign(conn, :user, admin), admin: admin, moderator: moderator} end @@ -2465,14 +2465,14 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do describe "PATCH /users/:nickname/force_password_reset" do setup %{conn: conn} do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) user = insert(:user) %{conn: assign(conn, :user, admin), admin: admin, user: user} end test "sets password_reset_pending to true", %{admin: admin, user: user} do - assert user.info.password_reset_pending == false + assert user.password_reset_pending == false conn = build_conn() @@ -2483,7 +2483,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do ObanHelpers.perform_all() - assert User.get_by_id(user.id).info.password_reset_pending == true + assert User.get_by_id(user.id).password_reset_pending == true end end end diff --git a/test/web/admin_api/search_test.exs b/test/web/admin_api/search_test.exs index 9df4cd539..082e691c4 100644 --- a/test/web/admin_api/search_test.exs +++ b/test/web/admin_api/search_test.exs @@ -47,9 +47,9 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do end test "it returns active/deactivated users" do - insert(:user, info: %{deactivated: true}) - insert(:user, info: %{deactivated: true}) - insert(:user, info: %{deactivated: false}) + insert(:user, deactivated: true) + insert(:user, deactivated: true) + insert(:user, deactivated: false) {:ok, _results, active_count} = Search.user(%{ @@ -70,7 +70,7 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do test "it returns specific user" do insert(:user) insert(:user) - user = insert(:user, nickname: "bob", local: true, info: %{deactivated: false}) + user = insert(:user, nickname: "bob", local: true, deactivated: false) {:ok, _results, total_count} = Search.user(%{query: ""}) @@ -108,7 +108,7 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do end test "it returns admin user" do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) insert(:user) insert(:user) @@ -119,7 +119,7 @@ defmodule Pleroma.Web.AdminAPI.SearchTest do end test "it returns moderator user" do - moderator = insert(:user, info: %{is_moderator: true}) + moderator = insert(:user, is_moderator: true) insert(:user) insert(:user) diff --git a/test/web/admin_api/views/report_view_test.exs b/test/web/admin_api/views/report_view_test.exs index 475705857..ef4a806e4 100644 --- a/test/web/admin_api/views/report_view_test.exs +++ b/test/web/admin_api/views/report_view_test.exs @@ -49,6 +49,8 @@ defmodule Pleroma.Web.AdminAPI.ReportViewTest do {:ok, report_activity} = CommonAPI.report(user, %{"account_id" => other_user.id, "status_ids" => [activity.id]}) + other_user = Pleroma.User.get_by_id(other_user.id) + expected = %{ content: nil, actor: diff --git a/test/web/common_api/common_api_test.exs b/test/web/common_api/common_api_test.exs index 83df44c36..1d2f20617 100644 --- a/test/web/common_api/common_api_test.exs +++ b/test/web/common_api/common_api_test.exs @@ -100,7 +100,7 @@ defmodule Pleroma.Web.CommonAPITest do {:ok, activity} = CommonAPI.update(user) user = User.get_cached_by_ap_id(user.ap_id) - [firefox] = user.info.source_data["tag"] + [firefox] = user.source_data["tag"] assert firefox["name"] == ":firefox:" @@ -291,7 +291,7 @@ defmodule Pleroma.Web.CommonAPITest do id = activity.id user = refresh_record(user) - assert %User{info: %{pinned_activities: [^id]}} = user + assert %User{pinned_activities: [^id]} = user end test "unlisted statuses can be pinned", %{user: user} do @@ -325,7 +325,7 @@ defmodule Pleroma.Web.CommonAPITest do user = refresh_record(user) - assert %User{info: %{pinned_activities: []}} = user + assert %User{pinned_activities: []} = user end test "should unpin when deleting a status", %{user: user, activity: activity} do @@ -337,7 +337,7 @@ defmodule Pleroma.Web.CommonAPITest do user = refresh_record(user) - assert %User{info: %{pinned_activities: []}} = user + assert %User{pinned_activities: []} = user end end @@ -468,7 +468,7 @@ defmodule Pleroma.Web.CommonAPITest do describe "accept_follow_request/2" do test "after acceptance, it sets all existing pending follow request states to 'accept'" do - user = insert(:user, info: %{locked: true}) + user = insert(:user, locked: true) follower = insert(:user) follower_two = insert(:user) @@ -488,7 +488,7 @@ defmodule Pleroma.Web.CommonAPITest do end test "after rejection, it sets all existing pending follow request states to 'reject'" do - user = insert(:user, info: %{locked: true}) + user = insert(:user, locked: true) follower = insert(:user) follower_two = insert(:user) diff --git a/test/web/federator_test.exs b/test/web/federator_test.exs index 43a715706..776cfa22f 100644 --- a/test/web/federator_test.exs +++ b/test/web/federator_test.exs @@ -81,14 +81,16 @@ defmodule Pleroma.Web.FederatorTest do local: false, nickname: "nick1@domain.com", ap_id: "https://domain.com/users/nick1", - info: %{ap_enabled: true, source_data: %{"inbox" => inbox1}} + source_data: %{"inbox" => inbox1}, + ap_enabled: true }) insert(:user, %{ local: false, nickname: "nick2@domain2.com", ap_id: "https://domain2.com/users/nick2", - info: %{ap_enabled: true, source_data: %{"inbox" => inbox2}} + source_data: %{"inbox" => inbox2}, + ap_enabled: true }) dt = NaiveDateTime.utc_now() @@ -162,7 +164,7 @@ defmodule Pleroma.Web.FederatorTest do local: false, nickname: "nick1@domain.com", ap_id: "https://domain.com/users/nick1", - info: %{salmon: "https://domain.com/salmon"} + salmon: "https://domain.com/salmon" }) remote_user2 = @@ -170,7 +172,7 @@ defmodule Pleroma.Web.FederatorTest do local: false, nickname: "nick2@domain2.com", ap_id: "https://domain2.com/users/nick2", - info: %{salmon: "https://domain2.com/salmon"} + salmon: "https://domain2.com/salmon" }) remote_user2_id = remote_user2.id diff --git a/test/web/masto_fe_controller_test.exs b/test/web/masto_fe_controller_test.exs index ab9dab352..b5dbd4a25 100644 --- a/test/web/masto_fe_controller_test.exs +++ b/test/web/masto_fe_controller_test.exs @@ -23,7 +23,7 @@ defmodule Pleroma.Web.MastodonAPI.MastoFEController do assert _result = json_response(conn, 200) user = User.get_cached_by_ap_id(user.ap_id) - assert user.info.settings == %{"programming" => "socks"} + assert user.settings == %{"programming" => "socks"} end describe "index/2 redirections" do diff --git a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs index 618031b40..519b56d6c 100644 --- a/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs +++ b/test/web/mastodon_api/controllers/account_controller/update_credentials_test.exs @@ -153,7 +153,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController.UpdateCredentialsTest do |> json_response(200) assert response["pleroma"]["skip_thread_containment"] == true - assert refresh_record(user).info.skip_thread_containment + assert refresh_record(user).skip_thread_containment end test "updates the user's hide_follows status", %{conn: conn} do diff --git a/test/web/mastodon_api/controllers/account_controller_test.exs b/test/web/mastodon_api/controllers/account_controller_test.exs index 6a59c3d94..a4bec2248 100644 --- a/test/web/mastodon_api/controllers/account_controller_test.exs +++ b/test/web/mastodon_api/controllers/account_controller_test.exs @@ -255,7 +255,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do test "getting followers, hide_followers", %{conn: conn} do user = insert(:user) - other_user = insert(:user, %{info: %{hide_followers: true}}) + other_user = insert(:user, hide_followers: true) {:ok, _user} = User.follow(user, other_user) conn = @@ -267,7 +267,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do test "getting followers, hide_followers, same user requesting", %{conn: conn} do user = insert(:user) - other_user = insert(:user, %{info: %{hide_followers: true}}) + other_user = insert(:user, hide_followers: true) {:ok, _user} = User.follow(user, other_user) conn = @@ -335,7 +335,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do end test "getting following, hide_follows", %{conn: conn} do - user = insert(:user, %{info: %{hide_follows: true}}) + user = insert(:user, hide_follows: true) other_user = insert(:user) {:ok, user} = User.follow(user, other_user) @@ -347,7 +347,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do end test "getting following, hide_follows, same user requesting", %{conn: conn} do - user = insert(:user, %{info: %{hide_follows: true}}) + user = insert(:user, hide_follows: true) other_user = insert(:user) {:ok, user} = User.follow(user, other_user) @@ -669,7 +669,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do token_from_db = Repo.preload(token_from_db, :user) assert token_from_db.user - assert token_from_db.user.info.confirmation_pending + assert token_from_db.user.confirmation_pending end test "returns error when user already registred", %{conn: conn, valid_params: valid_params} do @@ -713,7 +713,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do token_from_db = Repo.preload(token_from_db, :user) assert token_from_db.user - assert token_from_db.user.info.confirmation_pending + assert token_from_db.user.confirmation_pending end conn = @@ -798,7 +798,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do end test "verify_credentials default scope unlisted", %{conn: conn} do - user = insert(:user, %{info: %User.Info{default_scope: "unlisted"}}) + user = insert(:user, default_scope: "unlisted") conn = conn @@ -810,7 +810,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountControllerTest do end test "locked accounts", %{conn: conn} do - user = insert(:user, %{info: %User.Info{default_scope: "private"}}) + user = insert(:user, default_scope: "private") conn = conn diff --git a/test/web/mastodon_api/controllers/conversation_controller_test.exs b/test/web/mastodon_api/controllers/conversation_controller_test.exs index a308a7620..34b434f3f 100644 --- a/test/web/mastodon_api/controllers/conversation_controller_test.exs +++ b/test/web/mastodon_api/controllers/conversation_controller_test.exs @@ -17,7 +17,7 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do {:ok, user_two} = User.follow(user_two, user_one) - assert User.get_cached_by_id(user_two.id).info.unread_conversation_count == 0 + assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0 {:ok, direct} = CommonAPI.post(user_one, %{ @@ -25,7 +25,7 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do "visibility" => "direct" }) - assert User.get_cached_by_id(user_two.id).info.unread_conversation_count == 1 + assert User.get_cached_by_id(user_two.id).unread_conversation_count == 1 {:ok, _follower_only} = CommonAPI.post(user_one, %{ @@ -56,7 +56,7 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do assert is_binary(res_id) assert unread == true assert res_last_status["id"] == direct.id - assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 1 + assert User.get_cached_by_id(user_one.id).unread_conversation_count == 1 end test "updates the last_status on reply", %{conn: conn} do @@ -107,7 +107,7 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do |> post("/api/v1/conversations/#{direct_conversation_id}/read") |> json_response(200) - assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 0 + assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0 # The conversation is marked as unread on reply {:ok, _} = @@ -123,7 +123,7 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do |> get("/api/v1/conversations") |> json_response(200) - assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 1 + assert User.get_cached_by_id(user_one.id).unread_conversation_count == 1 # A reply doesn't increment the user's unread_conversation_count if the conversation is unread {:ok, _} = @@ -133,7 +133,7 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do "in_reply_to_status_id" => direct.id }) - assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 1 + assert User.get_cached_by_id(user_one.id).unread_conversation_count == 1 end test "(vanilla) Mastodon frontend behaviour", %{conn: conn} do diff --git a/test/web/mastodon_api/controllers/follow_request_controller_test.exs b/test/web/mastodon_api/controllers/follow_request_controller_test.exs index 4bf292df5..913f8c038 100644 --- a/test/web/mastodon_api/controllers/follow_request_controller_test.exs +++ b/test/web/mastodon_api/controllers/follow_request_controller_test.exs @@ -12,7 +12,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do describe "locked accounts" do test "/api/v1/follow_requests works" do - user = insert(:user, %{info: %User.Info{locked: true}}) + user = insert(:user, locked: true) other_user = insert(:user) {:ok, _activity} = ActivityPub.follow(other_user, user) @@ -32,7 +32,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do end test "/api/v1/follow_requests/:id/authorize works" do - user = insert(:user, %{info: %User.Info{locked: true}}) + user = insert(:user, locked: true) other_user = insert(:user) {:ok, _activity} = ActivityPub.follow(other_user, user) @@ -57,7 +57,7 @@ defmodule Pleroma.Web.MastodonAPI.FollowRequestControllerTest do end test "/api/v1/follow_requests/:id/reject works" do - user = insert(:user, %{info: %User.Info{locked: true}}) + user = insert(:user, locked: true) other_user = insert(:user) {:ok, _activity} = ActivityPub.follow(other_user, user) diff --git a/test/web/mastodon_api/controllers/instance_controller_test.exs b/test/web/mastodon_api/controllers/instance_controller_test.exs index f8049f81f..e00de6b18 100644 --- a/test/web/mastodon_api/controllers/instance_controller_test.exs +++ b/test/web/mastodon_api/controllers/instance_controller_test.exs @@ -41,20 +41,13 @@ defmodule Pleroma.Web.MastodonAPI.InstanceControllerTest do user = insert(:user, %{local: true}) user2 = insert(:user, %{local: true}) - {:ok, _user2} = User.deactivate(user2, !user2.info.deactivated) + {:ok, _user2} = User.deactivate(user2, !user2.deactivated) insert(:user, %{local: false, nickname: "u@peer1.com"}) insert(:user, %{local: false, nickname: "u@peer2.com"}) {:ok, _} = Pleroma.Web.CommonAPI.post(user, %{"status" => "cofe"}) - # Stats should count users with missing or nil `info.deactivated` value - - {:ok, _user} = - user.id - |> User.get_cached_by_id() - |> User.update_info(&Ecto.Changeset.change(&1, %{deactivated: nil})) - Pleroma.Stats.force_update() conn = get(conn, "/api/v1/instance") diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs index 2de2725e0..10efb265b 100644 --- a/test/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/web/mastodon_api/controllers/status_controller_test.exs @@ -526,8 +526,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do test "when you're an admin or moderator", %{conn: conn} do activity1 = insert(:note_activity) activity2 = insert(:note_activity) - admin = insert(:user, info: %{is_admin: true}) - moderator = insert(:user, info: %{is_moderator: true}) + admin = insert(:user, is_admin: true) + moderator = insert(:user, is_moderator: true) res_conn = conn diff --git a/test/web/mastodon_api/mastodon_api_test.exs b/test/web/mastodon_api/mastodon_api_test.exs index 7fcb2bd55..561ef05aa 100644 --- a/test/web/mastodon_api/mastodon_api_test.exs +++ b/test/web/mastodon_api/mastodon_api_test.exs @@ -14,11 +14,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPITest do import Pleroma.Factory describe "follow/3" do - test "returns error when user deactivated" do + test "returns error when followed user is deactivated" do follower = insert(:user) - user = insert(:user, local: true, info: %{deactivated: true}) + user = insert(:user, local: true, deactivated: true) {:error, error} = MastodonAPI.follow(follower, user) - assert error == "Could not follow user: You are deactivated." + assert error == "Could not follow user: #{user.nickname} is deactivated." end test "following for user" do diff --git a/test/web/mastodon_api/views/account_view_test.exs b/test/web/mastodon_api/views/account_view_test.exs index b7a4938a6..8c13ac862 100644 --- a/test/web/mastodon_api/views/account_view_test.exs +++ b/test/web/mastodon_api/views/account_view_test.exs @@ -26,12 +26,10 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do user = insert(:user, %{ - info: %{ - note_count: 5, - follower_count: 3, - source_data: source_data, - background: background_image - }, + follower_count: 3, + note_count: 5, + source_data: source_data, + background: background_image, nickname: "shp@shitposter.club", name: ":karjalanpiirakka: shp", bio: "valid html", @@ -101,7 +99,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do "non_followers" => true } - privacy = user.info.default_scope + privacy = user.default_scope assert %{ pleroma: %{notification_settings: ^notification_settings}, @@ -112,7 +110,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do test "Represent a Service(bot) account" do user = insert(:user, %{ - info: %{note_count: 5, follower_count: 3, source_data: %{"type" => "Service"}}, + follower_count: 3, + note_count: 5, + source_data: %{"type" => "Service"}, nickname: "shp@shitposter.club", inserted_at: ~N[2017-08-15 15:47:06.597036] }) @@ -164,8 +164,8 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do end test "Represent a deactivated user for an admin" do - admin = insert(:user, %{info: %{is_admin: true}}) - deactivated_user = insert(:user, %{info: %{deactivated: true}}) + admin = insert(:user, is_admin: true) + deactivated_user = insert(:user, deactivated: true) represented = AccountView.render("show.json", %{user: deactivated_user, for: admin}) assert represented[:pleroma][:deactivated] == true end @@ -253,7 +253,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do test "represent a relationship for the user with a pending follow request" do user = insert(:user) - other_user = insert(:user, %{info: %User.Info{locked: true}}) + other_user = insert(:user, locked: true) {:ok, user, other_user, _} = CommonAPI.follow(user, other_user) user = User.get_cached_by_id(user.id) @@ -282,7 +282,9 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do test "represent an embedded relationship" do user = insert(:user, %{ - info: %{note_count: 5, follower_count: 0, source_data: %{"type" => "Service"}}, + follower_count: 0, + note_count: 5, + source_data: %{"type" => "Service"}, nickname: "shp@shitposter.club", inserted_at: ~N[2017-08-15 15:47:06.597036] }) @@ -352,7 +354,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do end test "returns the settings store if the requesting user is the represented user and it's requested specifically" do - user = insert(:user, %{info: %User.Info{pleroma_settings_store: %{fe: "test"}}}) + user = insert(:user, pleroma_settings_store: %{fe: "test"}) result = AccountView.render("show.json", %{user: user, for: user, with_pleroma_settings: true}) @@ -374,14 +376,13 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do describe "hiding follows/following" do test "shows when follows/followers stats are hidden and sets follow/follower count to 0" do - info = %{ - hide_followers: true, - hide_followers_count: true, - hide_follows: true, - hide_follows_count: true - } - - user = insert(:user, info: info) + user = + insert(:user, %{ + hide_followers: true, + hide_followers_count: true, + hide_follows: true, + hide_follows_count: true + }) other_user = insert(:user) {:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user) @@ -395,7 +396,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do end test "shows when follows/followers are hidden" do - user = insert(:user, info: %{hide_followers: true, hide_follows: true}) + user = insert(:user, hide_followers: true, hide_follows: true) other_user = insert(:user) {:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user) {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user) @@ -408,7 +409,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do end test "shows actual follower/following count to the account owner" do - user = insert(:user, info: %{hide_followers: true, hide_follows: true}) + user = insert(:user, hide_followers: true, hide_follows: true) other_user = insert(:user) {:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user) {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user) @@ -456,7 +457,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do end test "shows non-zero when follow requests are pending" do - user = insert(:user, %{info: %{locked: true}}) + user = insert(:user, locked: true) assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user}) @@ -468,7 +469,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do end test "decreases when accepting a follow request" do - user = insert(:user, %{info: %{locked: true}}) + user = insert(:user, locked: true) assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user}) @@ -485,7 +486,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do end test "decreases when rejecting a follow request" do - user = insert(:user, %{info: %{locked: true}}) + user = insert(:user, locked: true) assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user}) @@ -502,14 +503,14 @@ defmodule Pleroma.Web.MastodonAPI.AccountViewTest do end test "shows non-zero when historical unapproved requests are present" do - user = insert(:user, %{info: %{locked: true}}) + user = insert(:user, locked: true) assert %{locked: true} = AccountView.render("show.json", %{user: user, for: user}) other_user = insert(:user) {:ok, _other_user, user, _activity} = CommonAPI.follow(other_user, user) - {:ok, user} = User.update_info(user, &User.Info.user_upgrade(&1, %{locked: false})) + {:ok, user} = User.update_and_set_cache(user, %{locked: false}) assert %{locked: false, follow_requests_count: 1} = AccountView.render("show.json", %{user: user, for: user}) diff --git a/test/web/node_info_test.exs b/test/web/node_info_test.exs index e15a0bfff..a3281b25b 100644 --- a/test/web/node_info_test.exs +++ b/test/web/node_info_test.exs @@ -24,8 +24,8 @@ defmodule Pleroma.Web.NodeInfoTest do end test "nodeinfo shows staff accounts", %{conn: conn} do - moderator = insert(:user, %{local: true, info: %{is_moderator: true}}) - admin = insert(:user, %{local: true, info: %{is_admin: true}}) + moderator = insert(:user, local: true, is_moderator: true) + admin = insert(:user, local: true, is_admin: true) conn = conn diff --git a/test/web/oauth/oauth_controller_test.exs b/test/web/oauth/oauth_controller_test.exs index 41aaf6189..ad8d79083 100644 --- a/test/web/oauth/oauth_controller_test.exs +++ b/test/web/oauth/oauth_controller_test.exs @@ -780,8 +780,8 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do {:ok, user} = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password)) - |> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true)) - |> Repo.update() + |> User.confirmation_changeset(need_confirmation: true) + |> User.update_and_set_cache() refute Pleroma.User.auth_active?(user) @@ -808,7 +808,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password), - info: %{deactivated: true} + deactivated: true ) app = insert(:oauth_app) @@ -834,7 +834,7 @@ defmodule Pleroma.Web.OAuth.OAuthControllerTest do user = insert(:user, password_hash: Comeonin.Pbkdf2.hashpwsalt(password), - info: %{password_reset_pending: true} + password_reset_pending: true ) app = insert(:oauth_app, scopes: ["read", "write"]) diff --git a/test/web/ostatus/ostatus_controller_test.exs b/test/web/ostatus/ostatus_controller_test.exs index b1af918d8..376446f93 100644 --- a/test/web/ostatus/ostatus_controller_test.exs +++ b/test/web/ostatus/ostatus_controller_test.exs @@ -51,7 +51,7 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do end) =~ "[error]" # Wrong key - info = %{ + update_params = %{ magic_key: "RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwrong1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB" } @@ -59,7 +59,8 @@ defmodule Pleroma.Web.OStatus.OStatusControllerTest do # Set a wrong magic-key for a user so it has to refetch "http://gs.example.org:4040/index.php/user/1" |> User.get_cached_by_ap_id() - |> User.update_info(&User.Info.remote_user_creation(&1, info)) + |> User.update_changeset(update_params) + |> User.update_and_set_cache() assert capture_log(fn -> conn = diff --git a/test/web/ostatus/ostatus_test.exs b/test/web/ostatus/ostatus_test.exs index 70a0e4473..ef34425da 100644 --- a/test/web/ostatus/ostatus_test.exs +++ b/test/web/ostatus/ostatus_test.exs @@ -33,7 +33,7 @@ defmodule Pleroma.Web.OStatusTest do object = Object.normalize(activity) user = User.get_cached_by_ap_id(activity.data["actor"]) - assert user.info.note_count == 1 + assert user.note_count == 1 assert activity.data["type"] == "Create" assert object.data["type"] == "Note" @@ -328,7 +328,7 @@ defmodule Pleroma.Web.OStatusTest do test "refuse following over OStatus if the followed's account is locked" do incoming = File.read!("test/fixtures/follow.xml") - _user = insert(:user, info: %{locked: true}, ap_id: "https://pawoo.net/users/pekorino") + _user = insert(:user, locked: true, ap_id: "https://pawoo.net/users/pekorino") {:ok, [{:error, "It's not possible to follow locked accounts over OStatus"}]} = OStatus.handle_incoming(incoming) @@ -392,7 +392,7 @@ defmodule Pleroma.Web.OStatusTest do assert user.name == "Constance Variable" assert user.nickname == "lambadalambda@social.heldscal.la" assert user.local == false - assert user.info.uri == uri + assert user.uri == uri assert user.ap_id == uri assert user.bio == "Call me Deacon Blues." assert user.avatar["type"] == "Image" @@ -402,36 +402,34 @@ defmodule Pleroma.Web.OStatusTest do assert user == user_again end - test "find_or_make_user sets all the nessary input fields" do + test "find_or_make_user sets all the necessary input fields" do uri = "https://social.heldscal.la/user/23211" {:ok, user} = OStatus.find_or_make_user(uri) - assert user.info == - %User.Info{ - id: user.info.id, - ap_enabled: false, - background: %{}, - banner: %{}, - blocks: [], - deactivated: false, - default_scope: "public", - domain_blocks: [], - follower_count: 0, - is_admin: false, - is_moderator: false, - keys: nil, - locked: false, - no_rich_text: false, - note_count: 0, - settings: nil, - source_data: %{}, - hub: "https://social.heldscal.la/main/push/hub", - magic_key: - "RSA.uzg6r1peZU0vXGADWxGJ0PE34WvmhjUmydbX5YYdOiXfODVLwCMi1umGoqUDm-mRu4vNEdFBVJU1CpFA7dKzWgIsqsa501i2XqElmEveXRLvNRWFB6nG03Q5OUY2as8eE54BJm0p20GkMfIJGwP6TSFb-ICp3QjzbatuSPJ6xCE=.AQAB", - salmon: "https://social.heldscal.la/main/salmon/user/23211", - topic: "https://social.heldscal.la/api/statuses/user_timeline/23211.atom", - uri: "https://social.heldscal.la/user/23211" - } + assert user.ap_enabled == false + assert user.background == %{} + assert user.banner == %{} + assert user.blocks == [] + assert user.deactivated == false + assert user.default_scope == "public" + assert user.domain_blocks == [] + assert user.follower_count == 0 + assert user.is_admin == false + assert user.is_moderator == false + assert user.is_moderator == false + assert is_nil(user.keys) + assert user.locked == false + + assert user.magic_key == + "RSA.uzg6r1peZU0vXGADWxGJ0PE34WvmhjUmydbX5YYdOiXfODVLwCMi1umGoqUDm-mRu4vNEdFBVJU1CpFA7dKzWgIsqsa501i2XqElmEveXRLvNRWFB6nG03Q5OUY2as8eE54BJm0p20GkMfIJGwP6TSFb-ICp3QjzbatuSPJ6xCE=.AQAB" + + assert user.no_rich_text == false + assert user.note_count == 0 + assert is_nil(user.settings) + assert user.hub == "https://social.heldscal.la/main/push/hub" + assert user.salmon == "https://social.heldscal.la/main/salmon/user/23211" + assert user.topic == "https://social.heldscal.la/api/statuses/user_timeline/23211.atom" + assert user.uri == "https://social.heldscal.la/user/23211" end test "find_make_or_update_actor takes an author element and returns an updated user" do @@ -465,7 +463,7 @@ defmodule Pleroma.Web.OStatusTest do user = insert(:user, %{ ap_id: "https://social.heldscal.la/user/23211", - info: %{ap_enabled: true}, + ap_enabled: true, local: false }) @@ -484,7 +482,7 @@ defmodule Pleroma.Web.OStatusTest do user = insert(:user, %{ ap_id: "https://social.heldscal.la/user/23211", - info: %{ap_enabled: true}, + ap_enabled: true, local: false }) diff --git a/test/web/pleroma_api/controllers/account_controller_test.exs b/test/web/pleroma_api/controllers/account_controller_test.exs index 3b4665afd..c809f510f 100644 --- a/test/web/pleroma_api/controllers/account_controller_test.exs +++ b/test/web/pleroma_api/controllers/account_controller_test.exs @@ -6,7 +6,6 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do use Pleroma.Web.ConnCase alias Pleroma.Config - alias Pleroma.Repo alias Pleroma.Tests.ObanHelpers alias Pleroma.User alias Pleroma.Web.CommonAPI @@ -20,10 +19,10 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do setup do {:ok, user} = insert(:user) - |> User.change_info(&User.Info.confirmation_changeset(&1, need_confirmation: true)) - |> Repo.update() + |> User.confirmation_changeset(need_confirmation: true) + |> User.update_and_set_cache() - assert user.info.confirmation_pending + assert user.confirmation_pending [user: user] end @@ -105,7 +104,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => @image}) user = refresh_record(user) - assert user.info.banner["type"] == "Image" + assert user.banner["type"] == "Image" assert %{"url" => _} = json_response(conn, 200) end @@ -119,7 +118,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do |> patch("/api/v1/pleroma/accounts/update_banner", %{"banner" => ""}) user = refresh_record(user) - assert user.info.banner == %{} + assert user.banner == %{} assert %{"url" => nil} = json_response(conn, 200) end @@ -135,7 +134,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => @image}) user = refresh_record(user) - assert user.info.background["type"] == "Image" + assert user.background["type"] == "Image" assert %{"url" => _} = json_response(conn, 200) end @@ -148,14 +147,14 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do |> patch("/api/v1/pleroma/accounts/update_background", %{"img" => ""}) user = refresh_record(user) - assert user.info.background == %{} + assert user.background == %{} assert %{"url" => nil} = json_response(conn, 200) end end describe "getting favorites timeline of specified user" do setup do - [current_user, user] = insert_pair(:user, %{info: %{hide_favorites: false}}) + [current_user, user] = insert_pair(:user, hide_favorites: false) [current_user: current_user, user: user] end @@ -319,7 +318,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do conn: conn, current_user: current_user } do - user = insert(:user, %{info: %{hide_favorites: true}}) + user = insert(:user, hide_favorites: true) activity = insert(:note_activity) CommonAPI.favorite(activity.id, user) @@ -341,7 +340,7 @@ defmodule Pleroma.Web.PleromaAPI.AccountControllerTest do |> assign(:user, current_user) |> get("/api/v1/pleroma/accounts/#{user.id}/favourites") - assert user.info.hide_favorites + assert user.hide_favorites assert json_response(conn, 403) == %{"error" => "Can't get favorites"} end end diff --git a/test/web/pleroma_api/controllers/emoji_api_controller_test.exs b/test/web/pleroma_api/controllers/emoji_api_controller_test.exs index 5f74460e8..3d3becefd 100644 --- a/test/web/pleroma_api/controllers/emoji_api_controller_test.exs +++ b/test/web/pleroma_api/controllers/emoji_api_controller_test.exs @@ -38,7 +38,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do end test "listing remote packs" do - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) conn = build_conn() |> assign(:user, admin) resp = conn |> get(emoji_api_path(conn, :list_packs)) |> json_response(200) @@ -121,7 +121,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do text(File.read!("#{@emoji_dir_path}/test_pack_nonshared/nonshared.zip")) end) - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) conn = build_conn() |> assign(:user, admin) @@ -206,7 +206,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do end) {:ok, - admin: insert(:user, info: %{is_admin: true}), + admin: insert(:user, is_admin: true), pack_file: pack_file, new_data: %{ "license" => "Test license changed", @@ -303,7 +303,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do File.rm_rf!("#{@emoji_dir_path}/test_pack/dir_2") end) - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) conn = build_conn() @@ -391,7 +391,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do File.rm_rf!("#{@emoji_dir_path}/test_created") end) - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) conn = build_conn() |> assign(:user, admin) @@ -431,7 +431,7 @@ defmodule Pleroma.Web.PleromaAPI.EmojiAPIControllerTest do refute Map.has_key?(resp, "test_pack_for_import") - admin = insert(:user, info: %{is_admin: true}) + admin = insert(:user, is_admin: true) assert conn |> assign(:user, admin) diff --git a/test/web/salmon/salmon_test.exs b/test/web/salmon/salmon_test.exs index 153ec41ac..a3ef80c9a 100644 --- a/test/web/salmon/salmon_test.exs +++ b/test/web/salmon/salmon_test.exs @@ -71,9 +71,7 @@ defmodule Pleroma.Web.Salmon.SalmonTest do [:passthrough], [] do user_data = %{ - info: %{ - salmon: "http://test-example.org/salmon" - }, + salmon: "http://test-example.org/salmon", local: false } diff --git a/test/web/streamer/streamer_test.exs b/test/web/streamer/streamer_test.exs index d33eb1e42..400f3287d 100644 --- a/test/web/streamer/streamer_test.exs +++ b/test/web/streamer/streamer_test.exs @@ -213,7 +213,7 @@ defmodule Pleroma.Web.StreamerTest do test "it sends message if recipients invalid and thread containment is enabled but user's thread containment is disabled" do Pleroma.Config.put([:instance, :skip_thread_containment], false) author = insert(:user) - user = insert(:user, following: [author.ap_id], info: %{skip_thread_containment: true}) + user = insert(:user, following: [author.ap_id], skip_thread_containment: true) activity = insert(:note_activity, diff --git a/test/web/twitter_api/password_controller_test.exs b/test/web/twitter_api/password_controller_test.exs index dc6d4e3e3..840c84a05 100644 --- a/test/web/twitter_api/password_controller_test.exs +++ b/test/web/twitter_api/password_controller_test.exs @@ -59,7 +59,7 @@ defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do end test "it sets password_reset_pending to false", %{conn: conn} do - user = insert(:user, info: %{password_reset_pending: true}) + user = insert(:user, password_reset_pending: true) {:ok, token} = PasswordResetToken.create_token(user) {:ok, _access_token} = Token.create_token(insert(:oauth_app), user, %{}) @@ -75,7 +75,7 @@ defmodule Pleroma.Web.TwitterAPI.PasswordControllerTest do |> post("/api/pleroma/password_reset", %{data: params}) |> html_response(:ok) - assert User.get_by_id(user.id).info.password_reset_pending == false + assert User.get_by_id(user.id).password_reset_pending == false end end end diff --git a/test/web/twitter_api/twitter_api_test.exs b/test/web/twitter_api/twitter_api_test.exs index d1d61d11a..85a9be3e0 100644 --- a/test/web/twitter_api/twitter_api_test.exs +++ b/test/web/twitter_api/twitter_api_test.exs @@ -71,7 +71,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPITest do {:ok, user} = TwitterAPI.register_user(data) ObanHelpers.perform_all() - assert user.info.confirmation_pending + assert user.confirmation_pending email = Pleroma.Emails.UserEmail.account_confirmation_email(user) diff --git a/test/web/twitter_api/util_controller_test.exs b/test/web/twitter_api/util_controller_test.exs index 9d4cb70f0..246da4da4 100644 --- a/test/web/twitter_api/util_controller_test.exs +++ b/test/web/twitter_api/util_controller_test.exs @@ -164,7 +164,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do "follows" => true, "non_follows" => true, "non_followers" => true - } == user.info.notification_settings + } == user.notification_settings end end @@ -370,7 +370,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do end test "returns error when user is deactivated", %{conn: conn} do - user = insert(:user, info: %{deactivated: true}) + user = insert(:user, deactivated: true) user2 = insert(:user) response = @@ -568,7 +568,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do user = User.get_cached_by_id(user.id) - assert user.info.deactivated == true + assert user.deactivated == true end test "it returns returns when password invalid", %{conn: conn} do @@ -583,7 +583,7 @@ defmodule Pleroma.Web.TwitterAPI.UtilControllerTest do assert response == %{"error" => "Invalid password."} user = User.get_cached_by_id(user.id) - refute user.info.deactivated + refute user.deactivated end end diff --git a/test/web/websub/websub_test.exs b/test/web/websub/websub_test.exs index 46ca545de..eae4013be 100644 --- a/test/web/websub/websub_test.exs +++ b/test/web/websub/websub_test.exs @@ -109,7 +109,7 @@ defmodule Pleroma.Web.WebsubTest do test "initiate a subscription for a given user and topic" do subscriber = insert(:user) - user = insert(:user, %{info: %Pleroma.User.Info{topic: "some_topic", hub: "some_hub"}}) + user = insert(:user, topic: "some_topic", hub: "some_hub") {:ok, websub} = Websub.subscribe(subscriber, user, &accepting_verifier/1) assert websub.subscribers == [subscriber.ap_id] From 66b5d0ff558bffeddf6475af72b73bf2870512f6 Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Thu, 17 Oct 2019 15:26:59 +0300 Subject: [PATCH 02/28] add Markers /api/v1/markers --- lib/pleroma/marker.ex | 74 ++++++++++++ .../mastodon_api/controllers/marker_controller.ex | 32 ++++++ lib/pleroma/web/mastodon_api/views/marker_view.ex | 17 +++ lib/pleroma/web/router.ex | 3 + .../migrations/20191014181019_create_markers.exs | 15 +++ test/marker_test.exs | 51 +++++++++ test/support/factory.ex | 9 ++ .../controllers/marker_controller_test.exs | 124 +++++++++++++++++++++ test/web/mastodon_api/views/marker_view_test.exs | 27 +++++ 9 files changed, 352 insertions(+) create mode 100644 lib/pleroma/marker.ex create mode 100644 lib/pleroma/web/mastodon_api/controllers/marker_controller.ex create mode 100644 lib/pleroma/web/mastodon_api/views/marker_view.ex create mode 100644 priv/repo/migrations/20191014181019_create_markers.exs create mode 100644 test/marker_test.exs create mode 100644 test/web/mastodon_api/controllers/marker_controller_test.exs create mode 100644 test/web/mastodon_api/views/marker_view_test.exs diff --git a/lib/pleroma/marker.ex b/lib/pleroma/marker.ex new file mode 100644 index 000000000..7f87c86c3 --- /dev/null +++ b/lib/pleroma/marker.ex @@ -0,0 +1,74 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Marker do + use Ecto.Schema + + import Ecto.Changeset + import Ecto.Query + + alias Ecto.Multi + alias Pleroma.Repo + alias Pleroma.User + + @timelines ["notifications"] + + schema "markers" do + field(:last_read_id, :string, default: "") + field(:timeline, :string, default: "") + field(:lock_version, :integer, default: 0) + + belongs_to(:user, User, type: FlakeId.Ecto.CompatType) + timestamps() + end + + def get_markers(user, timelines \\ []) do + Repo.all(get_query(user, timelines)) + end + + def upsert(%User{} = user, attrs) do + attrs + |> Map.take(@timelines) + |> Enum.reduce(Multi.new(), fn {timeline, timeline_attrs}, multi -> + marker = + user + |> get_marker(timeline) + |> changeset(timeline_attrs) + + Multi.insert(multi, timeline, marker, + returning: true, + on_conflict: {:replace, [:last_read_id]}, + conflict_target: [:user_id, :timeline] + ) + end) + |> Repo.transaction() + end + + defp get_marker(user, timeline) do + case Repo.find_resource(get_query(user, timeline)) do + {:ok, marker} -> %__MODULE__{marker | user: user} + _ -> %__MODULE__{timeline: timeline, user_id: user.id} + end + end + + @doc false + defp changeset(marker, attrs) do + marker + |> cast(attrs, [:last_read_id]) + |> validate_required([:user_id, :timeline, :last_read_id]) + |> validate_inclusion(:timeline, @timelines) + end + + defp by_timeline(query, timeline) do + from(m in query, where: m.timeline in ^List.wrap(timeline)) + end + + defp by_user_id(query, id), do: from(m in query, where: m.user_id == ^id) + + defp get_query(user, timelines) do + __MODULE__ + |> by_user_id(user.id) + |> by_timeline(timelines) + end +end diff --git a/lib/pleroma/web/mastodon_api/controllers/marker_controller.ex b/lib/pleroma/web/mastodon_api/controllers/marker_controller.ex new file mode 100644 index 000000000..ce025624d --- /dev/null +++ b/lib/pleroma/web/mastodon_api/controllers/marker_controller.ex @@ -0,0 +1,32 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.MarkerController do + use Pleroma.Web, :controller + alias Pleroma.Plugs.OAuthScopesPlug + + plug( + OAuthScopesPlug, + %{scopes: ["read:statuses"]} + when action == :index + ) + + plug(OAuthScopesPlug, %{scopes: ["write:statuses"]} when action == :upsert) + plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) + action_fallback(Pleroma.Web.MastodonAPI.FallbackController) + + # GET /api/v1/markers + def index(%{assigns: %{user: user}} = conn, params) do + markers = Pleroma.Marker.get_markers(user, params["timeline"]) + render(conn, "markers.json", %{markers: markers}) + end + + # POST /api/v1/markers + def upsert(%{assigns: %{user: user}} = conn, params) do + with {:ok, result} <- Pleroma.Marker.upsert(user, params), + markers <- Map.values(result) do + render(conn, "markers.json", %{markers: markers}) + end + end +end diff --git a/lib/pleroma/web/mastodon_api/views/marker_view.ex b/lib/pleroma/web/mastodon_api/views/marker_view.ex new file mode 100644 index 000000000..38fbeed5f --- /dev/null +++ b/lib/pleroma/web/mastodon_api/views/marker_view.ex @@ -0,0 +1,17 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.MarkerView do + use Pleroma.Web, :view + + def render("markers.json", %{markers: markers}) do + Enum.reduce(markers, %{}, fn m, acc -> + Map.put_new(acc, m.timeline, %{ + last_read_id: m.last_read_id, + version: m.lock_version, + updated_at: NaiveDateTime.to_iso8601(m.updated_at) + }) + end) + end +end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index ae799b8ac..45684284c 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -394,6 +394,9 @@ defmodule Pleroma.Web.Router do get("/push/subscription", SubscriptionController, :get) put("/push/subscription", SubscriptionController, :update) delete("/push/subscription", SubscriptionController, :delete) + + get("/markers", MarkerController, :index) + post("/markers", MarkerController, :upsert) end scope "/api/web", Pleroma.Web do diff --git a/priv/repo/migrations/20191014181019_create_markers.exs b/priv/repo/migrations/20191014181019_create_markers.exs new file mode 100644 index 000000000..c717831ba --- /dev/null +++ b/priv/repo/migrations/20191014181019_create_markers.exs @@ -0,0 +1,15 @@ +defmodule Pleroma.Repo.Migrations.CreateMarkers do + use Ecto.Migration + + def change do + create_if_not_exists table(:markers) do + add(:user_id, references(:users, type: :uuid, on_delete: :delete_all)) + add(:timeline, :string, default: "", null: false) + add(:last_read_id, :string, default: "", null: false) + add(:lock_version, :integer, default: 0, null: false) + timestamps() + end + + create_if_not_exists(unique_index(:markers, [:user_id, :timeline])) + end +end diff --git a/test/marker_test.exs b/test/marker_test.exs new file mode 100644 index 000000000..04bd67fe6 --- /dev/null +++ b/test/marker_test.exs @@ -0,0 +1,51 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.MarkerTest do + use Pleroma.DataCase + alias Pleroma.Marker + + import Pleroma.Factory + + describe "get_markers/2" do + test "returns user markers" do + user = insert(:user) + marker = insert(:marker, user: user) + insert(:marker, timeline: "home", user: user) + assert Marker.get_markers(user, ["notifications"]) == [refresh_record(marker)] + end + end + + describe "upsert/2" do + test "creates a marker" do + user = insert(:user) + + {:ok, %{"notifications" => %Marker{} = marker}} = + Marker.upsert( + user, + %{"notifications" => %{"last_read_id" => "34"}} + ) + + assert marker.timeline == "notifications" + assert marker.last_read_id == "34" + assert marker.lock_version == 0 + end + + test "updates exist marker" do + user = insert(:user) + marker = insert(:marker, user: user, last_read_id: "8909") + + {:ok, %{"notifications" => %Marker{}}} = + Marker.upsert( + user, + %{"notifications" => %{"last_read_id" => "9909"}} + ) + + marker = refresh_record(marker) + assert marker.timeline == "notifications" + assert marker.last_read_id == "9909" + assert marker.lock_version == 0 + end + end +end diff --git a/test/support/factory.ex b/test/support/factory.ex index b180844cd..4537c458b 100644 --- a/test/support/factory.ex +++ b/test/support/factory.ex @@ -397,4 +397,13 @@ defmodule Pleroma.Factory do ) } end + + def marker_factory do + %Pleroma.Marker{ + user: build(:user), + timeline: "notifications", + lock_version: 0, + last_read_id: "1" + } + end end diff --git a/test/web/mastodon_api/controllers/marker_controller_test.exs b/test/web/mastodon_api/controllers/marker_controller_test.exs new file mode 100644 index 000000000..1fcad873d --- /dev/null +++ b/test/web/mastodon_api/controllers/marker_controller_test.exs @@ -0,0 +1,124 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.MarkerControllerTest do + use Pleroma.Web.ConnCase + + import Pleroma.Factory + + describe "GET /api/v1/markers" do + test "gets markers with correct scopes", %{conn: conn} do + user = insert(:user) + token = insert(:oauth_token, user: user, scopes: ["read:statuses"]) + + {:ok, %{"notifications" => marker}} = + Pleroma.Marker.upsert( + user, + %{"notifications" => %{"last_read_id" => "69420"}} + ) + + response = + conn + |> assign(:user, user) + |> assign(:token, token) + |> get("/api/v1/markers", %{timeline: ["notifications"]}) + |> json_response(200) + + assert response == %{ + "notifications" => %{ + "last_read_id" => "69420", + "updated_at" => NaiveDateTime.to_iso8601(marker.updated_at), + "version" => 0 + } + } + end + + test "gets markers with missed scopes", %{conn: conn} do + user = insert(:user) + token = insert(:oauth_token, user: user, scopes: []) + + Pleroma.Marker.upsert(user, %{"notifications" => %{"last_read_id" => "69420"}}) + + response = + conn + |> assign(:user, user) + |> assign(:token, token) + |> get("/api/v1/markers", %{timeline: ["notifications"]}) + |> json_response(403) + + assert response == %{"error" => "Insufficient permissions: read:statuses."} + end + end + + describe "POST /api/v1/markers" do + test "creates a marker with correct scopes", %{conn: conn} do + user = insert(:user) + token = insert(:oauth_token, user: user, scopes: ["write:statuses"]) + + response = + conn + |> assign(:user, user) + |> assign(:token, token) + |> post("/api/v1/markers", %{ + home: %{last_read_id: "777"}, + notifications: %{"last_read_id" => "69420"} + }) + |> json_response(200) + + assert %{ + "notifications" => %{ + "last_read_id" => "69420", + "updated_at" => _, + "version" => 0 + } + } = response + end + + test "updates exist marker", %{conn: conn} do + user = insert(:user) + token = insert(:oauth_token, user: user, scopes: ["write:statuses"]) + + {:ok, %{"notifications" => marker}} = + Pleroma.Marker.upsert( + user, + %{"notifications" => %{"last_read_id" => "69477"}} + ) + + response = + conn + |> assign(:user, user) + |> assign(:token, token) + |> post("/api/v1/markers", %{ + home: %{last_read_id: "777"}, + notifications: %{"last_read_id" => "69888"} + }) + |> json_response(200) + + assert response == %{ + "notifications" => %{ + "last_read_id" => "69888", + "updated_at" => NaiveDateTime.to_iso8601(marker.updated_at), + "version" => 0 + } + } + end + + test "creates a marker with missed scopes", %{conn: conn} do + user = insert(:user) + token = insert(:oauth_token, user: user, scopes: []) + + response = + conn + |> assign(:user, user) + |> assign(:token, token) + |> post("/api/v1/markers", %{ + home: %{last_read_id: "777"}, + notifications: %{"last_read_id" => "69420"} + }) + |> json_response(403) + + assert response == %{"error" => "Insufficient permissions: write:statuses."} + end + end +end diff --git a/test/web/mastodon_api/views/marker_view_test.exs b/test/web/mastodon_api/views/marker_view_test.exs new file mode 100644 index 000000000..8a5c89d56 --- /dev/null +++ b/test/web/mastodon_api/views/marker_view_test.exs @@ -0,0 +1,27 @@ +# Pleroma: A lightweight social networking server +# Copyright © 2017-2019 Pleroma Authors +# SPDX-License-Identifier: AGPL-3.0-only + +defmodule Pleroma.Web.MastodonAPI.MarkerViewTest do + use Pleroma.DataCase + alias Pleroma.Web.MastodonAPI.MarkerView + import Pleroma.Factory + + test "returns markers" do + marker1 = insert(:marker, timeline: "notifications", last_read_id: "17") + marker2 = insert(:marker, timeline: "home", last_read_id: "42") + + assert MarkerView.render("markers.json", %{markers: [marker1, marker2]}) == %{ + "home" => %{ + last_read_id: "42", + updated_at: NaiveDateTime.to_iso8601(marker2.updated_at), + version: 0 + }, + "notifications" => %{ + last_read_id: "17", + updated_at: NaiveDateTime.to_iso8601(marker1.updated_at), + version: 0 + } + } + end +end From 152caef51d69ba4a47ac59346c782dfff8488f8b Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Fri, 18 Oct 2019 17:51:34 -0500 Subject: [PATCH 03/28] Direct messages should provide a distinct push notification subject --- lib/pleroma/web/push/impl.ex | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/pleroma/web/push/impl.ex b/lib/pleroma/web/push/impl.ex index 35d3ff07c..dd445e8bf 100644 --- a/lib/pleroma/web/push/impl.ex +++ b/lib/pleroma/web/push/impl.ex @@ -125,6 +125,10 @@ defmodule Pleroma.Web.Push.Impl do end end + def format_title(%{activity: %{data: %{"directMessage" => true}}}) do + "New Direct Message" + end + def format_title(%{activity: %{data: %{"type" => type}}}) do case type do "Create" -> "New Mention" From e7333db72ade8214ad80122d49862e520b093e8a Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 5 Oct 2019 20:06:03 +0000 Subject: [PATCH 04/28] user info: add invisible field --- lib/pleroma/user/info.ex | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex index 2d39abcb3..53525b386 100644 --- a/lib/pleroma/user/info.ex +++ b/lib/pleroma/user/info.ex @@ -53,6 +53,7 @@ defmodule Pleroma.User.Info do field(:fields, {:array, :map}, default: nil) field(:raw_fields, {:array, :map}, default: []) field(:discoverable, :boolean, default: false) + field(:invisible, :boolean, default: false) field(:notification_settings, :map, default: %{ @@ -393,6 +394,14 @@ defmodule Pleroma.User.Info do |> validate_required([:source_data]) end + def set_invisible(info, invisible) do + params = %{invisible: invisible} + + info + |> cast(params, [:invisible]) + |> validate_required([:invisible]) + end + def admin_api_update(info, params) do info |> cast(params, [ From 1469a084d4c95d24619f88c462601570f85ecfa2 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 5 Oct 2019 20:06:31 +0000 Subject: [PATCH 05/28] relay: set invisible to true --- lib/pleroma/web/activity_pub/relay.ex | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/web/activity_pub/relay.ex b/lib/pleroma/web/activity_pub/relay.ex index 03fc434a9..de80612f1 100644 --- a/lib/pleroma/web/activity_pub/relay.ex +++ b/lib/pleroma/web/activity_pub/relay.ex @@ -10,8 +10,12 @@ defmodule Pleroma.Web.ActivityPub.Relay do require Logger def get_actor do - "#{Pleroma.Web.Endpoint.url()}/relay" - |> User.get_or_create_service_actor_by_ap_id() + actor = + "#{Pleroma.Web.Endpoint.url()}/relay" + |> User.get_or_create_service_actor_by_ap_id() + + {:ok, actor} = User.update_info(actor, &User.Info.set_invisible(&1, true)) + actor end @spec follow(String.t()) :: {:ok, Activity.t()} | {:error, any()} From 95871cb4628933900f2004a8bece1b929d5525bf Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 5 Oct 2019 20:11:43 +0000 Subject: [PATCH 06/28] user: implement User.invisible?/1 --- lib/pleroma/user.ex | 3 +++ test/user_test.exs | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index ec705b8f6..2bbfaa55b 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -88,6 +88,9 @@ defmodule Pleroma.User do def superuser?(%User{local: true, info: %User.Info{is_moderator: true}}), do: true def superuser?(_), do: false + def invisible?(%User{info: %User.Info{invisible: true}}), do: true + def invisible?(_), do: false + def avatar_url(user, options \\ []) do case user.avatar do %{"url" => [%{"href" => href} | _]} -> href diff --git a/test/user_test.exs b/test/user_test.exs index ad050b7da..05bdb9a61 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -1232,6 +1232,20 @@ defmodule Pleroma.UserTest do end end + describe "invisible?/1" do + test "returns true for an invisible user" do + user = insert(:user, local: true, info: %{invisible: true}) + + assert User.invisible?(user) + end + + test "returns false for a non-invisible user" do + user = insert(:user, local: true) + + refute User.invisible?(user) + end + end + describe "visible_for?/2" do test "returns true when the account is itself" do user = insert(:user, local: true) From ef659331b03925c41cd3e557bd39cb2d73dd6aa1 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 5 Oct 2019 20:41:33 +0000 Subject: [PATCH 07/28] implement invisible support for remote users --- lib/pleroma/user/info.ex | 3 +- lib/pleroma/web/activity_pub/activity_pub.ex | 10 +++- lib/pleroma/web/activity_pub/transmogrifier.ex | 11 ++++- lib/pleroma/web/activity_pub/utils.ex | 10 ++-- .../tesla_mock/relay@mastdon.example.org.json | 54 ++++++++++++++++++++++ test/support/http_request_mock.ex | 8 ++++ test/web/activity_pub/activity_pub_test.exs | 6 +++ 7 files changed, 95 insertions(+), 7 deletions(-) create mode 100644 test/fixtures/tesla_mock/relay@mastdon.example.org.json diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex index 53525b386..982fb61c6 100644 --- a/lib/pleroma/user/info.ex +++ b/lib/pleroma/user/info.ex @@ -267,7 +267,8 @@ defmodule Pleroma.User.Info do :follower_count, :fields, :following_count, - :discoverable + :discoverable, + :invisible ]) |> validate_fields(true) end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 94c467b69..1cfe826fa 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1107,6 +1107,13 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do data = Transmogrifier.maybe_fix_user_object(data) discoverable = data["discoverable"] || false + invisible = + if is_list(data["type"]) do + Enum.member?(data["type"], "Invisible") + else + false + end + user_data = %{ ap_id: data["id"], info: %{ @@ -1115,7 +1122,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do banner: banner, fields: fields, locked: locked, - discoverable: discoverable + discoverable: discoverable, + invisible: invisible }, avatar: avatar, name: data["name"], diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 2c1ce9c55..49bbeb857 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -596,13 +596,20 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do data, _options ) - when object_type in ["Person", "Application", "Service", "Organization"] do + when object_type in [ + "Person", + "Application", + "Service", + "Organization", + ["Application", "Invisible"] + ] do with %User{ap_id: ^actor_id} = actor <- User.get_cached_by_ap_id(object["id"]) do {:ok, new_user_data} = ActivityPub.user_data_from_user_object(object) banner = new_user_data[:info][:banner] locked = new_user_data[:info][:locked] || false attachment = get_in(new_user_data, [:info, :source_data, "attachment"]) || [] + invisible = new_user_data[:info][:invisible] || false fields = attachment @@ -612,7 +619,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do update_data = new_user_data |> Map.take([:name, :bio, :avatar]) - |> Map.put(:info, %{banner: banner, locked: locked, fields: fields}) + |> Map.put(:info, %{banner: banner, locked: locked, fields: fields, invisible: invisible}) actor |> User.upgrade_changeset(update_data, true) diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 4ef479f96..6b28df92c 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -491,10 +491,14 @@ defmodule Pleroma.Web.ActivityPub.Utils do %Activity{data: %{"actor" => actor}}, object ) do - announcements = take_announcements(object) + unless actor |> User.get_cached_by_ap_id() |> User.invisible?() do + announcements = take_announcements(object) - with announcements <- Enum.uniq([actor | announcements]) do - update_element_in_object("announcement", announcements, object) + with announcements <- Enum.uniq([actor | announcements]) do + update_element_in_object("announcement", announcements, object) + end + else + {:ok, object} end end diff --git a/test/fixtures/tesla_mock/relay@mastdon.example.org.json b/test/fixtures/tesla_mock/relay@mastdon.example.org.json new file mode 100644 index 000000000..b70be2bf4 --- /dev/null +++ b/test/fixtures/tesla_mock/relay@mastdon.example.org.json @@ -0,0 +1,54 @@ +{ + "@context": ["https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1", { + "manuallyApprovesFollowers": "as:manuallyApprovesFollowers", + "sensitive": "as:sensitive", + "movedTo": "as:movedTo", + "Hashtag": "as:Hashtag", + "ostatus": "http://ostatus.org#", + "atomUri": "ostatus:atomUri", + "inReplyToAtomUri": "ostatus:inReplyToAtomUri", + "conversation": "ostatus:conversation", + "toot": "http://joinmastodon.org/ns#", + "Emoji": "toot:Emoji" + }], + "id": "http://mastodon.example.org/users/admin", + "type": ["Application", "Invisible"], + "following": "http://mastodon.example.org/users/admin/following", + "followers": "http://mastodon.example.org/users/admin/followers", + "inbox": "http://mastodon.example.org/users/admin/inbox", + "outbox": "http://mastodon.example.org/users/admin/outbox", + "preferredUsername": "admin", + "name": null, + "summary": "\u003cp\u003e\u003c/p\u003e", + "url": "http://mastodon.example.org/@admin", + "manuallyApprovesFollowers": false, + "publicKey": { + "id": "http://mastodon.example.org/users/admin#main-key", + "owner": "http://mastodon.example.org/users/admin", + "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtc4Tir+3ADhSNF6VKrtW\nOU32T01w7V0yshmQei38YyiVwVvFu8XOP6ACchkdxbJ+C9mZud8qWaRJKVbFTMUG\nNX4+6Q+FobyuKrwN7CEwhDALZtaN2IPbaPd6uG1B7QhWorrY+yFa8f2TBM3BxnUy\nI4T+bMIZIEYG7KtljCBoQXuTQmGtuffO0UwJksidg2ffCF5Q+K//JfQagJ3UzrR+\nZXbKMJdAw4bCVJYs4Z5EhHYBwQWiXCyMGTd7BGlmMkY6Av7ZqHKC/owp3/0EWDNz\nNqF09Wcpr3y3e8nA10X40MJqp/wR+1xtxp+YGbq/Cj5hZGBG7etFOmIpVBrDOhry\nBwIDAQAB\n-----END PUBLIC KEY-----\n" + }, + "attachment": [{ + "type": "PropertyValue", + "name": "foo", + "value": "bar" + }, + { + "type": "PropertyValue", + "name": "foo1", + "value": "bar1" + } + ], + "endpoints": { + "sharedInbox": "http://mastodon.example.org/inbox" + }, + "icon": { + "type": "Image", + "mediaType": "image/jpeg", + "url": "https://cdn.niu.moe/accounts/avatars/000/033/323/original/fd7f8ae0b3ffedc9.jpeg" + }, + "image": { + "type": "Image", + "mediaType": "image/png", + "url": "https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png" + } +} diff --git a/test/support/http_request_mock.ex b/test/support/http_request_mock.ex index 7d65209fb..eba22c40b 100644 --- a/test/support/http_request_mock.ex +++ b/test/support/http_request_mock.ex @@ -348,6 +348,14 @@ defmodule HttpRequestMock do }} end + def get("http://mastodon.example.org/users/relay", _, _, Accept: "application/activity+json") do + {:ok, + %Tesla.Env{ + status: 200, + body: File.read!("test/fixtures/tesla_mock/relay@mastdon.example.org.json") + }} + end + def get("http://mastodon.example.org/users/gargron", _, _, Accept: "application/activity+json") do {:error, :nxdomain} end diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index 28a9b773c..b87050a4a 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -179,6 +179,12 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do assert user.follower_address == "http://mastodon.example.org/users/admin/followers" end + test "it returns a user that is invisible" do + user_id = "http://mastodon.example.org/users/relay" + {:ok, user} = ActivityPub.make_user_from_ap_id(user_id) + assert user.info.invisible + end + test "it fetches the appropriate tag-restricted posts" do user = insert(:user) From 80d3912a56816e4cb136a33a7aafcb0d0fede0fa Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 8 Oct 2019 20:59:43 +0000 Subject: [PATCH 08/28] test: activitypub: use User.invisible?/1 for testing invisibility --- test/web/activity_pub/activity_pub_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/web/activity_pub/activity_pub_test.exs b/test/web/activity_pub/activity_pub_test.exs index b87050a4a..8ae946969 100644 --- a/test/web/activity_pub/activity_pub_test.exs +++ b/test/web/activity_pub/activity_pub_test.exs @@ -182,7 +182,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubTest do test "it returns a user that is invisible" do user_id = "http://mastodon.example.org/users/relay" {:ok, user} = ActivityPub.make_user_from_ap_id(user_id) - assert user.info.invisible + assert User.invisible?(user) end test "it fetches the appropriate tag-restricted posts" do From 9694d514371a454d320b0129332c28a4695fd340 Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Mon, 14 Oct 2019 09:09:32 +0300 Subject: [PATCH 09/28] added test fo Pleroma.Web.MastodonAPI.StatusController --- .../controllers/status_controller_test.exs | 29 ++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs index 2de2725e0..7b52abdce 100644 --- a/test/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/web/mastodon_api/controllers/status_controller_test.exs @@ -12,6 +12,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do alias Pleroma.Object alias Pleroma.Repo alias Pleroma.ScheduledActivity + alias Pleroma.Tests.ObanHelpers alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.CommonAPI @@ -29,6 +30,34 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do [conn: conn] end + test "posting a status and checks reblog count after perform all backroud job", %{conn: conn} do + Pleroma.Config.put([:instance, :federating], true) + Pleroma.Config.get([:instance, :allow_relay], true) + user = insert(:user) + + response = + conn + |> assign(:user, user) + |> post("api/v1/statuses", %{ + "content_type" => "text/plain", + "source" => "Pleroma FE", + "status" => "Hello world", + "visibility" => "public" + }) + |> json_response(200) + + assert response["reblogs_count"] == 0 + ObanHelpers.perform_all() + + response = + conn + |> assign(:user, user) + |> get("api/v1/statuses/#{response["id"]}", %{}) + |> json_response(200) + + assert response["reblogs_count"] == 0 + end + test "posting a status", %{conn: conn} do idempotency_key = "Pikachu rocks!" From 189a2889258038ae9372113e5d901f18b7417a82 Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Mon, 14 Oct 2019 09:31:08 +0300 Subject: [PATCH 10/28] fix test --- test/web/mastodon_api/controllers/status_controller_test.exs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs index 7b52abdce..ce964359b 100644 --- a/test/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/web/mastodon_api/controllers/status_controller_test.exs @@ -19,6 +19,9 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do import Pleroma.Factory + clear_config([:instance, :federating]) + clear_config([:instance, :allow_relay]) + describe "posting statuses" do setup do user = insert(:user) From c9280b97306b894a38377acf43c62d7808df01d8 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 19 Oct 2019 17:46:24 +0000 Subject: [PATCH 11/28] rework to use properties instead of compound typing, per SocialCG --- lib/pleroma/web/activity_pub/activity_pub.ex | 8 +------- lib/pleroma/web/activity_pub/transmogrifier.ex | 3 +-- lib/pleroma/web/activity_pub/views/user_view.ex | 3 ++- priv/static/schemas/litepub-0.1.jsonld | 1 + test/fixtures/tesla_mock/relay@mastdon.example.org.json | 3 ++- 5 files changed, 7 insertions(+), 11 deletions(-) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 1cfe826fa..9a0a3522a 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1106,13 +1106,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do locked = data["manuallyApprovesFollowers"] || false data = Transmogrifier.maybe_fix_user_object(data) discoverable = data["discoverable"] || false - - invisible = - if is_list(data["type"]) do - Enum.member?(data["type"], "Invisible") - else - false - end + invisible = data["invisible"] || false user_data = %{ ap_id: data["id"], diff --git a/lib/pleroma/web/activity_pub/transmogrifier.ex b/lib/pleroma/web/activity_pub/transmogrifier.ex index 49bbeb857..4a250d131 100644 --- a/lib/pleroma/web/activity_pub/transmogrifier.ex +++ b/lib/pleroma/web/activity_pub/transmogrifier.ex @@ -600,8 +600,7 @@ defmodule Pleroma.Web.ActivityPub.Transmogrifier do "Person", "Application", "Service", - "Organization", - ["Application", "Invisible"] + "Organization" ] do with %User{ap_id: ^actor_id} = actor <- User.get_cached_by_ap_id(object["id"]) do {:ok, new_user_data} = ActivityPub.user_data_from_user_object(object) diff --git a/lib/pleroma/web/activity_pub/views/user_view.ex b/lib/pleroma/web/activity_pub/views/user_view.ex index 9b39d1629..8c5b4460b 100644 --- a/lib/pleroma/web/activity_pub/views/user_view.ex +++ b/lib/pleroma/web/activity_pub/views/user_view.ex @@ -55,7 +55,8 @@ defmodule Pleroma.Web.ActivityPub.UserView do "owner" => user.ap_id, "publicKeyPem" => public_key }, - "endpoints" => endpoints + "endpoints" => endpoints, + "invisible" => User.invisible?(user) } |> Map.merge(Utils.make_json_ld_header()) end diff --git a/priv/static/schemas/litepub-0.1.jsonld b/priv/static/schemas/litepub-0.1.jsonld index 1cfcb7ec7..c8e69cab5 100644 --- a/priv/static/schemas/litepub-0.1.jsonld +++ b/priv/static/schemas/litepub-0.1.jsonld @@ -19,6 +19,7 @@ "value": "schema:value", "sensitive": "as:sensitive", "litepub": "http://litepub.social/ns#", + "invisible": "litepub:invisible", "directMessage": "litepub:directMessage", "listMessage": { "@id": "litepub:listMessage", diff --git a/test/fixtures/tesla_mock/relay@mastdon.example.org.json b/test/fixtures/tesla_mock/relay@mastdon.example.org.json index b70be2bf4..c1fab7d3b 100644 --- a/test/fixtures/tesla_mock/relay@mastdon.example.org.json +++ b/test/fixtures/tesla_mock/relay@mastdon.example.org.json @@ -12,7 +12,8 @@ "Emoji": "toot:Emoji" }], "id": "http://mastodon.example.org/users/admin", - "type": ["Application", "Invisible"], + "type": "Application", + "invisible": true, "following": "http://mastodon.example.org/users/admin/following", "followers": "http://mastodon.example.org/users/admin/followers", "inbox": "http://mastodon.example.org/users/admin/inbox", From 52d56ed705232b7b3b43d78aaef7c5170a5c1217 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 19 Oct 2019 17:50:17 +0000 Subject: [PATCH 12/28] tests: add test verifying the relay user is invisible --- test/web/activity_pub/relay_test.exs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/web/activity_pub/relay_test.exs b/test/web/activity_pub/relay_test.exs index 4a0a03944..ac2007b2c 100644 --- a/test/web/activity_pub/relay_test.exs +++ b/test/web/activity_pub/relay_test.exs @@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do alias Pleroma.Activity alias Pleroma.Object + alias Pleroma.User alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Relay @@ -19,6 +20,11 @@ defmodule Pleroma.Web.ActivityPub.RelayTest do assert user.ap_id == "#{Pleroma.Web.Endpoint.url()}/relay" end + test "relay actor is invisible" do + user = Relay.get_actor() + assert User.invisible?(user) + end + describe "follow/1" do test "returns errors when user not found" do assert capture_log(fn -> From ba92522c6902c2992f0b9fa50aaded1087e125ba Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 19 Oct 2019 17:53:52 +0000 Subject: [PATCH 13/28] tests: add test to ensure invisible actors are rendered with the invisible hint set to true --- test/web/activity_pub/views/user_view_test.exs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/web/activity_pub/views/user_view_test.exs b/test/web/activity_pub/views/user_view_test.exs index 3155749aa..a31b4c92e 100644 --- a/test/web/activity_pub/views/user_view_test.exs +++ b/test/web/activity_pub/views/user_view_test.exs @@ -76,6 +76,12 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do assert result["image"]["url"] == "https://somebanner" end + test "renders an invisible user with the invisible property set to true" do + user = insert(:user, %{info: %{invisible: true}}) + + assert %{"invisible" => true} = UserView.render("service.json", %{user: user}) + end + describe "endpoints" do test "local users have a usable endpoints structure" do user = insert(:user) From 05c58eaecef3d51b567ff1529aa33f36e03f5452 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 19 Oct 2019 23:23:13 +0000 Subject: [PATCH 14/28] change Maksim's test description --- test/web/mastodon_api/controllers/status_controller_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/web/mastodon_api/controllers/status_controller_test.exs b/test/web/mastodon_api/controllers/status_controller_test.exs index ce964359b..4da610b28 100644 --- a/test/web/mastodon_api/controllers/status_controller_test.exs +++ b/test/web/mastodon_api/controllers/status_controller_test.exs @@ -33,7 +33,7 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do [conn: conn] end - test "posting a status and checks reblog count after perform all backroud job", %{conn: conn} do + test "posting a status does not increment reblog_count when relaying", %{conn: conn} do Pleroma.Config.put([:instance, :federating], true) Pleroma.Config.get([:instance, :allow_relay], true) user = insert(:user) From e8843974cb9b8adfe8798bb8f7ff17b7a92f5ab8 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Sun, 20 Oct 2019 13:42:42 +0300 Subject: [PATCH 15/28] [#1304] Moved remaining fields from User.Info to User. Misc. fixes / improvements. --- docs/API/admin_api.md | 4 +- lib/mix/tasks/pleroma/user.ex | 16 +- lib/pleroma/notification.ex | 6 +- lib/pleroma/user.ex | 228 ++++++++++++++++----- lib/pleroma/user/info.ex | 107 ---------- lib/pleroma/user/search.ex | 4 +- lib/pleroma/web/activity_pub/activity_pub.ex | 18 +- lib/pleroma/web/common_api/common_api.ex | 8 +- .../mastodon_api/controllers/account_controller.ex | 6 +- .../controllers/domain_block_controller.ex | 4 +- lib/pleroma/web/streamer/worker.ex | 8 +- .../web/twitter_api/twitter_api_controller.ex | 4 +- ...91009154608_copy_users_info_fields_to_users.exs | 139 ++++++++++++- test/user_test.exs | 8 +- 14 files changed, 355 insertions(+), 205 deletions(-) delete mode 100644 lib/pleroma/user/info.ex diff --git a/docs/API/admin_api.md b/docs/API/admin_api.md index ee9e68cb1..b56f53967 100644 --- a/docs/API/admin_api.md +++ b/docs/API/admin_api.md @@ -160,7 +160,7 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret - Params: none - Response: - On failure: `{"error": "…"}` - - On success: JSON of the `user.info` + - On success: JSON of the user ### Remove user from permission group @@ -168,7 +168,7 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret - Params: none - Response: - On failure: `{"error": "…"}` - - On success: JSON of the `user.info` + - On success: JSON of the user - Note: An admin cannot revoke their own admin status. ## `/api/pleroma/admin/users/:nickname/activation_status` diff --git a/lib/mix/tasks/pleroma/user.ex b/lib/mix/tasks/pleroma/user.ex index 265c5f1a7..d7bdc2310 100644 --- a/lib/mix/tasks/pleroma/user.ex +++ b/lib/mix/tasks/pleroma/user.ex @@ -5,6 +5,7 @@ defmodule Mix.Tasks.Pleroma.User do use Mix.Task import Mix.Pleroma + alias Ecto.Changeset alias Pleroma.User alias Pleroma.UserInviteToken alias Pleroma.Web.OAuth @@ -364,21 +365,30 @@ defmodule Mix.Tasks.Pleroma.User do end defp set_moderator(user, value) do - {:ok, user} = User.update_and_set_cache(user, %{is_moderator: value}) + {:ok, user} = + user + |> Changeset.change(%{is_moderator: value}) + |> User.update_and_set_cache() shell_info("Moderator status of #{user.nickname}: #{user.is_moderator}") user end defp set_admin(user, value) do - {:ok, user} = User.update_and_set_cache(user, %{is_admin: value}) + {:ok, user} = + user + |> Changeset.change(%{is_admin: value}) + |> User.update_and_set_cache() shell_info("Admin status of #{user.nickname}: #{user.is_admin}") user end defp set_locked(user, value) do - {:ok, user} = User.update_and_set_cache(user, %{locked: value}) + {:ok, user} = + user + |> Changeset.change(%{locked: value}) + |> User.update_and_set_cache() shell_info("Locked status of #{user.nickname}: #{user.locked}") user diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 19d22370f..6ded91f3c 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -58,11 +58,11 @@ defmodule Pleroma.Notification do if opts[:with_muted] do query else - where(query, [n, a], a.actor not in ^user.info.muted_notifications) - |> where([n, a], a.actor not in ^user.info.blocks) + where(query, [n, a], a.actor not in ^user.muted_notifications) + |> where([n, a], a.actor not in ^user.blocks) |> where( [n, a], - fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.info.domain_blocks + fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.domain_blocks ) |> join(:left, [n, a], tm in Pleroma.ThreadMute, on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 165342011..d16d22198 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -122,7 +122,8 @@ defmodule Pleroma.User do has_many(:notifications, Notification) has_many(:registrations, Registration) has_many(:deliveries, Delivery) - embeds_one(:info, User.Info) + + field(:info, :map, default: %{}) timestamps() end @@ -304,14 +305,39 @@ defmodule Pleroma.User do changeset = %User{local: false} - |> cast(params, [:bio, :name, :ap_id, :nickname, :avatar] ++ @info_fields) + |> cast( + params, + [ + :bio, + :name, + :ap_id, + :nickname, + :avatar, + :ap_enabled, + :source_data, + :banner, + :locked, + :magic_key, + :uri, + :hub, + :topic, + :salmon, + :hide_followers, + :hide_follows, + :hide_followers_count, + :hide_follows_count, + :follower_count, + :fields, + :following_count, + :discoverable + ] + ) |> validate_required([:name, :ap_id]) |> unique_constraint(:nickname) |> validate_format(:nickname, @email_regex) |> validate_length(:bio, max: bio_limit) |> validate_length(:name, max: name_limit) |> validate_fields(true) - |> change_info(& &1) case params[:source_data] do %{"followers" => followers, "following" => following} -> @@ -330,7 +356,31 @@ defmodule Pleroma.User do name_limit = Pleroma.Config.get([:instance, :user_name_length], 100) struct - |> cast(params, [:bio, :name, :avatar, :following] ++ @info_fields) + |> cast( + params, + [ + :bio, + :name, + :avatar, + :following, + :locked, + :no_rich_text, + :default_scope, + :banner, + :hide_follows, + :hide_followers, + :hide_followers_count, + :hide_follows_count, + :hide_favorites, + :background, + :show_role, + :skip_thread_containment, + :fields, + :raw_fields, + :pleroma_settings_store, + :discoverable + ] + ) |> unique_constraint(:nickname) |> validate_format(:nickname, local_nickname_regex()) |> validate_length(:bio, max: bio_limit) @@ -355,15 +405,27 @@ defmodule Pleroma.User do :follower_address, :following_address, :avatar, - :last_refreshed_at - ] ++ @info_fields + :last_refreshed_at, + :ap_enabled, + :source_data, + :banner, + :locked, + :magic_key, + :follower_count, + :following_count, + :hide_follows, + :fields, + :hide_followers, + :discoverable, + :hide_followers_count, + :hide_follows_count + ] ) |> unique_constraint(:nickname) |> validate_format(:nickname, local_nickname_regex()) |> validate_length(:bio, max: bio_limit) |> validate_length(:name, max: name_limit) |> validate_fields(remote?) - |> change_info(& &1) end def password_update_changeset(struct, params) do @@ -426,7 +488,6 @@ defmodule Pleroma.User do |> validate_format(:email, @email_regex) |> validate_length(:bio, max: bio_limit) |> validate_length(:name, min: 1, max: name_limit) - |> change_info(& &1) |> maybe_validate_required_email(opts[:external]) |> put_password_hash |> put_ap_id() @@ -884,7 +945,9 @@ defmodule Pleroma.User do ) |> Repo.one() - update_and_set_cache(user, %{note_count: note_count}) + user + |> cast(%{note_count: note_count}, [:note_count]) + |> update_and_set_cache() end @spec maybe_fetch_follow_information(User.t()) :: User.t() @@ -1023,11 +1086,11 @@ defmodule Pleroma.User do @spec mute(User.t(), User.t(), boolean()) :: {:ok, User.t()} | {:error, String.t()} def mute(muter, %User{ap_id: ap_id}, notifications? \\ true) do - update_info(muter, &User.Info.add_to_mutes(&1, ap_id, notifications?)) + add_to_mutes(muter, ap_id, notifications?) end def unmute(muter, %{ap_id: ap_id}) do - update_info(muter, &User.Info.remove_from_mutes(&1, ap_id)) + remove_from_mutes(muter, ap_id) end def subscribe(subscriber, %{ap_id: ap_id}) do @@ -1077,7 +1140,7 @@ defmodule Pleroma.User do {:ok, blocker} = update_follower_count(blocker) - update_info(blocker, &User.Info.add_to_block(&1, ap_id)) + add_to_block(blocker, ap_id) end # helper to handle the block given only an actor's AP id @@ -1086,17 +1149,17 @@ defmodule Pleroma.User do end def unblock(blocker, %{ap_id: ap_id}) do - update_info(blocker, &User.Info.remove_from_block(&1, ap_id)) + remove_from_block(blocker, ap_id) end def mutes?(nil, _), do: false - def mutes?(user, %{ap_id: ap_id}), do: Enum.member?(user.info.mutes, ap_id) + def mutes?(user, %{ap_id: ap_id}), do: Enum.member?(user.mutes, ap_id) @spec muted_notifications?(User.t() | nil, User.t() | map()) :: boolean() def muted_notifications?(nil, _), do: false def muted_notifications?(user, %{ap_id: ap_id}), - do: Enum.member?(user.info.muted_notifications, ap_id) + do: Enum.member?(user.muted_notifications, ap_id) def blocks?(%User{} = user, %User{} = target) do blocks_ap_id?(user, target) || blocks_domain?(user, target) @@ -1105,13 +1168,13 @@ defmodule Pleroma.User do def blocks?(nil, _), do: false def blocks_ap_id?(%User{} = user, %User{} = target) do - Enum.member?(user.info.blocks, target.ap_id) + Enum.member?(user.blocks, target.ap_id) end def blocks_ap_id?(_, _), do: false def blocks_domain?(%User{} = user, %User{} = target) do - domain_blocks = Pleroma.Web.ActivityPub.MRF.subdomains_regex(user.info.domain_blocks) + domain_blocks = Pleroma.Web.ActivityPub.MRF.subdomains_regex(user.domain_blocks) %{host: host} = URI.parse(target.ap_id) Pleroma.Web.ActivityPub.MRF.subdomain_match?(domain_blocks, host) end @@ -1126,13 +1189,13 @@ defmodule Pleroma.User do @spec muted_users(User.t()) :: [User.t()] def muted_users(user) do - User.Query.build(%{ap_id: user.info.mutes, deactivated: false}) + User.Query.build(%{ap_id: user.mutes, deactivated: false}) |> Repo.all() end @spec blocked_users(User.t()) :: [User.t()] def blocked_users(user) do - User.Query.build(%{ap_id: user.info.blocks, deactivated: false}) + User.Query.build(%{ap_id: user.blocks, deactivated: false}) |> Repo.all() end @@ -1142,14 +1205,6 @@ defmodule Pleroma.User do |> Repo.all() end - def block_domain(user, domain) do - update_info(user, &User.Info.add_to_domain_block(&1, domain)) - end - - def unblock_domain(user, domain) do - update_info(user, &User.Info.remove_from_domain_block(&1, domain)) - end - def deactivate_async(user, status \\ true) do BackgroundWorker.enqueue("deactivate_user", %{"user_id" => user.id, "status" => status}) end @@ -1385,7 +1440,7 @@ defmodule Pleroma.User do else _ -> {:ok, user} = - %User{info: %User.Info{}} + %User{} |> cast(%{}, [:ap_id, :nickname, :local]) |> put_change(:ap_id, uri) |> put_change(:nickname, nickname) @@ -1549,7 +1604,6 @@ defmodule Pleroma.User do %User{ name: ap_id, ap_id: ap_id, - info: %User.Info{}, nickname: "erroruser@example.com", inserted_at: NaiveDateTime.utc_now() } @@ -1562,7 +1616,7 @@ defmodule Pleroma.User do end def showing_reblogs?(%User{} = user, %User{} = target) do - target.ap_id not in user.info.muted_reblogs + target.ap_id not in user.muted_reblogs end @doc """ @@ -1741,28 +1795,6 @@ defmodule Pleroma.User do |> update_and_set_cache() end - @doc """ - Changes `user.info` and returns the user changeset. - - `fun` is called with the `user.info`. - """ - def change_info(user, fun) do - changeset = change(user) - info = get_field(changeset, :info) || %User.Info{} - put_embed(changeset, :info, fun.(info)) - end - - @doc """ - Updates `user.info` and sets cache. - - `fun` is called with the `user.info`. - """ - def update_info(user, fun) do - user - |> change_info(fun) - |> update_and_set_cache() - end - def roles(%{is_moderator: is_moderator, is_admin: is_admin}) do %{ admin: is_admin, @@ -1918,4 +1950,96 @@ defmodule Pleroma.User do def remove_from_subscribers(user, subscribed) do set_subscribers(user, List.delete(user.subscribers, subscribed)) end + + defp set_domain_blocks(user, domain_blocks) do + params = %{domain_blocks: domain_blocks} + + user + |> cast(params, [:domain_blocks]) + |> validate_required([:domain_blocks]) + |> update_and_set_cache() + end + + def block_domain(user, domain_blocked) do + set_domain_blocks(user, Enum.uniq([domain_blocked | user.domain_blocks])) + end + + def unblock_domain(user, domain_blocked) do + set_domain_blocks(user, List.delete(user.domain_blocks, domain_blocked)) + end + + defp set_blocks(user, blocks) do + params = %{blocks: blocks} + + user + |> cast(params, [:blocks]) + |> validate_required([:blocks]) + |> update_and_set_cache() + end + + def add_to_block(user, blocked) do + set_blocks(user, Enum.uniq([blocked | user.blocks])) + end + + def remove_from_block(user, blocked) do + set_blocks(user, List.delete(user.blocks, blocked)) + end + + defp set_mutes(user, mutes) do + params = %{mutes: mutes} + + user + |> cast(params, [:mutes]) + |> validate_required([:mutes]) + |> update_and_set_cache() + end + + def add_to_mutes(user, muted, notifications?) do + with {:ok, user} <- set_mutes(user, Enum.uniq([muted | user.mutes])) do + set_notification_mutes( + user, + Enum.uniq([muted | user.muted_notifications]), + notifications? + ) + end + end + + def remove_from_mutes(user, muted) do + with {:ok, user} <- set_mutes(user, List.delete(user.mutes, muted)) do + set_notification_mutes( + user, + List.delete(user.muted_notifications, muted), + true + ) + end + end + + defp set_notification_mutes(user, _muted_notifications, _notifications? = false) do + {:ok, user} + end + + defp set_notification_mutes(user, muted_notifications, _notifications? = true) do + params = %{muted_notifications: muted_notifications} + + user + |> cast(params, [:muted_notifications]) + |> validate_required([:muted_notifications]) + |> update_and_set_cache() + end + + def add_reblog_mute(user, ap_id) do + params = %{muted_reblogs: user.muted_reblogs ++ [ap_id]} + + user + |> cast(params, [:muted_reblogs]) + |> update_and_set_cache() + end + + def remove_reblog_mute(user, ap_id) do + params = %{muted_reblogs: List.delete(user.muted_reblogs, ap_id)} + + user + |> cast(params, [:muted_reblogs]) + |> update_and_set_cache() + end end diff --git a/lib/pleroma/user/info.ex b/lib/pleroma/user/info.ex deleted file mode 100644 index fe59ddeab..000000000 --- a/lib/pleroma/user/info.ex +++ /dev/null @@ -1,107 +0,0 @@ -# Pleroma: A lightweight social networking server -# Copyright © 2017-2019 Pleroma Authors -# SPDX-License-Identifier: AGPL-3.0-only - -defmodule Pleroma.User.Info do - use Ecto.Schema - import Ecto.Changeset - - alias Pleroma.User.Info - - @type t :: %__MODULE__{} - - embedded_schema do - field(:blocks, {:array, :string}, default: []) - field(:domain_blocks, {:array, :string}, default: []) - field(:mutes, {:array, :string}, default: []) - field(:muted_reblogs, {:array, :string}, default: []) - field(:muted_notifications, {:array, :string}, default: []) - - # Found in the wild - # ap_id -> Where is this used? - # bio -> Where is this used? - # avatar -> Where is this used? - # fqn -> Where is this used? - # host -> Where is this used? - # subject _> Where is this used? - end - - def set_mutes(info, mutes) do - params = %{mutes: mutes} - - info - |> cast(params, [:mutes]) - |> validate_required([:mutes]) - end - - @spec set_notification_mutes(Changeset.t(), [String.t()], boolean()) :: Changeset.t() - def set_notification_mutes(changeset, muted_notifications, notifications?) do - if notifications? do - put_change(changeset, :muted_notifications, muted_notifications) - |> validate_required([:muted_notifications]) - else - changeset - end - end - - def set_blocks(info, blocks) do - params = %{blocks: blocks} - - info - |> cast(params, [:blocks]) - |> validate_required([:blocks]) - end - - @spec add_to_mutes(Info.t(), String.t(), boolean()) :: Changeset.t() - def add_to_mutes(info, muted, notifications?) do - info - |> set_mutes(Enum.uniq([muted | info.mutes])) - |> set_notification_mutes( - Enum.uniq([muted | info.muted_notifications]), - notifications? - ) - end - - @spec remove_from_mutes(Info.t(), String.t()) :: Changeset.t() - def remove_from_mutes(info, muted) do - info - |> set_mutes(List.delete(info.mutes, muted)) - |> set_notification_mutes(List.delete(info.muted_notifications, muted), true) - end - - def add_to_block(info, blocked) do - set_blocks(info, Enum.uniq([blocked | info.blocks])) - end - - def remove_from_block(info, blocked) do - set_blocks(info, List.delete(info.blocks, blocked)) - end - - def set_domain_blocks(info, domain_blocks) do - params = %{domain_blocks: domain_blocks} - - info - |> cast(params, [:domain_blocks]) - |> validate_required([:domain_blocks]) - end - - def add_to_domain_block(info, domain_blocked) do - set_domain_blocks(info, Enum.uniq([domain_blocked | info.domain_blocks])) - end - - def remove_from_domain_block(info, domain_blocked) do - set_domain_blocks(info, List.delete(info.domain_blocks, domain_blocked)) - end - - def add_reblog_mute(info, ap_id) do - params = %{muted_reblogs: info.muted_reblogs ++ [ap_id]} - - cast(info, params, [:muted_reblogs]) - end - - def remove_reblog_mute(info, ap_id) do - params = %{muted_reblogs: List.delete(info.muted_reblogs, ap_id)} - - cast(info, params, [:muted_reblogs]) - end -end diff --git a/lib/pleroma/user/search.ex b/lib/pleroma/user/search.ex index 6fb2c2352..7fffb1e55 100644 --- a/lib/pleroma/user/search.ex +++ b/lib/pleroma/user/search.ex @@ -68,14 +68,14 @@ defmodule Pleroma.User.Search do defp base_query(_user, false), do: User defp base_query(user, true), do: User.get_followers_query(user) - defp filter_blocked_user(query, %User{info: %{blocks: blocks}}) + defp filter_blocked_user(query, %User{blocks: blocks}) when length(blocks) > 0 do from(q in query, where: not (q.ap_id in ^blocks)) end defp filter_blocked_user(query, _), do: query - defp filter_blocked_domains(query, %User{info: %{domain_blocks: domain_blocks}}) + defp filter_blocked_domains(query, %User{domain_blocks: domain_blocks}) when length(domain_blocks) > 0 do domains = Enum.join(domain_blocks, ",") diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 78efaae2a..b9e88ec70 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -235,8 +235,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do {:fake, false, activity} <- {:fake, fake, activity}, _ <- increase_replies_count_if_reply(create_data), _ <- increase_poll_votes_if_vote(create_data), - # Changing note count prior to enqueuing federation task in order to avoid - # race conditions on updating user.info {:ok, _actor} <- increase_note_count_if_public(actor, activity), :ok <- maybe_federate(activity) do {:ok, activity} @@ -429,8 +427,6 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do {:ok, activity} <- insert(data, local, false), stream_out_participations(object, user), _ <- decrease_replies_count_if_reply(object), - # Changing note count prior to enqueuing federation task in order to avoid - # race conditions on updating user.info {:ok, _actor} <- decrease_note_count_if_public(user, object), :ok <- maybe_federate(activity) do {:ok, activity} @@ -800,8 +796,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_muted(query, %{"with_muted" => val}) when val in [true, "true", "1"], do: query - defp restrict_muted(query, %{"muting_user" => %User{info: info}} = opts) do - mutes = info.mutes + defp restrict_muted(query, %{"muting_user" => %User{} = user} = opts) do + mutes = user.mutes query = from([activity] in query, @@ -818,9 +814,9 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_muted(query, _), do: query - defp restrict_blocked(query, %{"blocking_user" => %User{info: info}}) do - blocks = info.blocks || [] - domain_blocks = info.domain_blocks || [] + defp restrict_blocked(query, %{"blocking_user" => %User{} = user}) do + blocks = user.blocks || [] + domain_blocks = user.domain_blocks || [] query = if has_named_binding?(query, :object), do: query, else: Activity.with_joined_object(query) @@ -861,8 +857,8 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do defp restrict_pinned(query, _), do: query - defp restrict_muted_reblogs(query, %{"muting_user" => %User{info: info}}) do - muted_reblogs = info.muted_reblogs || [] + defp restrict_muted_reblogs(query, %{"muting_user" => %User{} = user}) do + muted_reblogs = user.muted_reblogs || [] from( activity in query, diff --git a/lib/pleroma/web/common_api/common_api.ex b/lib/pleroma/web/common_api/common_api.ex index ef738a870..449b808b5 100644 --- a/lib/pleroma/web/common_api/common_api.ex +++ b/lib/pleroma/web/common_api/common_api.ex @@ -392,14 +392,14 @@ defmodule Pleroma.Web.CommonAPI do defp set_visibility(activity, _), do: {:ok, activity} def hide_reblogs(user, %{ap_id: ap_id} = _muted) do - if ap_id not in user.info.muted_reblogs do - User.update_info(user, &User.Info.add_reblog_mute(&1, ap_id)) + if ap_id not in user.muted_reblogs do + User.add_reblog_mute(user, ap_id) end end def show_reblogs(user, %{ap_id: ap_id} = _muted) do - if ap_id in user.info.muted_reblogs do - User.update_info(user, &User.Info.remove_reblog_mute(&1, ap_id)) + if ap_id in user.muted_reblogs do + User.remove_reblog_mute(user, ap_id) end end end diff --git a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex index 7ba2f9ff1..73fad519e 100644 --- a/lib/pleroma/web/mastodon_api/controllers/account_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/account_controller.ex @@ -197,11 +197,7 @@ defmodule Pleroma.Web.MastodonAPI.AccountController do |> Enum.dedup() user_params = Map.put(user_params, :emoji, user_emojis) - - changeset = - user - |> User.update_changeset(user_params) - |> User.change_info(& &1) + changeset = User.update_changeset(user, user_params) with {:ok, user} <- User.update_and_set_cache(changeset) do if original_user != user, do: CommonAPI.update(user) diff --git a/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex b/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex index c7606246b..456fe7ab2 100644 --- a/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex +++ b/lib/pleroma/web/mastodon_api/controllers/domain_block_controller.ex @@ -21,8 +21,8 @@ defmodule Pleroma.Web.MastodonAPI.DomainBlockController do plug(Pleroma.Plugs.EnsurePublicOrAuthenticatedPlug) @doc "GET /api/v1/domain_blocks" - def index(%{assigns: %{user: %{info: info}}} = conn, _) do - json(conn, Map.get(info, :domain_blocks, [])) + def index(%{assigns: %{user: user}} = conn, _) do + json(conn, Map.get(user, :domain_blocks, [])) end @doc "POST /api/v1/domain_blocks" diff --git a/lib/pleroma/web/streamer/worker.ex b/lib/pleroma/web/streamer/worker.ex index 9910c3484..c2ee9e1f5 100644 --- a/lib/pleroma/web/streamer/worker.ex +++ b/lib/pleroma/web/streamer/worker.ex @@ -129,12 +129,12 @@ defmodule Pleroma.Web.Streamer.Worker do end defp should_send?(%User{} = user, %Activity{} = item) do - blocks = user.info.blocks || [] - mutes = user.info.mutes || [] - reblog_mutes = user.info.muted_reblogs || [] + blocks = user.blocks || [] + mutes = user.mutes || [] + reblog_mutes = user.muted_reblogs || [] recipient_blocks = MapSet.new(blocks ++ mutes) recipients = MapSet.new(item.recipients) - domain_blocks = Pleroma.Web.ActivityPub.MRF.subdomains_regex(user.info.domain_blocks) + domain_blocks = Pleroma.Web.ActivityPub.MRF.subdomains_regex(user.domain_blocks) with parent when not is_nil(parent) <- Object.normalize(item), true <- Enum.all?([blocks, mutes, reblog_mutes], &(item.actor not in &1)), diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index 5eafc01de..39f10c49f 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -23,7 +23,9 @@ defmodule Pleroma.Web.TwitterAPI.Controller do with %User{} = user <- User.get_cached_by_id(uid), true <- user.local and user.confirmation_pending and user.confirmation_token == token, {:ok, _} <- - User.update_and_set_cache(User.confirmation_changeset(user, need_confirmation: false)) do + user + |> User.confirmation_changeset(need_confirmation: false) + |> User.update_and_set_cache() do redirect(conn, to: "/") end end diff --git a/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs b/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs index b26b122eb..6b096a962 100644 --- a/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs +++ b/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs @@ -1,6 +1,98 @@ defmodule Pleroma.Repo.Migrations.CopyUsersInfoaddsToUsers do use Ecto.Migration + @info_fields [ + :banner, + :background, + :source_data, + :note_count, + :follower_count, + :following_count, + :locked, + :confirmation_pending, + :password_reset_pending, + :confirmation_token, + :default_scope, + :blocks, + :domain_blocks, + :mutes, + :muted_reblogs, + :muted_notifications, + :subscribers, + :deactivated, + :no_rich_text, + :ap_enabled, + :is_moderator, + :is_admin, + :show_role, + :settings, + :magic_key, + :uri, + :topic, + :hub, + :salmon, + :hide_followers_count, + :hide_follows_count, + :hide_followers, + :hide_follows, + :hide_favorites, + :unread_conversation_count, + :pinned_activities, + :email_notifications, + :mascot, + :emoji, + :pleroma_settings_store, + :fields, + :raw_fields, + :discoverable, + :skip_thread_containment, + :notification_settings + ] + + @jsonb_fields [ + :banner, + :background, + :source_data, + :settings, + :email_notifications, + :mascot, + :pleroma_settings_store, + :notification_settings + ] + + @array_jsonb_fields [:emoji, :fields, :raw_fields] + + @int_fields [:note_count, :follower_count, :following_count, :unread_conversation_count] + + @boolean_fields [ + :locked, + :confirmation_pending, + :password_reset_pending, + :deactivated, + :no_rich_text, + :ap_enabled, + :is_moderator, + :is_admin, + :show_role, + :hide_followers_count, + :hide_follows_count, + :hide_followers, + :hide_follows, + :hide_favorites, + :discoverable, + :skip_thread_containment + ] + + @array_text_fields [ + :blocks, + :domain_blocks, + :mutes, + :muted_reblogs, + :muted_notifications, + :subscribers, + :pinned_activities + ] + def change do alter table(:users) do add(:banner, :map, default: %{}) @@ -8,11 +100,10 @@ defmodule Pleroma.Repo.Migrations.CopyUsersInfoaddsToUsers do add(:source_data, :map, default: %{}) add(:note_count, :integer, default: 0) add(:follower_count, :integer, default: 0) - # Should be filled in only for remote users add(:following_count, :integer, default: nil) - add(:locked, :boolean, default: false) - add(:confirmation_pending, :boolean, default: false) - add(:password_reset_pending, :boolean, default: false) + add(:locked, :boolean, default: false, null: false) + add(:confirmation_pending, :boolean, default: false, null: false) + add(:password_reset_pending, :boolean, default: false, null: false) add(:confirmation_token, :text, default: nil) add(:default_scope, :string, default: "public") add(:blocks, {:array, :text}, default: []) @@ -50,5 +141,45 @@ defmodule Pleroma.Repo.Migrations.CopyUsersInfoaddsToUsers do add(:notification_settings, :map, default: %{}) add(:skip_thread_containment, :boolean, default: false, null: false) end + + if direction == :up do + for f <- @info_fields do + set_field = "update users set #{f} =" + + cond do + f in @jsonb_fields -> + execute("#{set_field} info->'#{f}'") + + f in @array_jsonb_fields -> + execute("#{set_field} ARRAY(SELECT jsonb_array_elements(info->'#{f}'))") + + f in @int_fields -> + execute("#{set_field} (info->>'#{f}')::int") + + f in @boolean_fields -> + execute("#{set_field} coalesce((info->>'#{f}')::boolean, false)") + + f in @array_text_fields -> + execute("#{set_field} ARRAY(SELECT jsonb_array_elements_text(info->'#{f}'))") + + true -> + execute("#{set_field} info->>'#{f}'") + end + end + + for index_name <- [ + :users_deactivated_index, + :users_is_moderator_index, + :users_is_admin_index, + :users_subscribers_index + ] do + drop_if_exists(index(:users, [], name: index_name)) + end + end + + create_if_not_exists(index(:users, [:deactivated])) + create_if_not_exists(index(:users, [:is_moderator])) + create_if_not_exists(index(:users, [:is_admin])) + create_if_not_exists(index(:users, [:subscribers])) end end diff --git a/test/user_test.exs b/test/user_test.exs index 381d8ea27..d96bc9829 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -1133,11 +1133,9 @@ defmodule Pleroma.UserTest do ap_id: user.ap_id, name: user.name, nickname: user.nickname, - info: %{ - fields: [ - %{"name" => "myfield", "value" => String.duplicate("h", current_max_length + 1)} - ] - } + fields: [ + %{"name" => "myfield", "value" => String.duplicate("h", current_max_length + 1)} + ] } assert {:ok, %User{}} = User.insert_or_update_user(data) From b4cbf0568bd6924ded9b9fbdb588a4da92bf83e7 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Sun, 20 Oct 2019 13:58:27 +0300 Subject: [PATCH 16/28] [#1304] Analysis issue fix. --- lib/pleroma/user.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index d16d22198..282cf6962 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -2014,11 +2014,11 @@ defmodule Pleroma.User do end end - defp set_notification_mutes(user, _muted_notifications, _notifications? = false) do + defp set_notification_mutes(user, _muted_notifications, false = _notifications?) do {:ok, user} end - defp set_notification_mutes(user, muted_notifications, _notifications? = true) do + defp set_notification_mutes(user, muted_notifications, true = _notifications?) do params = %{muted_notifications: muted_notifications} user From ee04fbc35ad56784614c8cdd3f863da284a5725e Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Sun, 20 Oct 2019 22:29:56 +0300 Subject: [PATCH 17/28] [#1304]. Post-merge fixes. Merge branch 'develop' of git.pleroma.social:pleroma/pleroma into 1304-user-info-deprecation # Conflicts: # CHANGELOG.md # lib/pleroma/notification.ex # lib/pleroma/user.ex # lib/pleroma/user/info.ex # lib/pleroma/web/admin_api/admin_api_controller.ex # lib/pleroma/web/ostatus/handlers/follow_handler.ex # lib/pleroma/web/ostatus/ostatus.ex # lib/pleroma/web/salmon/salmon.ex # lib/pleroma/web/websub/websub.ex # test/web/admin_api/admin_api_controller_test.exs # test/web/federator_test.exs # test/web/mastodon_api/controllers/conversation_controller_test.exs # test/web/ostatus/ostatus_controller_test.exs # test/web/ostatus/ostatus_test.exs # test/web/salmon/salmon_test.exs # test/web/websub/websub_test.exs --- docs/API/admin_api.md | 4 +-- lib/pleroma/user.ex | 11 +------ lib/pleroma/web/admin_api/admin_api_controller.ex | 36 ++++++---------------- ...91009154608_copy_users_info_fields_to_users.exs | 6 ---- test/conversation/participation_test.exs | 8 ++--- .../controllers/conversation_controller_test.exs | 4 +-- .../controllers/pleroma_api_controller_test.exs | 4 +-- 7 files changed, 20 insertions(+), 53 deletions(-) diff --git a/docs/API/admin_api.md b/docs/API/admin_api.md index 6faf1786b..e64ae6429 100644 --- a/docs/API/admin_api.md +++ b/docs/API/admin_api.md @@ -180,7 +180,7 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret - `nicknames`: nicknames array - Response: - On failure: `{"error": "…"}` - - On success: JSON of the `user.info` + - On success: JSON of the user ## DEPRECATED `DELETE /api/pleroma/admin/users/:nickname/permission_group/:permission_group` @@ -200,7 +200,7 @@ Note: Available `:permission_group` is currently moderator and admin. 404 is ret - `nicknames`: nicknames array - Response: - On failure: `{"error": "…"}` - - On success: JSON of the `user.info` + - On success: JSON of the user - Note: An admin cannot revoke their own admin status. ## `PATCH /api/pleroma/admin/users/activate` diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index e2ebb7d64..89f88c74d 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -89,9 +89,6 @@ defmodule Pleroma.User do field(:settings, :map, default: nil) field(:magic_key, :string, default: nil) field(:uri, :string, default: nil) - field(:topic, :string, default: nil) - field(:hub, :string, default: nil) - field(:salmon, :string, default: nil) field(:hide_followers_count, :boolean, default: false) field(:hide_follows_count, :boolean, default: false) field(:hide_followers, :boolean, default: false) @@ -250,9 +247,6 @@ defmodule Pleroma.User do :settings, :magic_key, :uri, - :topic, - :hub, - :salmon, :hide_followers_count, :hide_follows_count, :hide_followers, @@ -317,9 +311,6 @@ defmodule Pleroma.User do :locked, :magic_key, :uri, - :hub, - :topic, - :salmon, :hide_followers, :hide_follows, :hide_followers_count, @@ -1453,7 +1444,7 @@ defmodule Pleroma.User do {:ok, key} end - def public_key_from_info(_), do: {:error, "not found key"} + def public_key(_), do: {:error, "not found key"} def get_public_key_for_ap_id(ap_id) do with {:ok, %User{} = user} <- get_or_fetch_by_ap_id(ap_id), diff --git a/lib/pleroma/web/admin_api/admin_api_controller.ex b/lib/pleroma/web/admin_api/admin_api_controller.ex index 66b5276d4..7ffbb23e7 100644 --- a/lib/pleroma/web/admin_api/admin_api_controller.ex +++ b/lib/pleroma/web/admin_api/admin_api_controller.ex @@ -51,8 +51,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do :tag_users, :untag_users, :right_add, - :right_delete, - :set_activation_status + :right_delete ] ) @@ -364,11 +363,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do "nicknames" => nicknames }) when permission_group in ["moderator", "admin"] do - info = Map.put(%{}, "is_" <> permission_group, true) + update = %{:"is_#{permission_group}" => true} users = nicknames |> Enum.map(&User.get_cached_by_nickname/1) - User.update_info(users, &User.Info.admin_api_update(&1, info)) + for u <- users, do: User.admin_api_update(u, update) ModerationLog.insert_log(%{ action: "grant", @@ -377,7 +376,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do permission: permission_group }) - json(conn, info) + json(conn, update) end def right_add_multiple(conn, _) do @@ -429,11 +428,11 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do ) when permission_group in ["moderator", "admin"] do with false <- Enum.member?(nicknames, admin_nickname) do - info = Map.put(%{}, "is_" <> permission_group, false) + update = %{:"is_#{permission_group}" => false} users = nicknames |> Enum.map(&User.get_cached_by_nickname/1) - User.update_info(users, &User.Info.admin_api_update(&1, info)) + for u <- users, do: User.admin_api_update(u, update) ModerationLog.insert_log(%{ action: "revoke", @@ -442,7 +441,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do permission: permission_group }) - json(conn, info) + json(conn, update) else _ -> render_error(conn, :forbidden, "You can't revoke your own admin/moderator status.") end @@ -481,25 +480,6 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do render_error(conn, :forbidden, "You can't revoke your own admin status.") end - def set_activation_status(%{assigns: %{user: admin}} = conn, %{ - "nickname" => nickname, - "status" => status - }) do - with {:ok, status} <- Ecto.Type.cast(:boolean, status), - %User{} = user <- User.get_cached_by_nickname(nickname), - {:ok, _} <- User.deactivate(user, !status) do - action = if(user.deactivated, do: "activate", else: "deactivate") - - ModerationLog.insert_log(%{ - actor: admin, - subject: user, - action: action - }) - - json_response(conn, :no_content, "") - end - end - def relay_list(conn, _params) do with {:ok, list} <- Relay.list() do json(conn, %{relays: list}) @@ -507,6 +487,8 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do _ -> conn |> put_status(500) + end + end def relay_follow(%{assigns: %{user: admin}} = conn, %{"relay_url" => target}) do with {:ok, _message} <- Relay.follow(target) do diff --git a/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs b/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs index 6b096a962..d9df5bb51 100644 --- a/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs +++ b/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs @@ -28,9 +28,6 @@ defmodule Pleroma.Repo.Migrations.CopyUsersInfoaddsToUsers do :settings, :magic_key, :uri, - :topic, - :hub, - :salmon, :hide_followers_count, :hide_follows_count, :hide_followers, @@ -121,9 +118,6 @@ defmodule Pleroma.Repo.Migrations.CopyUsersInfoaddsToUsers do add(:settings, :map, default: nil) add(:magic_key, :text, default: nil) add(:uri, :text, default: nil) - add(:topic, :text, default: nil) - add(:hub, :text, default: nil) - add(:salmon, :text, default: nil) add(:hide_followers_count, :boolean, default: false, null: false) add(:hide_follows_count, :boolean, default: false, null: false) add(:hide_followers, :boolean, default: false, null: false) diff --git a/test/conversation/participation_test.exs b/test/conversation/participation_test.exs index 64c350904..91867bf70 100644 --- a/test/conversation/participation_test.exs +++ b/test/conversation/participation_test.exs @@ -36,8 +36,8 @@ defmodule Pleroma.Conversation.ParticipationTest do [%{read: true}] = Participation.for_user(user) [%{read: false} = participation] = Participation.for_user(other_user) - assert User.get_cached_by_id(user.id).info.unread_conversation_count == 0 - assert User.get_cached_by_id(other_user.id).info.unread_conversation_count == 1 + assert User.get_cached_by_id(user.id).unread_conversation_count == 0 + assert User.get_cached_by_id(other_user.id).unread_conversation_count == 1 {:ok, _} = CommonAPI.post(other_user, %{ @@ -52,8 +52,8 @@ defmodule Pleroma.Conversation.ParticipationTest do [%{read: false}] = Participation.for_user(user) [%{read: true}] = Participation.for_user(other_user) - assert User.get_cached_by_id(user.id).info.unread_conversation_count == 1 - assert User.get_cached_by_id(other_user.id).info.unread_conversation_count == 0 + assert User.get_cached_by_id(user.id).unread_conversation_count == 1 + assert User.get_cached_by_id(other_user.id).unread_conversation_count == 0 end test "for a new conversation, it sets the recipents of the participation" do diff --git a/test/web/mastodon_api/controllers/conversation_controller_test.exs b/test/web/mastodon_api/controllers/conversation_controller_test.exs index b92da665b..542af4944 100644 --- a/test/web/mastodon_api/controllers/conversation_controller_test.exs +++ b/test/web/mastodon_api/controllers/conversation_controller_test.exs @@ -95,8 +95,8 @@ defmodule Pleroma.Web.MastodonAPI.ConversationControllerTest do "visibility" => "direct" }) - assert User.get_cached_by_id(user_one.id).info.unread_conversation_count == 0 - assert User.get_cached_by_id(user_two.id).info.unread_conversation_count == 1 + assert User.get_cached_by_id(user_one.id).unread_conversation_count == 0 + assert User.get_cached_by_id(user_two.id).unread_conversation_count == 1 [%{"id" => direct_conversation_id, "unread" => true}] = conn diff --git a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs index 9cccc8c8a..0c83edb56 100644 --- a/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs +++ b/test/web/pleroma_api/controllers/pleroma_api_controller_test.exs @@ -108,7 +108,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do [participation2, participation1] = Participation.for_user(other_user) assert Participation.get(participation2.id).read == false assert Participation.get(participation1.id).read == false - assert User.get_cached_by_id(other_user.id).info.unread_conversation_count == 2 + assert User.get_cached_by_id(other_user.id).unread_conversation_count == 2 [%{"unread" => false}, %{"unread" => false}] = conn @@ -119,7 +119,7 @@ defmodule Pleroma.Web.PleromaAPI.PleromaAPIControllerTest do [participation2, participation1] = Participation.for_user(other_user) assert Participation.get(participation2.id).read == true assert Participation.get(participation1.id).read == true - assert User.get_cached_by_id(other_user.id).info.unread_conversation_count == 0 + assert User.get_cached_by_id(other_user.id).unread_conversation_count == 0 end describe "POST /api/v1/pleroma/notifications/read" do From 75da202ab74489af15e086f06810e22211d52d33 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Mon, 21 Oct 2019 10:20:28 +0300 Subject: [PATCH 18/28] [#1304] Typo fix. --- .../migrations/20191009154608_copy_users_info_fields_to_users.exs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs b/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs index d9df5bb51..72c852d2b 100644 --- a/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs +++ b/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs @@ -1,4 +1,4 @@ -defmodule Pleroma.Repo.Migrations.CopyUsersInfoaddsToUsers do +defmodule Pleroma.Repo.Migrations.CopyUsersInfoFieldsToUsers do use Ecto.Migration @info_fields [ @@ -136,7 +136,7 @@ defmodule Pleroma.Repo.Migrations.CopyUsersInfoaddsToUsers do add(:skip_thread_containment, :boolean, default: false, null: false) end - if direction == :up do + if direction() == :up do for f <- @info_fields do set_field = "update users set #{f} =" From 31d6ef6f92ff028499faa85945a51fdd6b5fcf89 Mon Sep 17 00:00:00 2001 From: Maksim Pechnikov Date: Mon, 21 Oct 2019 11:53:11 +0300 Subject: [PATCH 19/28] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19cd1e539..d7be06bf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Admin API: `POST/DELETE /api/pleroma/admin/users/:nickname/permission_group/:permission_group` are deprecated in favor of: `POST/DELETE /api/pleroma/admin/users/permission_group/:permission_group` (both accept `nicknames` array), `DELETE /api/pleroma/admin/users` (`nickname` query param or `nickname` sent in JSON body) is deprecated in favor of: `DELETE /api/pleroma/admin/users` (`nicknames` query array param or `nicknames` sent in JSON body). - Admin API: Add `GET /api/pleroma/admin/relay` endpoint - lists all followed relays - Pleroma API: `POST /api/v1/pleroma/conversations/read` to mark all conversations as read +- Mastodon API: Add `/api/v1/markers` for managing timeline read markers ### Changed - **Breaking:** Elixir >=1.8 is now required (was >= 1.7) From 7c7f90bc4f361b8bf4b49790640a4aa490ee619f Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Mon, 21 Oct 2019 11:58:22 +0300 Subject: [PATCH 20/28] [#1304] Merged `develop`, handled User.Info.invisible. --- lib/pleroma/user.ex | 16 ++++++++++++++-- lib/pleroma/web/activity_pub/relay.ex | 2 +- .../20191009154608_copy_users_info_fields_to_users.exs | 3 +++ .../migrations/20191017225002_drop_websub_tables.exs | 4 +++- test/user_test.exs | 2 +- test/web/activity_pub/views/user_view_test.exs | 2 +- 6 files changed, 23 insertions(+), 6 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index 00a1df133..e8038c1c1 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -103,6 +103,7 @@ defmodule Pleroma.User do field(:fields, {:array, :map}, default: nil) field(:raw_fields, {:array, :map}, default: []) field(:discoverable, :boolean, default: false) + field(:invisible, :boolean, default: false) field(:skip_thread_containment, :boolean, default: false) field(:notification_settings, :map, @@ -142,7 +143,7 @@ defmodule Pleroma.User do def superuser?(%User{local: true, is_moderator: true}), do: true def superuser?(_), do: false - def invisible?(%User{info: %User.Info{invisible: true}}), do: true + def invisible?(%User{invisible: true}), do: true def invisible?(_), do: false def avatar_url(user, options \\ []) do @@ -264,6 +265,7 @@ defmodule Pleroma.User do :fields, :raw_fields, :discoverable, + :invisible, :skip_thread_containment, :notification_settings ] @@ -321,7 +323,8 @@ defmodule Pleroma.User do :follower_count, :fields, :following_count, - :discoverable + :discoverable, + :invisible ] ) |> validate_required([:name, :ap_id]) @@ -2021,4 +2024,13 @@ defmodule Pleroma.User do |> cast(params, [:muted_reblogs]) |> update_and_set_cache() end + + def set_invisible(user, invisible) do + params = %{invisible: invisible} + + user + |> cast(params, [:invisible]) + |> validate_required([:invisible]) + |> update_and_set_cache() + end end diff --git a/lib/pleroma/web/activity_pub/relay.ex b/lib/pleroma/web/activity_pub/relay.ex index de80612f1..a9434d75c 100644 --- a/lib/pleroma/web/activity_pub/relay.ex +++ b/lib/pleroma/web/activity_pub/relay.ex @@ -14,7 +14,7 @@ defmodule Pleroma.Web.ActivityPub.Relay do "#{Pleroma.Web.Endpoint.url()}/relay" |> User.get_or_create_service_actor_by_ap_id() - {:ok, actor} = User.update_info(actor, &User.Info.set_invisible(&1, true)) + {:ok, actor} = User.set_invisible(actor, true) actor end diff --git a/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs b/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs index 72c852d2b..87b1e2c8c 100644 --- a/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs +++ b/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs @@ -42,6 +42,7 @@ defmodule Pleroma.Repo.Migrations.CopyUsersInfoFieldsToUsers do :fields, :raw_fields, :discoverable, + :invisible, :skip_thread_containment, :notification_settings ] @@ -77,6 +78,7 @@ defmodule Pleroma.Repo.Migrations.CopyUsersInfoFieldsToUsers do :hide_follows, :hide_favorites, :discoverable, + :invisible, :skip_thread_containment ] @@ -132,6 +134,7 @@ defmodule Pleroma.Repo.Migrations.CopyUsersInfoFieldsToUsers do add(:fields, {:array, :map}, default: nil) add(:raw_fields, {:array, :map}, default: []) add(:discoverable, :boolean, default: false, null: false) + add(:invisible, :boolean, default: false, null: false) add(:notification_settings, :map, default: %{}) add(:skip_thread_containment, :boolean, default: false, null: false) end diff --git a/priv/repo/migrations/20191017225002_drop_websub_tables.exs b/priv/repo/migrations/20191017225002_drop_websub_tables.exs index 9e483b2a1..4cf67a59c 100644 --- a/priv/repo/migrations/20191017225002_drop_websub_tables.exs +++ b/priv/repo/migrations/20191017225002_drop_websub_tables.exs @@ -1,8 +1,10 @@ defmodule Pleroma.Repo.Migrations.DropWebsubTables do use Ecto.Migration - def change do + def up do drop_if_exists(table(:websub_client_subscriptions)) drop_if_exists(table(:websub_server_subscriptions)) end + + def down, do: :noop end diff --git a/test/user_test.exs b/test/user_test.exs index c78e1512a..92de31c74 100644 --- a/test/user_test.exs +++ b/test/user_test.exs @@ -1233,7 +1233,7 @@ defmodule Pleroma.UserTest do describe "invisible?/1" do test "returns true for an invisible user" do - user = insert(:user, local: true, info: %{invisible: true}) + user = insert(:user, local: true, invisible: true) assert User.invisible?(user) end diff --git a/test/web/activity_pub/views/user_view_test.exs b/test/web/activity_pub/views/user_view_test.exs index 392b717b1..3299be2d5 100644 --- a/test/web/activity_pub/views/user_view_test.exs +++ b/test/web/activity_pub/views/user_view_test.exs @@ -75,7 +75,7 @@ defmodule Pleroma.Web.ActivityPub.UserViewTest do end test "renders an invisible user with the invisible property set to true" do - user = insert(:user, %{info: %{invisible: true}}) + user = insert(:user, invisible: true) assert %{"invisible" => true} = UserView.render("service.json", %{user: user}) end From 2dbee29cf5a1a17438e8bc3d2586717da64e20ff Mon Sep 17 00:00:00 2001 From: rinpatch Date: Mon, 21 Oct 2019 12:38:35 +0300 Subject: [PATCH 21/28] Do not include notifications from blocked users when with_muted is set This is not what with_muted is for per documentation and it was agreed on irc that this behavior doesn't make sense. --- lib/pleroma/notification.ex | 15 ++++++++++----- test/notification_test.exs | 12 ++++++------ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index d145f8d5b..e5da1492b 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -55,9 +55,19 @@ defmodule Pleroma.Notification do ) |> preload([n, a, o], activity: {a, object: o}) |> exclude_muted(user, opts) + |> exclude_blocked(user) |> exclude_visibility(opts) end + defp exclude_blocked(query, user) do + query + |> where([n, a], a.actor not in ^user.info.blocks) + |> where( + [n, a], + fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.info.domain_blocks + ) + end + defp exclude_muted(query, _, %{with_muted: true}) do query end @@ -65,11 +75,6 @@ defmodule Pleroma.Notification do defp exclude_muted(query, user, _opts) do query |> where([n, a], a.actor not in ^user.info.muted_notifications) - |> where([n, a], a.actor not in ^user.info.blocks) - |> where( - [n, a], - fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.info.domain_blocks - ) |> join(:left, [n, a], tm in Pleroma.ThreadMute, on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data) ) diff --git a/test/notification_test.exs b/test/notification_test.exs index 54c0f9877..96316f8dd 100644 --- a/test/notification_test.exs +++ b/test/notification_test.exs @@ -683,7 +683,7 @@ defmodule Pleroma.NotificationTest do assert Notification.for_user(user) == [] end - test "it returns notifications for muted user with notifications and with_muted parameter" do + test "it returns notifications from a muted user when with_muted is set" do user = insert(:user) muted = insert(:user) {:ok, user} = User.mute(user, muted) @@ -693,27 +693,27 @@ defmodule Pleroma.NotificationTest do assert length(Notification.for_user(user, %{with_muted: true})) == 1 end - test "it returns notifications for blocked user and with_muted parameter" do + test "it doesn't return notifications from a blocked user when with_muted is set" do user = insert(:user) blocked = insert(:user) {:ok, user} = User.block(user, blocked) {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"}) - assert length(Notification.for_user(user, %{with_muted: true})) == 1 + assert length(Notification.for_user(user, %{with_muted: true})) == 0 end - test "it returns notificatitons for blocked domain and with_muted parameter" do + test "it doesn't return notifications from a domain-blocked user when with_muted is set" do user = insert(:user) blocked = insert(:user, ap_id: "http://some-domain.com") {:ok, user} = User.block_domain(user, "some-domain.com") {:ok, _activity} = CommonAPI.post(blocked, %{"status" => "hey @#{user.nickname}"}) - assert length(Notification.for_user(user, %{with_muted: true})) == 1 + assert length(Notification.for_user(user, %{with_muted: true})) == 0 end - test "it returns notifications for muted thread with_muted parameter" do + test "it returns notifications from muted threads when with_muted is set" do user = insert(:user) another_user = insert(:user) From 2cbb3f236466600db10cb0482e5b2d0ce1f4b945 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Mon, 21 Oct 2019 18:34:20 -0500 Subject: [PATCH 22/28] Add tests for the subject of push notifications --- test/web/push/impl_test.exs | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/test/web/push/impl_test.exs b/test/web/push/impl_test.exs index 2f6ce4bd2..38b16973d 100644 --- a/test/web/push/impl_test.exs +++ b/test/web/push/impl_test.exs @@ -97,7 +97,7 @@ defmodule Pleroma.Web.Push.ImplTest do refute Pleroma.Repo.get(Subscription, subscription.id) end - test "renders body for create activity" do + test "renders title and body for create activity" do user = insert(:user, nickname: "Bob") {:ok, activity} = @@ -116,18 +116,24 @@ defmodule Pleroma.Web.Push.ImplTest do object ) == "@Bob: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce sagittis fini..." + + assert Impl.format_title(%{activity: activity}) == + "New Mention" end - test "renders body for follow activity" do + test "renders title and body for follow activity" do user = insert(:user, nickname: "Bob") other_user = insert(:user) {:ok, _, _, activity} = CommonAPI.follow(user, other_user) object = Object.normalize(activity) assert Impl.format_body(%{activity: activity}, user, object) == "@Bob has followed you" + + assert Impl.format_title(%{activity: activity}) == + "New Follower" end - test "renders body for announce activity" do + test "renders title and body for announce activity" do user = insert(:user) {:ok, activity} = @@ -141,9 +147,12 @@ defmodule Pleroma.Web.Push.ImplTest do assert Impl.format_body(%{activity: announce_activity}, user, object) == "@#{user.nickname} repeated: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce sagittis fini..." + + assert Impl.format_title(%{activity: announce_activity}) == + "New Repeat" end - test "renders body for like activity" do + test "renders title and body for like activity" do user = insert(:user, nickname: "Bob") {:ok, activity} = @@ -156,5 +165,21 @@ defmodule Pleroma.Web.Push.ImplTest do object = Object.normalize(activity) assert Impl.format_body(%{activity: activity}, user, object) == "@Bob has favorited your post" + + assert Impl.format_title(%{activity: activity}) == + "New Favorite" + end + + test "renders title for create activity with direct visibility" do + user = insert(:user, nickname: "Bob") + + {:ok, activity} = + CommonAPI.post(user, %{ + "visibility" => "direct", + "status" => "This is just between you and me, pal" + }) + + assert Impl.format_title(%{activity: activity}) == + "New Direct Message" end end From 0c628fafc56e1b6108660071d39b94f786233391 Mon Sep 17 00:00:00 2001 From: Mark Felder Date: Mon, 21 Oct 2019 18:35:43 -0500 Subject: [PATCH 23/28] Spelling --- test/web/push/impl_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/web/push/impl_test.exs b/test/web/push/impl_test.exs index 38b16973d..9b554601d 100644 --- a/test/web/push/impl_test.exs +++ b/test/web/push/impl_test.exs @@ -84,7 +84,7 @@ defmodule Pleroma.Web.Push.ImplTest do ) == :error end - test "delete subsciption if restult send message between 400..500" do + test "delete subscription if result send message between 400..500" do subscription = insert(:push_subscription) assert Impl.push_message( From 277aea45b9799596c4144b80b9e77e2801d9becd Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 22 Oct 2019 19:43:31 -0500 Subject: [PATCH 24/28] tests: transmogrifier: add explicit regression tests for JSON-LD string to single-element array deserialization There appears to be confusion on whether or not Pleroma can handle this particular sin of JSON-LD. It can, and we will add regression tests to prove that it can handle this particular sin. Which, by the way, this is actually not a "feature" of JSON-LD, but whatever. --- test/web/activity_pub/transmogrifier_test.exs | 44 +++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/test/web/activity_pub/transmogrifier_test.exs b/test/web/activity_pub/transmogrifier_test.exs index dbb6e59b0..77e041b4a 100644 --- a/test/web/activity_pub/transmogrifier_test.exs +++ b/test/web/activity_pub/transmogrifier_test.exs @@ -1106,6 +1106,50 @@ defmodule Pleroma.Web.ActivityPub.TransmogrifierTest do assert activity.data["actor"] == other_user.ap_id assert activity.data["cc"] == [user.ap_id] end + + test "it correctly processes messages with non-array to field" do + user = insert(:user) + + message = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => "https://www.w3.org/ns/activitystreams#Public", + "type" => "Create", + "object" => %{ + "content" => "blah blah blah", + "type" => "Note", + "attributedTo" => user.ap_id, + "inReplyTo" => nil + }, + "actor" => user.ap_id + } + + assert {:ok, activity} = Transmogrifier.handle_incoming(message) + + assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["to"] + end + + test "it correctly processes messages with non-array cc field" do + user = insert(:user) + + message = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "to" => user.follower_address, + "cc" => "https://www.w3.org/ns/activitystreams#Public", + "type" => "Create", + "object" => %{ + "content" => "blah blah blah", + "type" => "Note", + "attributedTo" => user.ap_id, + "inReplyTo" => nil + }, + "actor" => user.ap_id + } + + assert {:ok, activity} = Transmogrifier.handle_incoming(message) + + assert ["https://www.w3.org/ns/activitystreams#Public"] == activity.data["cc"] + assert [user.follower_address] == activity.data["to"] + end end describe "prepare outgoing" do From 3f6a596922fa6839ca26b3136074e4cf054458ad Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 22 Oct 2019 20:50:25 -0500 Subject: [PATCH 25/28] activitypub: visibility: refactor is_public?() to use JSON-LD safe accessors --- lib/pleroma/web/activity_pub/utils.ex | 42 +++++------ lib/pleroma/web/activity_pub/visibility.ex | 3 +- .../activity_pub/activity_pub_controller_test.exs | 81 ++++++++++++++++++++++ 3 files changed, 105 insertions(+), 21 deletions(-) diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index 6b28df92c..699d5162f 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -49,26 +49,28 @@ defmodule Pleroma.Web.ActivityPub.Utils do def determine_explicit_mentions(_), do: [] - @spec recipient_in_collection(any(), any()) :: boolean() - defp recipient_in_collection(ap_id, coll) when is_binary(coll), do: ap_id == coll - defp recipient_in_collection(ap_id, coll) when is_list(coll), do: ap_id in coll - defp recipient_in_collection(_, _), do: false + @spec label_in_collection?(any(), any()) :: boolean() + defp label_in_collection?(ap_id, coll) when is_binary(coll), do: ap_id == coll + defp label_in_collection?(ap_id, coll) when is_list(coll), do: ap_id in coll + defp label_in_collection?(_, _), do: false + + @spec label_in_message?(String.t(), map()) :: boolean() + def label_in_message?(label, params), + do: + [params["to"], params["cc"], params["bto"], params["bcc"]] + |> Enum.any?(&label_in_collection?(label, &1)) + + @spec unaddressed_message?(map()) :: boolean() + def unaddressed_message?(params), + do: + [params["to"], params["cc"], params["bto"], params["bcc"]] + |> Enum.all?(&is_nil(&1)) @spec recipient_in_message(User.t(), User.t(), map()) :: boolean() - def recipient_in_message(%User{ap_id: ap_id} = recipient, %User{} = actor, params) do - addresses = [params["to"], params["cc"], params["bto"], params["bcc"]] - - cond do - Enum.any?(addresses, &recipient_in_collection(ap_id, &1)) -> true - # if the message is unaddressed at all, then assume it is directly addressed - # to the recipient - Enum.all?(addresses, &is_nil(&1)) -> true - # if the message is sent from somebody the user is following, then assume it - # is addressed to the recipient - User.following?(recipient, actor) -> true - true -> false - end - end + def recipient_in_message(%User{ap_id: ap_id} = recipient, %User{} = actor, params), + do: + label_in_message?(ap_id, params) || unaddressed_message?(params) || + User.following?(recipient, actor) defp extract_list(target) when is_binary(target), do: [target] defp extract_list(lst) when is_list(lst), do: lst @@ -76,8 +78,8 @@ defmodule Pleroma.Web.ActivityPub.Utils do def maybe_splice_recipient(ap_id, params) do need_splice? = - !recipient_in_collection(ap_id, params["to"]) && - !recipient_in_collection(ap_id, params["cc"]) + !label_in_collection?(ap_id, params["to"]) && + !label_in_collection?(ap_id, params["cc"]) if need_splice? do cc_list = extract_list(params["cc"]) diff --git a/lib/pleroma/web/activity_pub/visibility.ex b/lib/pleroma/web/activity_pub/visibility.ex index 270d0fa02..f3ab48f7c 100644 --- a/lib/pleroma/web/activity_pub/visibility.ex +++ b/lib/pleroma/web/activity_pub/visibility.ex @@ -7,6 +7,7 @@ defmodule Pleroma.Web.ActivityPub.Visibility do alias Pleroma.Object alias Pleroma.Repo alias Pleroma.User + alias Pleroma.Web.ActivityPub.Utils require Pleroma.Constants @@ -15,7 +16,7 @@ defmodule Pleroma.Web.ActivityPub.Visibility do def is_public?(%Object{data: data}), do: is_public?(data) def is_public?(%Activity{data: data}), do: is_public?(data) def is_public?(%{"directMessage" => true}), do: false - def is_public?(data), do: Pleroma.Constants.as_public() in (data["to"] ++ (data["cc"] || [])) + def is_public?(data), do: Utils.label_in_message?(Pleroma.Constants.as_public(), data) def is_private?(activity) do with false <- is_public?(activity), diff --git a/test/web/activity_pub/activity_pub_controller_test.exs b/test/web/activity_pub/activity_pub_controller_test.exs index 6a3e48b5e..fc0444c32 100644 --- a/test/web/activity_pub/activity_pub_controller_test.exs +++ b/test/web/activity_pub/activity_pub_controller_test.exs @@ -354,6 +354,87 @@ defmodule Pleroma.Web.ActivityPub.ActivityPubControllerTest do assert Activity.get_by_ap_id(data["id"]) end + test "it accepts messages with to as string instead of array", %{conn: conn, data: data} do + user = insert(:user) + + data = + Map.put(data, "to", user.ap_id) + |> Map.delete("cc") + + conn = + conn + |> assign(:valid_signature, true) + |> put_req_header("content-type", "application/activity+json") + |> post("/users/#{user.nickname}/inbox", data) + + assert "ok" == json_response(conn, 200) + ObanHelpers.perform(all_enqueued(worker: ReceiverWorker)) + assert Activity.get_by_ap_id(data["id"]) + end + + test "it accepts messages with cc as string instead of array", %{conn: conn, data: data} do + user = insert(:user) + + data = + Map.put(data, "cc", user.ap_id) + |> Map.delete("to") + + conn = + conn + |> assign(:valid_signature, true) + |> put_req_header("content-type", "application/activity+json") + |> post("/users/#{user.nickname}/inbox", data) + + assert "ok" == json_response(conn, 200) + ObanHelpers.perform(all_enqueued(worker: ReceiverWorker)) + %Activity{} = activity = Activity.get_by_ap_id(data["id"]) + assert user.ap_id in activity.recipients + end + + test "it accepts messages with bcc as string instead of array", %{conn: conn, data: data} do + user = insert(:user) + + data = + Map.put(data, "bcc", user.ap_id) + |> Map.delete("to") + |> Map.delete("cc") + + conn = + conn + |> assign(:valid_signature, true) + |> put_req_header("content-type", "application/activity+json") + |> post("/users/#{user.nickname}/inbox", data) + + assert "ok" == json_response(conn, 200) + ObanHelpers.perform(all_enqueued(worker: ReceiverWorker)) + assert Activity.get_by_ap_id(data["id"]) + end + + test "it accepts announces with to as string instead of array", %{conn: conn} do + user = insert(:user) + + data = %{ + "@context" => "https://www.w3.org/ns/activitystreams", + "actor" => "http://mastodon.example.org/users/admin", + "id" => "http://mastodon.example.org/users/admin/statuses/19512778738411822/activity", + "object" => "https://mastodon.social/users/emelie/statuses/101849165031453009", + "to" => "https://www.w3.org/ns/activitystreams#Public", + "cc" => [user.ap_id], + "type" => "Announce" + } + + conn = + conn + |> assign(:valid_signature, true) + |> put_req_header("content-type", "application/activity+json") + |> post("/users/#{user.nickname}/inbox", data) + + assert "ok" == json_response(conn, 200) + ObanHelpers.perform(all_enqueued(worker: ReceiverWorker)) + %Activity{} = activity = Activity.get_by_ap_id(data["id"]) + assert "https://www.w3.org/ns/activitystreams#Public" in activity.recipients + end + test "it accepts messages from actors that are followed by the user", %{ conn: conn, data: data From 11cd9944258bfc2123b821b21321e12097d0f19b Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Wed, 23 Oct 2019 17:15:48 +0300 Subject: [PATCH 26/28] [#1304] Fixed null::jsonb handling in User.Info migration. --- lib/pleroma/user.ex | 2 +- .../20191009154608_copy_users_info_fields_to_users.exs | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index e8038c1c1..7bef6e281 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -100,7 +100,7 @@ defmodule Pleroma.User do field(:mascot, :map, default: nil) field(:emoji, {:array, :map}, default: []) field(:pleroma_settings_store, :map, default: %{}) - field(:fields, {:array, :map}, default: nil) + field(:fields, {:array, :map}, default: []) field(:raw_fields, {:array, :map}, default: []) field(:discoverable, :boolean, default: false) field(:invisible, :boolean, default: false) diff --git a/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs b/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs index 87b1e2c8c..9dd27511c 100644 --- a/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs +++ b/priv/repo/migrations/20191009154608_copy_users_info_fields_to_users.exs @@ -1,6 +1,8 @@ defmodule Pleroma.Repo.Migrations.CopyUsersInfoFieldsToUsers do use Ecto.Migration + @jsonb_array_default "'[]'::jsonb" + @info_fields [ :banner, :background, @@ -129,10 +131,10 @@ defmodule Pleroma.Repo.Migrations.CopyUsersInfoFieldsToUsers do add(:pinned_activities, {:array, :text}, default: []) add(:email_notifications, :map, default: %{"digest" => false}) add(:mascot, :map, default: nil) - add(:emoji, {:array, :map}, default: []) + add(:emoji, :map, default: fragment(@jsonb_array_default)) add(:pleroma_settings_store, :map, default: %{}) - add(:fields, {:array, :map}, default: nil) - add(:raw_fields, {:array, :map}, default: []) + add(:fields, :map, default: fragment(@jsonb_array_default)) + add(:raw_fields, :map, default: fragment(@jsonb_array_default)) add(:discoverable, :boolean, default: false, null: false) add(:invisible, :boolean, default: false, null: false) add(:notification_settings, :map, default: %{}) @@ -143,12 +145,15 @@ defmodule Pleroma.Repo.Migrations.CopyUsersInfoFieldsToUsers do for f <- @info_fields do set_field = "update users set #{f} =" + # Coercion of null::jsonb to NULL + jsonb = "case when info->>'#{f}' IS NULL then null else info->'#{f}' end" + cond do f in @jsonb_fields -> - execute("#{set_field} info->'#{f}'") + execute("#{set_field} #{jsonb}") f in @array_jsonb_fields -> - execute("#{set_field} ARRAY(SELECT jsonb_array_elements(info->'#{f}'))") + execute("#{set_field} coalesce(#{jsonb}, #{@jsonb_array_default})") f in @int_fields -> execute("#{set_field} (info->>'#{f}')::int") @@ -157,7 +162,7 @@ defmodule Pleroma.Repo.Migrations.CopyUsersInfoFieldsToUsers do execute("#{set_field} coalesce((info->>'#{f}')::boolean, false)") f in @array_text_fields -> - execute("#{set_field} ARRAY(SELECT jsonb_array_elements_text(info->'#{f}'))") + execute("#{set_field} ARRAY(SELECT jsonb_array_elements_text(#{jsonb}))") true -> execute("#{set_field} info->>'#{f}'") From 065e9fac12c1ea06eca2ff55a8253d4bc23362e1 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Wed, 23 Oct 2019 17:31:02 +0300 Subject: [PATCH 27/28] [#1304] Adjusted User.Info references from Notification. --- lib/pleroma/notification.ex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/pleroma/notification.ex b/lib/pleroma/notification.ex index 83844d3be..b7ecf51e4 100644 --- a/lib/pleroma/notification.ex +++ b/lib/pleroma/notification.ex @@ -61,10 +61,10 @@ defmodule Pleroma.Notification do defp exclude_blocked(query, user) do query - |> where([n, a], a.actor not in ^user.info.blocks) + |> where([n, a], a.actor not in ^user.blocks) |> where( [n, a], - fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.info.domain_blocks + fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.domain_blocks ) end From c0246309a5013b17a405644a0918ec0d3569eaf1 Mon Sep 17 00:00:00 2001 From: Ivan Tashkinov Date: Wed, 23 Oct 2019 19:30:02 +0300 Subject: [PATCH 28/28] [#1304] Extra bullet-proofing. --- lib/pleroma/web/activity_pub/activity_pub.ex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 7fc5051ea..07dde3537 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -1164,7 +1164,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do with {:enabled, true} <- {:enabled, Pleroma.Config.get([:instance, :external_user_synchronization])}, {:ok, info} <- fetch_follow_information_for_user(data) do - info = Map.merge(data.info, info) + info = Map.merge(data[:info] || %{}, info) Map.put(data, :info, info) else {:enabled, false} ->