Merge remote-tracking branch 'upstream/develop' into refactor/following-relationships

This commit is contained in:
Egor Kislitsyn 2019-10-24 14:42:14 +07:00
commit 4c1dd55c48
104 changed files with 2081 additions and 1368 deletions

View File

@ -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)
@ -65,6 +66,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Mastodon API: Add `pleroma.direct_conversation_id` to the status endpoint (`GET /api/v1/statuses/:id`)
- Mastodon API: Mark the direct conversation as read for the author when they send a new direct message
</details>
- Deprecated `User.Info` embedded schema (fields moved to `User`)
### Fixed
- Report emails now include functional links to profiles of remote user accounts

View File

@ -170,7 +170,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
## `POST /api/pleroma/admin/users/permission_group/:permission_group`
@ -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`
@ -189,7 +189,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.
## `DELETE /api/pleroma/admin/users/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`

View File

@ -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
@ -109,10 +110,10 @@ def run(["toggle_activated", nickname]) 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 +341,7 @@ def run(["toggle_confirmed", nickname]) 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 +365,32 @@ def run(["sign_out", nickname]) 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
|> Changeset.change(%{is_moderator: value})
|> User.update_and_set_cache()
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
|> Changeset.change(%{is_admin: value})
|> User.update_and_set_cache()
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
|> Changeset.change(%{locked: value})
|> User.update_and_set_cache()
shell_info("Locked status of #{user.nickname}: #{user.info.locked}")
shell_info("Locked status of #{user.nickname}: #{user.locked}")
user
end
end

View File

@ -17,7 +17,7 @@ def perform 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
)

View File

@ -72,7 +72,7 @@ def account_confirmation_email(user) do
Endpoint,
:confirm_email,
user.id,
to_string(user.info.confirmation_token)
to_string(user.confirmation_token)
)
html_body = """

View File

@ -127,7 +127,7 @@ def truncate(text, max_length \\ 200, omission \\ "...") 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)

74
lib/pleroma/marker.ex Normal file
View File

@ -0,0 +1,74 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# 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

View File

@ -40,7 +40,7 @@ def for_user_query(user, opts \\ []) 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
)
)
@ -55,21 +55,26 @@ def for_user_query(user, opts \\ []) 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.blocks)
|> where(
[n, a],
fragment("substring(? from '.*://([^/]*)')", a.actor) not in ^user.domain_blocks
)
end
defp exclude_muted(query, _, %{with_muted: true}) do
query
end
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
)
|> where([n, a], a.actor not in ^user.muted_notifications)
|> join(:left, [n, a], tm in Pleroma.ThreadMute,
on: tm.user_id == ^user.id and tm.context == fragment("?->>'context'", a.data)
)
@ -309,7 +314,7 @@ def skip?(:self, activity, user) 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)
@ -319,14 +324,14 @@ def skip?(
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)
@ -335,7 +340,7 @@ def skip?(:follows, activity, %{info: %{notification_settings: %{"follows" => fa
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)

View File

@ -19,7 +19,7 @@ def call(%{assigns: %{user: %User{}}} = conn, _), do: conn
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

View File

@ -71,7 +71,7 @@ defp fetch_user_and_token(token) 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

View File

@ -10,7 +10,7 @@ def init(options) 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

View File

@ -11,7 +11,7 @@ def init(options) 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

View File

@ -68,12 +68,7 @@ defp get_stat_data 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)

File diff suppressed because it is too large Load Diff

View File

@ -1,472 +0,0 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# 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(: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(: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?
# 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_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}
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
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
|> 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 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}
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 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,
: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]}
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
# ``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

View File

@ -58,7 +58,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()
@ -102,15 +101,19 @@ defp compose_query({:tags, tags}, query) when is_list(tags) and length(tags) > 0
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
@ -119,7 +122,13 @@ defp compose_query({:local, _}, query), do: location_query(query, true)
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
@ -128,7 +137,7 @@ defp compose_query({:deactivated, false}, 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

View File

@ -108,14 +108,14 @@ defp trigram_rank(query, query_string) 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, ",")

View File

@ -69,7 +69,7 @@ defp get_recipients(data) 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
@ -248,8 +248,6 @@ def create(%{to: to, actor: actor, context: context, object: object} = params, f
_ <- increase_replies_count_if_reply(create_data),
_ <- increase_poll_votes_if_vote(create_data),
{:quick_insert, false, activity} <- {:quick_insert, quick_insert?, activity},
# 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}
@ -445,8 +443,6 @@ def delete(%Object{data: %{"id" => id, "actor" => actor}} = object, options \\ [
{: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}
@ -662,7 +658,7 @@ defp restrict_thread_visibility(query, _, %{skip_thread_containment: true} = _),
defp restrict_thread_visibility(
query,
%{"user" => %User{info: %{skip_thread_containment: true}}},
%{"user" => %User{skip_thread_containment: true}},
_
),
do: query
@ -700,7 +696,7 @@ def fetch_user_activities(user, reading_user, params \\ %{}) 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(%{
@ -861,8 +857,8 @@ defp restrict_reblogs(query, _), do: query
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,
@ -879,9 +875,9 @@ defp restrict_muted(query, %{"muting_user" => %User{info: info}} = opts) 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)
@ -922,8 +918,8 @@ defp restrict_pinned(query, %{"pinned" => "true", "pinned_activity_ids" => ids})
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,
@ -1108,17 +1104,17 @@ defp object_to_user_data(data) do
locked = data["manuallyApprovesFollowers"] || false
data = Transmogrifier.maybe_fix_user_object(data)
discoverable = data["discoverable"] || false
invisible = data["invisible"] || false
user_data = %{
ap_id: data["id"],
info: %{
ap_enabled: true,
source_data: data,
banner: banner,
fields: fields,
locked: locked,
discoverable: discoverable
},
discoverable: discoverable,
invisible: invisible,
avatar: avatar,
name: data["name"],
follower_address: data["followers"],
@ -1170,7 +1166,7 @@ defp maybe_update_follow_information(data) 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} ->

View File

@ -137,7 +137,7 @@ def following(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname, "p
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 @@ def followers(%{assigns: %{user: for_user}} = conn, %{"nickname" => nickname, "p
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 @@ def handle_user_activity(user, %{"type" => "Create"} = params) 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

View File

@ -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?

View File

@ -140,7 +140,7 @@ defp get_cc_ap_ids(ap_id, recipients) 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 @@ defp maybe_use_sharedinbox(%User{info: %{source_data: data}}),
"""
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 @@ def publish(%User{} = actor, %{data: %{"bcc" => bcc}} = activity)
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.

View File

@ -10,8 +10,12 @@ defmodule Pleroma.Web.ActivityPub.Relay do
require Logger
def get_actor do
actor =
"#{Pleroma.Web.Endpoint.url()}/relay"
|> User.get_or_create_service_actor_by_ap_id()
{:ok, actor} = User.set_invisible(actor, true)
actor
end
@spec follow(String.t()) :: {:ok, Activity.t()} | {:error, any()}

View File

@ -599,13 +599,18 @@ def handle_incoming(
data,
_options
)
when object_type in ["Person", "Application", "Service", "Organization"] do
when object_type in [
"Person",
"Application",
"Service",
"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)
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"]) || []
invisible = new_user_data[:invisible] || false
fields =
attachment
@ -614,8 +619,10 @@ def handle_incoming(
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)
|> Map.put(:invisible, invisible)
actor
|> User.upgrade_changeset(update_data, true)
@ -982,7 +989,7 @@ defp build_mention_tag(%{ap_id: ap_id, nickname: nickname} = _) 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)

View File

@ -49,26 +49,28 @@ def determine_explicit_mentions(%{"tag" => tag} = object) when is_map(tag) 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 @@ defp extract_list(_), 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"])
@ -491,11 +493,15 @@ def add_announce_to_object(
%Activity{data: %{"actor" => actor}},
object
) do
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)
end
else
{:ok, object}
end
end
def add_announce_to_object(_, object), do: {:ok, object}

View File

@ -55,7 +55,8 @@ def render("service.json", %{user: user}) do
"owner" => user.ap_id,
"publicKeyPem" => public_key
},
"endpoints" => endpoints
"endpoints" => endpoints,
"invisible" => User.invisible?(user)
}
|> Map.merge(Utils.make_json_ld_header())
end
@ -78,8 +79,8 @@ def render("user.json", %{user: user}) 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 +100,7 @@ def render("user.json", %{user: user}) 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 +108,8 @@ def render("user.json", %{user: user}) 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 +117,8 @@ def render("user.json", %{user: user}) 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 +136,8 @@ def render("following.json", %{user: user, page: page} = opts) 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 +156,7 @@ def render("following.json", %{user: user} = opts) 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 +165,8 @@ def render("following.json", %{user: user} = opts) 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 +184,8 @@ def render("followers.json", %{user: user, page: page} = opts) 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])

View File

@ -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 @@ def is_public?(%Object{data: %{"type" => "Tombstone"}}), do: false
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),

View File

@ -51,8 +51,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIController do
:tag_users,
:untag_users,
:right_add,
:right_delete,
:set_activation_status
:right_delete
]
)
@ -250,9 +249,9 @@ def list_user_statuses(conn, %{"nickname" => nickname} = params) 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,
@ -364,11 +363,11 @@ def right_add_multiple(%{assigns: %{user: admin}} = conn, %{
"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 @@ def right_add_multiple(%{assigns: %{user: admin}} = conn, %{
permission: permission_group
})
json(conn, info)
json(conn, update)
end
def right_add_multiple(conn, _) do
@ -389,12 +388,12 @@ def right_add(%{assigns: %{user: admin}} = conn, %{
"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",
@ -403,7 +402,7 @@ def right_add(%{assigns: %{user: admin}} = conn, %{
permission: permission_group
})
json(conn, info)
json(conn, fields)
end
def right_add(conn, _) do
@ -415,8 +414,8 @@ def right_get(conn, %{"nickname" => nickname}) 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
@ -429,11 +428,11 @@ def right_delete_multiple(
)
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 @@ def right_delete_multiple(
permission: permission_group
})
json(conn, info)
json(conn, update)
else
_ -> render_error(conn, :forbidden, "You can't revoke your own admin/moderator status.")
end
@ -460,12 +459,12 @@ def right_delete(
}
)
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",
@ -474,7 +473,7 @@ def right_delete(
permission: permission_group
})
json(conn, info)
json(conn, fields)
end
def right_delete(%{assigns: %{user: %{nickname: nickname}}} = conn, %{"nickname" => nickname}) do

View File

@ -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
@ -34,9 +33,9 @@ def render("show.json", %{user: user}) 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

View File

@ -266,10 +266,10 @@ defp maybe_create_activity_expiration(result, _), do: result
# 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
@ -290,20 +290,20 @@ def pin(id_or_ap_id, %{ap_id: user_ap_id} = user) 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
@ -395,14 +395,14 @@ defp set_visibility(activity, %{"visibility" => visibility}) 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

View File

@ -42,7 +42,7 @@ def manifest(conn, _params) 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 ->

View File

@ -130,25 +130,6 @@ def verify_credentials(%{assigns: %{user: user}} = conn, _) 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 @@ def update_credentials(%{assigns: %{user: original_user}} = conn, params) do
params
end
info_params =
user_params =
[
:no_rich_text,
:locked,
@ -176,15 +157,13 @@ def update_credentials(%{assigns: %{user: original_user}} = conn, params) 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,27 @@ def update_credentials(%{assigns: %{user: original_user}} = conn, params) 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)
changeset =
{: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
|> User.update_changeset(user_params)
|> User.change_info(&User.Info.profile_update(&1, info_params))
|> 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.update_changeset(user, user_params)
with {:ok, user} <- User.update_and_set_cache(changeset) do
if original_user != user, do: CommonAPI.update(user)
@ -269,7 +263,7 @@ def followers(%{assigns: %{user: for_user, account: user}} = conn, params) 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 +277,7 @@ def following(%{assigns: %{user: for_user, account: user}} = conn, params) 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

View File

@ -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"

View File

@ -0,0 +1,32 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# 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

View File

@ -74,23 +74,23 @@ defp do_render("show.json", %{user: user} = opts) 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 @@ defp do_render("show.json", %{user: user} = opts) 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 @@ defp do_render("show.json", %{user: user} = opts) 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 @@ defp do_render("show.json", %{user: user} = opts) do
source: %{
note: HTML.strip_tags((user.bio || "") |> String.replace("<br>", "\n")),
sensitive: false,
fields: raw_fields,
fields: user.raw_fields,
pleroma: %{
discoverable: discoverable
discoverable: user.discoverable
}
},
@ -150,14 +146,14 @@ defp do_render("show.json", %{user: user} = opts) 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 @@ defp maybe_put_settings(
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 @@ defp maybe_put_chat_token(data, %User{id: id}, %User{id: id}, %{
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 @@ defp maybe_put_unread_conversation_count(data, %User{id: user_id} = user, %User{
data
|> Kernel.put_in(
[:pleroma, :unread_conversation_count],
user.info.unread_conversation_count
user.unread_conversation_count
)
end

View File

@ -0,0 +1,17 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# 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

View File

@ -498,6 +498,6 @@ defp present?(nil), do: false
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

View File

@ -202,9 +202,9 @@ def token_exchange(
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

View File

@ -80,9 +80,7 @@ def update_avatar(%{assigns: %{user: user}} = conn, params) 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 @@ def update_banner(%{assigns: %{user: user}} = conn, %{"banner" => ""}) 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 @@ def update_banner(%{assigns: %{user: user}} = conn, params) 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 @@ def update_background(%{assigns: %{user: user}} = conn, params) 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

View File

@ -24,9 +24,7 @@ def update(%{assigns: %{user: user}} = conn, %{"file" => file}) 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

View File

@ -125,6 +125,10 @@ def format_body(
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"

View File

@ -405,6 +405,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

View File

@ -129,12 +129,12 @@ defp do_stream(%{topic: topic, item: item}) 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)),
@ -212,7 +212,7 @@ def push_to_socket(topics, topic, item) 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

View File

@ -20,11 +20,12 @@ 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
|> User.confirmation_changeset(need_confirmation: false)
|> User.update_and_set_cache() do
redirect(conn, to: "/")
end
end

View File

@ -61,12 +61,12 @@ def initial_state(token, user, custom_emojis) 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 @@ def initial_state(token, user, custom_emojis) 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),

View File

@ -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)

View File

@ -1,6 +1,5 @@
defmodule Pleroma.Repo.Migrations.CopyMutedToMutedNotifications do
use Ecto.Migration
alias Pleroma.User
def change do
execute(

View File

@ -0,0 +1,187 @@
defmodule Pleroma.Repo.Migrations.CopyUsersInfoFieldsToUsers do
use Ecto.Migration
@jsonb_array_default "'[]'::jsonb"
@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,
: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,
:invisible,
: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,
:invisible,
: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: %{})
add(:background, :map, default: %{})
add(:source_data, :map, default: %{})
add(:note_count, :integer, default: 0)
add(:follower_count, :integer, default: 0)
add(:following_count, :integer, default: nil)
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: [])
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(: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, :map, default: fragment(@jsonb_array_default))
add(:pleroma_settings_store, :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: %{})
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} ="
# 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} #{jsonb}")
f in @array_jsonb_fields ->
execute("#{set_field} coalesce(#{jsonb}, #{@jsonb_array_default})")
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(#{jsonb}))")
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

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -36,8 +36,8 @@ test "for a new conversation or a reply, it doesn't mark the author's participat
[%{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 @@ test "for a new conversation or a reply, it doesn't mark the author's participat
[%{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

View File

@ -20,7 +20,7 @@ test "it sends digest emails" 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()

View File

@ -36,7 +36,7 @@ test "build user invitation email" 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}]

View File

@ -0,0 +1,55 @@
{
"@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": 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",
"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"
}
}

View File

@ -125,10 +125,10 @@ test "gives a replacement for user links, using local nicknames in user links te
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"})

51
test/marker_test.exs Normal file
View File

@ -0,0 +1,51 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# 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

View File

@ -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)

View File

@ -136,7 +136,7 @@ test "it creates a notification for an activity from a muted thread" 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 @@ test "it disables notifications from followers" 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 @@ test "it disables notifications from people the user follows" 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)
@ -683,7 +683,7 @@ test "it doesn't return notifications for muted thread" 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 @@ test "it returns notifications for muted user with notifications and with_muted
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)

View File

@ -37,6 +37,6 @@ test "with secret set and given in the 'admin_token' parameter, it assigns an ad
%{conn | params: %{"admin_token" => "password123"}}
|> AdminSecretAuthenticationPlug.call(%{})
assert conn.assigns[:user].info.is_admin
assert conn.assigns[:user].is_admin
end
end

View File

@ -17,7 +17,7 @@ test "doesn't do anything if the user isn't set", %{conn: conn} 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

View File

@ -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()

View File

@ -42,7 +42,7 @@ defp make_fake_conn(key_id),
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 @@ test "it returns error when not found user" 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

View File

@ -376,4 +376,13 @@ def config_factory do
)
}
end
def marker_factory do
%Pleroma.Marker{
user: build(:user),
timeline: "notifications",
lock_version: 0,
last_read_id: "1"
}
end
end

View File

@ -348,6 +348,14 @@ def get("http://mastodon.example.org/users/admin", _, _, Accept: "application/ac
}}
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

View File

@ -22,18 +22,18 @@ test "counts statuses" 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

View File

@ -72,26 +72,26 @@ test "it prunes old objects from the database" do
describe "running update_users_following_followers_counts" do
test "following and followers count are updated" do
[user, user2] = insert_pair(:user)
{:ok, %User{info: info} = user} = User.follow(user, user2)
{:ok, %User{} = user} = User.follow(user, user2)
following = User.following(user)
assert length(following) == 2
assert info.follower_count == 0
assert user.follower_count == 0
{:ok, user} =
user
|> User.change_info(&Ecto.Changeset.change(&1, %{follower_count: 3}))
|> Ecto.Changeset.change(%{follower_count: 3})
|> Repo.update()
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(user)) == 2
assert user.info.follower_count == 0
assert user.follower_count == 0
end
end

View File

@ -58,8 +58,8 @@ test "user is created" 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 @@ test "user is deactivated" 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 @@ test "user is activated" 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
@ -156,7 +156,7 @@ test "user is unsubscribed" do
user = User.get_cached_by_nickname(user.nickname)
assert Enum.empty?(User.get_friends(user))
assert user.info.deactivated
assert user.deactivated
end
test "no user to unsubscribe" do
@ -183,13 +183,13 @@ test "All statuses set" 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",
@ -209,9 +209,9 @@ test "All statuses unset" 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
@ -359,28 +359,28 @@ test "it prints an error message when user is not exist" 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

View File

@ -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

View File

@ -68,7 +68,7 @@ test "ap_following returns the following collection for the user" 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 @@ test "returns all pending follow requests" 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)
@ -94,7 +94,7 @@ test "doesn't return already accepted or duplicate follow requests" 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)
@ -150,14 +150,14 @@ test "follow takes a user and another user" 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(user)
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
@ -181,8 +181,8 @@ test "can't subscribe to a user who blocked us" 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)
@ -381,8 +381,8 @@ test "it creates unconfirmed user" 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
@ -391,8 +391,8 @@ test "it creates confirmed user if :confirmed option is given" 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
@ -481,7 +481,8 @@ test "updates an existing user, if stale" 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
@ -587,63 +588,63 @@ test "gets all friends (followed users) for a given user" 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
@ -903,14 +904,14 @@ test "get recipients from activity" 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)
@ -990,7 +991,7 @@ test ".delete_user_activities deletes all create activities", %{user: user} 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)
@ -1081,12 +1082,10 @@ test "with overly long fields" do
ap_id: user.ap_id,
name: user.name,
nickname: user.nickname,
info: %{
fields: [
%{"name" => "myfield", "value" => String.duplicate("h", current_max_length + 1)}
]
}
}
assert {:ok, %User{}} = User.insert_or_update_user(data)
end
@ -1129,7 +1128,7 @@ test "html_filter_policy returns default policies, when rich-text is enabled" 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
@ -1166,8 +1165,8 @@ test "User.delete() plugs any possible zombie objects" 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)
@ -1184,25 +1183,39 @@ test "returns false for unprivileged users" 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
end
describe "invisible?/1" do
test "returns true for an invisible user" do
user = insert(:user, local: true, 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)
@ -1213,14 +1226,14 @@ test "returns true when the account is itself" 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)
@ -1229,8 +1242,8 @@ test "returns true when the account is unauthenticated and auth is not required"
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
@ -1296,7 +1309,7 @@ test "Users are inactive by default" 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 =
@ -1314,7 +1327,7 @@ test "Only includes users who has no recent activity" 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))
@ -1347,7 +1360,7 @@ test "Only includes users with no read notifications" 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
@ -1387,19 +1400,19 @@ test "Only includes users with no read notifications" 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
@ -1435,7 +1448,7 @@ test "it returns a list of AP ids for a given set of nicknames" 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
@ -1554,7 +1567,7 @@ test "updates the counters normally on following/getting a follow when disabled"
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
@ -1577,7 +1590,7 @@ test "syncronizes the counters with the remote instance for the followed when en
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
@ -1600,7 +1613,7 @@ test "syncronizes the counters with the remote instance for the follower when en
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
@ -1640,41 +1653,6 @@ test "changes email", %{user: user} 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])
@ -1731,4 +1709,18 @@ test "allows getting local users by nickname no matter what :limit_to_local_cont
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

View File

@ -354,6 +354,87 @@ test "it inserts an incoming activity into the database", %{conn: conn, data: da
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
@ -683,7 +764,7 @@ test "it returns the followers in a collection", %{conn: conn} 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 +777,7 @@ test "it returns returns a uri if the user has 'hide_followers' set", %{conn: co
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 +789,7 @@ test "it returns a 403 error on pages, if the user has 'hide_followers' set and
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 +845,7 @@ test "it returns the following in a collection", %{conn: conn} 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 +859,7 @@ test "it returns a uri if the user has 'hide_follows' set", %{conn: conn} 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 +871,7 @@ test "it returns a 403 error on pages, if the user has 'hide_follows' set and th
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)

View File

@ -174,11 +174,17 @@ test "it returns a user" 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
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.invisible?(user)
end
test "it fetches the appropriate tag-restricted posts" do
user = insert(:user)
@ -360,7 +366,7 @@ test "does not increase user note count" 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
@ -423,7 +429,7 @@ test "increases user note count only for public activities" 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
@ -1090,7 +1096,7 @@ test "it creates a delete activity and deletes the original object" 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), %{
@ -1122,7 +1128,7 @@ test "decrements user note count only for public activities" 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
@ -1386,9 +1392,9 @@ test "detects hidden followers" 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
@ -1409,9 +1415,9 @@ test "detects hidden follows" 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

View File

@ -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 @@ test "it allows posts without links" 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 @@ test "it disallows posts with links" 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 @@ test "it allows posts without links" 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 @@ test "it allows posts with links" 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 @@ test "it allows posts without links" 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 @@ test "it rejects posts with links" 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

View File

@ -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 @@ test "it returns sharedInbox for messages involving as:Public in to" 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 @@ test "it returns sharedInbox for messages involving as:Public in cc" 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 @@ test "it returns sharedInbox for messages involving multiple recipients in to" d
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 @@ test "it returns sharedInbox for messages involving multiple recipients in cc" d
test "it returns sharedInbox for messages involving multiple recipients in total" do
user =
insert(:user, %{
info: %{
insert(:user,
source_data: %{
"inbox" => "http://example.com/personal-inbox",
"endpoints" => %{"sharedInbox" => "http://example.com/inbox"}
}
}
})
)
user_two = insert(:user)
@ -104,14 +102,12 @@ test "it returns sharedInbox for messages involving multiple recipients in total
test "it returns inbox for messages involving single recipients in total" do
user =
insert(:user, %{
info: %{
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 @@ test "it returns inbox for messages involving single recipients in total" 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 @@ test "it returns inbox for messages involving single recipients in total" 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)

View File

@ -20,6 +20,11 @@ test "gets an actor for the relay" 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 ->

View File

@ -58,7 +58,7 @@ test "it works for incoming follow requests" 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")

View File

@ -145,7 +145,7 @@ test "it works for incoming notices" 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
@ -582,7 +582,7 @@ test "it works for incoming update activities" do
}
]
assert user.info.banner["url"] == [
assert user.banner["url"] == [
%{
"href" =>
"https://cd.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
@ -601,7 +601,7 @@ test "it works with custom profile fields" 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"}
]
@ -622,7 +622,7 @@ test "it works with custom profile fields" 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"}
]
@ -640,7 +640,7 @@ test "it works with custom profile fields" 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"}
]
@ -651,7 +651,7 @@ test "it works with custom profile fields" 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
@ -674,7 +674,7 @@ test "it works for incoming update activities which lock the account" 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
@ -915,7 +915,7 @@ test "it works for incoming accepts which were pre-accepted" 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)
@ -937,7 +937,7 @@ test "it works for incoming accepts which were orphaned" 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)
@ -957,7 +957,7 @@ test "it works for incoming accepts which are referenced by IRI only" 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")
@ -976,7 +976,7 @@ test "it fails for incoming accepts which cannot be correlated" 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")
@ -995,7 +995,7 @@ test "it fails for incoming rejects which cannot be correlated" 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)
@ -1021,7 +1021,7 @@ test "it works for incoming rejects which are orphaned" 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)
@ -1106,6 +1106,50 @@ test "it accepts Flag activities" 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
@ -1298,18 +1342,18 @@ test "it upgrades a user to activitypub" 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
@ -1330,7 +1374,7 @@ test "it upgrades a user to activitypub" do
"https://cdn.niu.moe/accounts/headers/000/033/323/original/850b3448fa5fd477.png"
}
]
} = user.info.banner
} = user.banner
refute "..." in activity.recipients

View File

@ -297,7 +297,7 @@ test "fetches only Create activities" 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 @@ test "updates the state of all Follow activities with the same actor and object"
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)

View File

@ -29,7 +29,7 @@ test "Renders profile fields" 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 @@ test "Renders profile fields" 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 @@ test "Does not add an avatar image if the user hasn't set one" do
user =
insert(:user,
avatar: %{"url" => [%{"href" => "https://someurl"}]},
info: %{
banner: %{"url" => [%{"href" => "https://somebanner"}]}
}
)
{:ok, user} = User.ensure_keys_present(user)
@ -76,6 +74,12 @@ test "Does not add an avatar image if the user hasn't set one" do
assert result["image"]["url"] == "https://somebanner"
end
test "renders an invisible user with the invisible property set to true" do
user = insert(:user, 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)
@ -121,8 +125,7 @@ test "sets totalItems to zero when followers are hidden" 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 +134,7 @@ test "sets correct totalItems when followers are hidden but the follower counter
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 +145,7 @@ test "sets totalItems to zero when follows are hidden" 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 +154,7 @@ test "sets correct totalItems when follows are hidden but the follow counter is
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

View File

@ -25,7 +25,7 @@ defmodule Pleroma.Web.AdminAPI.AdminAPIControllerTest do
describe "DELETE /api/pleroma/admin/users" do
test "single user" do
admin = insert(:user, info: %{is_admin: true})
admin = insert(:user, is_admin: true)
user = insert(:user)
conn =
@ -43,7 +43,7 @@ test "single user" do
end
test "multiple users" do
admin = insert(:user, info: %{is_admin: true})
admin = insert(:user, is_admin: true)
user_one = insert(:user)
user_two = insert(:user)
@ -67,7 +67,7 @@ test "multiple users" do
describe "/api/pleroma/admin/users" do
test "Create" do
admin = insert(:user, info: %{is_admin: true})
admin = insert(:user, is_admin: true)
conn =
build_conn()
@ -97,7 +97,7 @@ test "Create" 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 =
@ -128,7 +128,7 @@ test "Cannot create user with exisiting email" 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 =
@ -159,7 +159,7 @@ test "Cannot create user with exisiting nickname" 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 =
@ -208,7 +208,7 @@ test "Multiple user creation works in transaction" 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 =
@ -231,7 +231,7 @@ test "Show", %{conn: conn} 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 =
@ -245,7 +245,7 @@ test "when the user doesn't exist", %{conn: conn} 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)
@ -271,7 +271,7 @@ test "allows to force-follow another user" 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)
@ -299,7 +299,7 @@ test "allows to force-unfollow another user" 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"]})
@ -348,7 +348,7 @@ test "it does not modify tags of not specified users", %{conn: conn, user3: user
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"]})
@ -397,7 +397,7 @@ test "it does not modify tags of not specified users", %{conn: conn, user3: user
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()
@ -412,7 +412,7 @@ test "GET is giving user_info" 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 =
@ -432,7 +432,7 @@ test "/:right POST, can add to a permission group" do
end
test "/:right POST, can add to a permission group (multiple)" do
admin = insert(:user, info: %{is_admin: true})
admin = insert(:user, is_admin: true)
user_one = insert(:user)
user_two = insert(:user)
@ -455,8 +455,8 @@ test "/:right POST, can add to a permission group (multiple)" 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()
@ -475,9 +475,9 @@ test "/:right DELETE, can remove from a permission group" do
end
test "/:right DELETE, can remove from a permission group (multiple)" do
admin = insert(:user, info: %{is_admin: true})
user_one = insert(:user, info: %{is_admin: true})
user_two = insert(:user, info: %{is_admin: true})
admin = insert(:user, is_admin: true)
user_one = insert(:user, is_admin: true)
user_two = insert(:user, is_admin: true)
conn =
build_conn()
@ -502,7 +502,7 @@ test "/:right DELETE, can remove from a permission group (multiple)" 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
@ -562,7 +562,7 @@ test "it returns 403 if requested by a non-admin", %{conn: conn} 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])
@ -594,7 +594,7 @@ test "it returns 500 if `registrations_open` is enabled", %{conn: conn, user: us
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 =
@ -610,7 +610,7 @@ test "/api/pleroma/admin/users/:nickname/password_reset" 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()
@ -626,7 +626,7 @@ test "renders users array for the first page", %{conn: conn, admin: admin} do
users =
[
%{
"deactivated" => admin.info.deactivated,
"deactivated" => admin.deactivated,
"id" => admin.id,
"nickname" => admin.nickname,
"roles" => %{"admin" => true, "moderator" => false},
@ -636,7 +636,7 @@ test "renders users array for the first page", %{conn: conn, admin: admin} 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},
@ -677,7 +677,7 @@ test "regular search", %{conn: conn} do
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"deactivated" => user.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
@ -701,7 +701,7 @@ test "search by domain", %{conn: conn} do
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"deactivated" => user.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
@ -725,7 +725,7 @@ test "search by full nickname", %{conn: conn} do
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"deactivated" => user.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
@ -749,7 +749,7 @@ test "search by display name", %{conn: conn} do
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"deactivated" => user.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
@ -773,7 +773,7 @@ test "search by email", %{conn: conn} do
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"deactivated" => user.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
@ -797,7 +797,7 @@ test "regular search with page size", %{conn: conn} do
"page_size" => 1,
"users" => [
%{
"deactivated" => user.info.deactivated,
"deactivated" => user.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
@ -816,7 +816,7 @@ test "regular search with page size", %{conn: conn} do
"page_size" => 1,
"users" => [
%{
"deactivated" => user2.info.deactivated,
"deactivated" => user2.deactivated,
"id" => user2.id,
"nickname" => user2.nickname,
"roles" => %{"admin" => false, "moderator" => false},
@ -830,7 +830,7 @@ test "regular search with page size", %{conn: conn} 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)
@ -845,7 +845,7 @@ test "only local users" do
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"deactivated" => user.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
@ -859,7 +859,7 @@ test "only local users" 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)
@ -872,7 +872,7 @@ test "only local users with no query", %{admin: old_admin} do
users =
[
%{
"deactivated" => user.info.deactivated,
"deactivated" => user.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
@ -882,7 +882,7 @@ test "only local users with no query", %{admin: old_admin} 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},
@ -912,7 +912,7 @@ test "only local users with no query", %{admin: old_admin} 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)
@ -951,7 +951,7 @@ test "load only admins", %{conn: conn, admin: admin} 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)
@ -1016,11 +1016,11 @@ test "load users with tags list", %{conn: conn} 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()
@ -1032,7 +1032,7 @@ test "it works with multiple filters" do
"page_size" => 50,
"users" => [
%{
"deactivated" => user.info.deactivated,
"deactivated" => user.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
@ -1047,9 +1047,9 @@ test "it works with multiple filters" do
end
test "PATCH /api/pleroma/admin/users/activate" do
admin = insert(:user, info: %{is_admin: true})
user_one = insert(:user, info: %{deactivated: true})
user_two = insert(:user, info: %{deactivated: true})
admin = insert(:user, is_admin: true)
user_one = insert(:user, deactivated: true)
user_two = insert(:user, deactivated: true)
conn =
build_conn()
@ -1069,9 +1069,9 @@ test "PATCH /api/pleroma/admin/users/activate" do
end
test "PATCH /api/pleroma/admin/users/deactivate" do
admin = insert(:user, info: %{is_admin: true})
user_one = insert(:user, info: %{deactivated: false})
user_two = insert(:user, info: %{deactivated: false})
admin = insert(:user, is_admin: true)
user_one = insert(:user, deactivated: false)
user_two = insert(:user, deactivated: false)
conn =
build_conn()
@ -1091,7 +1091,7 @@ test "PATCH /api/pleroma/admin/users/deactivate" 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 =
@ -1101,7 +1101,7 @@ test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" do
assert json_response(conn, 200) ==
%{
"deactivated" => !user.info.deactivated,
"deactivated" => !user.deactivated,
"id" => user.id,
"nickname" => user.nickname,
"roles" => %{"admin" => false, "moderator" => false},
@ -1119,7 +1119,7 @@ test "PATCH /api/pleroma/admin/users/:nickname/toggle_activation" 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()
@ -1183,7 +1183,7 @@ test "with max use and expires_at", %{conn: conn} 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()
@ -1221,7 +1221,7 @@ test "with invite", %{conn: conn} 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 =
@ -1241,7 +1241,7 @@ test "with token" do
end
test "with invalid token" do
admin = insert(:user, info: %{is_admin: true})
admin = insert(:user, is_admin: true)
conn =
build_conn()
@ -1254,7 +1254,7 @@ test "with invalid token" 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
@ -1287,7 +1287,7 @@ test "returns 404 when report id is invalid", %{conn: conn} 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)
@ -1348,7 +1348,7 @@ test "returns 404 when report is not exist", %{conn: conn} 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
@ -1468,7 +1468,7 @@ test "returns 403 when requested by anonymous" 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
@ -1523,7 +1523,7 @@ test "returns 404 when report id is invalid", %{conn: conn} 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}
@ -1589,7 +1589,7 @@ test "returns 400 when visibility is unknown", %{conn: conn, id: id} 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}
@ -1619,7 +1619,7 @@ test "returns error when status is not exist", %{conn: conn} 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
@ -1656,7 +1656,7 @@ test "with settings in db", %{conn: conn} 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"
@ -2224,7 +2224,7 @@ test "delete part of settings by atom subkeys", %{conn: conn} 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"
@ -2260,7 +2260,7 @@ test "transfer settings to DB and to file", %{conn: conn, admin: admin} 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!()
@ -2317,8 +2317,8 @@ test "returns private statuses with godmode on", %{conn: conn, user: user} 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
@ -2526,14 +2526,14 @@ test "returns log filtered by search", %{conn: conn, moderator: moderator} 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()
@ -2544,13 +2544,13 @@ test "sets password_reset_pending to true", %{admin: admin, user: user} 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
describe "relays" 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

View File

@ -47,9 +47,9 @@ test "it returns local/external users" 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 @@ test "it returns active/deactivated users" 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 @@ test "it return user by full nickname" 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 @@ test "it returns admin user" 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)

View File

@ -49,6 +49,8 @@ test "includes reported statuses" 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:

View File

@ -100,7 +100,7 @@ test "it adds emoji when updating profiles" 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 @@ test "pin status", %{user: user, activity: activity} 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 @@ test "unpin status", %{user: user, activity: activity} 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 @@ test "should unpin when deleting a status", %{user: user, activity: activity} do
user = refresh_record(user)
assert %User{info: %{pinned_activities: []}} = user
assert %User{pinned_activities: []} = user
end
end
@ -468,7 +468,7 @@ test "also unsubscribes a user" 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 @@ test "after acceptance, it sets all existing pending follow request states to 'a
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)

View File

@ -81,14 +81,16 @@ test "it federates only to reachable instances via AP" 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()

View File

@ -23,7 +23,7 @@ test "put settings", %{conn: conn} 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

View File

@ -153,7 +153,7 @@ test "updates the user's skip_thread_containment option", %{conn: conn} 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

View File

@ -269,7 +269,7 @@ test "getting followers", %{conn: conn} 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 =
@ -281,7 +281,7 @@ test "getting followers, hide_followers", %{conn: conn} 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 =
@ -349,7 +349,7 @@ test "getting following", %{conn: conn} 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)
@ -361,7 +361,7 @@ test "getting following, hide_follows", %{conn: conn} 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)
@ -683,7 +683,7 @@ test "Account registration via Application", %{conn: conn} 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
@ -727,7 +727,7 @@ test "rate limit", %{conn: conn} 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 =
@ -812,7 +812,7 @@ test "verify_credentials", %{conn: conn} 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
@ -824,7 +824,7 @@ test "verify_credentials default scope unlisted", %{conn: conn} 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

View File

@ -17,7 +17,7 @@ test "returns a list of conversations", %{conn: conn} 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 @@ test "returns a list of conversations", %{conn: conn} 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 @@ test "returns a list of conversations", %{conn: conn} do
assert is_binary(res_id)
assert unread == false
assert res_last_status["id"] == direct.id
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
end
test "updates the last_status on reply", %{conn: conn} do
@ -95,8 +95,8 @@ test "the user marks a conversation as read", %{conn: conn} 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
@ -110,8 +110,8 @@ test "the user marks a conversation as read", %{conn: conn} 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_two.id).info.unread_conversation_count == 0
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 == 0
# The conversation is marked as unread on reply
{:ok, _} =
@ -127,8 +127,8 @@ test "the user marks a conversation as read", %{conn: conn} 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_two.id).info.unread_conversation_count == 0
assert User.get_cached_by_id(user_one.id).unread_conversation_count == 1
assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0
# A reply doesn't increment the user's unread_conversation_count if the conversation is unread
{:ok, _} =
@ -138,8 +138,8 @@ test "the user marks a conversation as read", %{conn: conn} 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_two.id).info.unread_conversation_count == 0
assert User.get_cached_by_id(user_one.id).unread_conversation_count == 1
assert User.get_cached_by_id(user_two.id).unread_conversation_count == 0
end
test "(vanilla) Mastodon frontend behaviour", %{conn: conn} do

View File

@ -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)
@ -30,7 +30,7 @@ test "/api/v1/follow_requests works" 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)
@ -56,7 +56,7 @@ test "/api/v1/follow_requests/:id/authorize works" 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)

View File

@ -41,20 +41,13 @@ test "get instance stats", %{conn: conn} 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")

View File

@ -0,0 +1,124 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# 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

View File

@ -12,12 +12,16 @@ 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
import Pleroma.Factory
clear_config([:instance, :federating])
clear_config([:instance, :allow_relay])
describe "posting statuses" do
setup do
user = insert(:user)
@ -29,6 +33,34 @@ defmodule Pleroma.Web.MastodonAPI.StatusControllerTest do
[conn: conn]
end
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)
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!"
@ -526,8 +558,8 @@ test "when you didn't create it", %{conn: conn} 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

View File

@ -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

View File

@ -26,12 +26,10 @@ test "Represent a user account" do
user =
insert(:user, %{
info: %{
note_count: 5,
follower_count: 3,
note_count: 5,
source_data: source_data,
background: background_image
},
background: background_image,
nickname: "shp@shitposter.club",
name: ":karjalanpiirakka: shp",
bio: "<script src=\"invalid-html\"></script><span>valid html</span>",
@ -101,7 +99,7 @@ test "Represent the user account for the account owner" do
"non_followers" => true
}
privacy = user.info.default_scope
privacy = user.default_scope
assert %{
pleroma: %{notification_settings: ^notification_settings},
@ -112,7 +110,9 @@ test "Represent the user account for the account owner" 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 @@ test "Represent a Service(bot) account" 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 @@ test "represent a relationship for the user blocking a domain" 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 @@ test "represent a relationship for the user with a pending follow request" 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 @@ test "represent an embedded relationship" 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 @@ test "sanitizes display names" do
describe "hiding follows/following" do
test "shows when follows/followers stats are hidden and sets follow/follower count to 0" do
info = %{
user =
insert(:user, %{
hide_followers: true,
hide_followers_count: true,
hide_follows: true,
hide_follows_count: true
}
user = insert(:user, info: info)
})
other_user = insert(:user)
{:ok, user, other_user, _activity} = CommonAPI.follow(user, other_user)
@ -395,7 +396,7 @@ test "shows when follows/followers stats are hidden and sets follow/follower cou
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 @@ test "shows when follows/followers are hidden" 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 @@ test "shows zero when no follow requests are pending" 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 @@ test "shows non-zero when follow requests are pending" 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 @@ test "decreases when accepting a follow request" 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 @@ test "decreases when rejecting a follow request" 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})

View File

@ -0,0 +1,27 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2019 Pleroma Authors <https://pleroma.social/>
# 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

View File

@ -24,8 +24,8 @@ test "GET /.well-known/nodeinfo", %{conn: conn} 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

View File

@ -780,8 +780,8 @@ test "rejects token exchange for valid credentials belonging to unconfirmed user
{: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 @@ test "rejects token exchange for valid credentials belonging to deactivated user
user =
insert(:user,
password_hash: Comeonin.Pbkdf2.hashpwsalt(password),
info: %{deactivated: true}
deactivated: true
)
app = insert(:oauth_app)
@ -834,7 +834,7 @@ test "rejects token exchange for user with password_reset_pending set to true" d
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"])

View File

@ -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 @@ test "can set profile banner", %{conn: conn} 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 @@ test "can reset profile banner", %{conn: conn} 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 @@ test "background image can be set", %{conn: conn} 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 @@ test "background image can be reset", %{conn: conn} 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 @@ test "returns 403 error when user has hidden own favorites", %{
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 @@ test "hides favorites for new users by default", %{conn: conn, current_user: cur
|> 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

View File

@ -38,7 +38,7 @@ test "shared & non-shared pack information in list_packs is ok" 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 @@ test "downloading shared & unshared packs from another instance via download_fro
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 @@ test "downloading shared & unshared packs from another instance via download_fro
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 @@ test "updating pack files" 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 @@ test "creating and deleting a pack" 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 @@ test "filesystem import" 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)

View File

@ -108,7 +108,7 @@ test "POST /api/v1/pleroma/conversations/read", %{conn: conn} 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 @@ test "POST /api/v1/pleroma/conversations/read", %{conn: conn} 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

View File

@ -84,7 +84,7 @@ test "fail message sending" 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(
@ -97,7 +97,7 @@ test "delete subsciption if restult send message between 400..500" 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 @@ test "renders body for create activity" 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 @@ test "renders body for announce activity" 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 @@ test "renders body for like activity" 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

Some files were not shown because too many files have changed in this diff Show More